summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qpid/doc/book/src/java-broker/MessageStore-Tool.xml150
-rw-r--r--qpid/java/bdbstore/build.xml2
-rw-r--r--qpid/java/bdbstore/jmx/MANIFEST.MF20
-rw-r--r--qpid/java/bdbstore/jmx/build.xml (renamed from qpid/java/broker-plugins/experimental/shutdown/build.xml)20
-rw-r--r--qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java (renamed from qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreManagerMBean.java)30
-rw-r--r--qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java73
-rw-r--r--qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/ManagedBDBHAMessageStore.java (renamed from qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/ManagedBDBHAMessageStore.java)2
-rw-r--r--qpid/java/bdbstore/jmx/src/main/resources/services/org.apache.qpid.server.jmx.MBeanProvider1
-rw-r--r--qpid/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java (renamed from qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java)1
-rw-r--r--qpid/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java (renamed from qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java)1
-rw-r--r--qpid/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java (renamed from qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreManagerMBeanTest.java)12
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java32
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java8
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java45
-rw-r--r--qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java20
-rw-r--r--qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java2
-rw-r--r--qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java6
-rw-r--r--qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java44
-rw-r--r--qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java109
-rw-r--r--qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdbbin1357197 -> 1361990 bytes
-rw-r--r--qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdbbin1357227 -> 1361990 bytes
-rw-r--r--qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdbbin1332881 -> 1333643 bytes
-rw-r--r--qpid/java/broker-plugins/access-control/MANIFEST.MF2
-rw-r--r--qpid/java/broker-plugins/experimental/shutdown/MANIFEST.MF16
-rw-r--r--qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Activator.java57
-rwxr-xr-xqpid/java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd25
-rw-r--r--qpid/java/broker-plugins/firewall/MANIFEST.MF2
-rw-r--r--qpid/java/broker-plugins/jmx/MANIFEST.MF65
-rw-r--r--qpid/java/broker-plugins/jmx/build.xml43
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/management/AMQManagedObject.java)39
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java)27
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java136
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java76
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java)89
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java189
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanIntrospector.java)9
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java)107
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java52
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java)10
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java)3
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java196
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java)17
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java183
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java323
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java)24
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java692
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java93
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java (renamed from qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Shutdown.java)27
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java (renamed from qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/ShutdownMBean.java)11
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java)77
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java208
-rw-r--r--qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java239
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java)14
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java235
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java (renamed from qpid/java/broker/src/test/java/org/apache/qpid/server/logging/management/LoggingManagementMBeanTest.java)84
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java202
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.java157
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java85
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java (renamed from qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedBrokerMBeanTest.java)29
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java283
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java (renamed from qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java)2
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java (renamed from qpid/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java)5
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java (renamed from qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java)276
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java204
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java251
-rw-r--r--qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java39
-rw-r--r--qpid/java/broker-plugins/management/MANIFEST.MF66
-rw-r--r--qpid/java/broker-plugins/management/build.xml39
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/Management.java155
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java72
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java77
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java79
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java109
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java208
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java118
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java215
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.java53
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java86
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.java74
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java177
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java503
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java576
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java253
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java104
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/addBinding.html42
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/addExchange.html53
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/addQueue.html174
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/authenticationprovider/addUser.html42
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/authenticationprovider/setPassword.html42
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html29
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/css/common.css92
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/footer.html28
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/images/qpid-logo.pngbin0 -> 6600 bytes
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/authorization/sasl.js213
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/UpdatableStore.js110
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/footer.js30
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/formatter.js99
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/properties.js26
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/updater.js45
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/util.js56
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/AuthenticationProvider.js122
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Broker.js205
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Connection.js213
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Exchange.js229
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Queue.js438
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/VirtualHost.js327
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/addBinding.js223
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/addExchange.js147
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/addQueue.js158
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js327
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/controller.js104
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/moveCopyMessages.js137
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/showMessage.js142
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/treeView.js313
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/management.html92
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/moveCopyMessages.html36
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/showAuthProvider.html25
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/showBroker.html25
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/showConnection.html47
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/showExchange.html46
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/showMessage.html73
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/showQueue.html97
-rw-r--r--qpid/java/broker-plugins/management/src/main/java/resources/showVirtualHost.html84
-rw-r--r--qpid/java/broker-web/build.xml107
-rw-r--r--qpid/java/broker-web/src/main/java/org/apache/qpid/web/listener/BrokerOptionsBuilder.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/management/Managable.java)24
-rw-r--r--qpid/java/broker-web/src/main/java/org/apache/qpid/web/listener/InitParametersOptionsBuilder.java314
-rw-r--r--qpid/java/broker-web/src/main/java/org/apache/qpid/web/listener/QpidServletContextListener.java162
-rw-r--r--qpid/java/broker-web/src/main/resources/WEB-INF/etc/config.xml107
-rw-r--r--qpid/java/broker-web/src/main/resources/WEB-INF/etc/virtualhosts.xml162
-rw-r--r--qpid/java/broker-web/src/main/resources/WEB-INF/web.xml261
-rw-r--r--qpid/java/broker/etc/broker_example.acl19
-rw-r--r--qpid/java/broker/etc/config.xml2
-rw-r--r--qpid/java/broker/etc/log4j.xml6
-rw-r--r--qpid/java/broker/etc/passwd2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java74
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java10
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java18
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java410
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java18
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java35
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java20
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java5
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java6
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java52
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java15
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java57
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java215
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java45
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java5
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java85
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java14
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java5
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java74
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java5
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java158
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java5
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java81
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java145
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java210
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java90
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java6
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java18
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java17
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java28
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java29
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Attribute.java199
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationMethod.java33
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java55
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java82
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java3
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java25
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java38
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Connection.java107
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Event.java27
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/EventType.java60
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java97
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/PasswordCredentialManagingAuthenticationProvider.java46
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java91
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java32
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java6
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/QueueNotificationListener.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java)5
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Session.java82
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java11
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java27
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java6
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/User.java59
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java154
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java37
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java293
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java487
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java222
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java484
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java315
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java225
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java409
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java262
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.java46
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java318
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java702
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java239
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.java67
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java844
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java142
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/AbstractConfiguredObject.java335
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/BrokerImpl.java148
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/ExchangeImpl.java115
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/QueueImpl.java107
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/VirtualHostImpl.java248
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties41
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java12
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java97
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java344
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java12
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java43
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java63
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java69
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java664
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java50
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java39
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java8
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java269
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java227
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java16
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java34
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java7
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java24
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java13
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java49
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java27
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java8
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java12
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java38
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java6
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java9
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java4
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java2
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java12
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java72
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java53
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java49
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java93
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java7
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionMBean.java263
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java11
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java6
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java3
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java13
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java128
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java31
-rw-r--r--qpid/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java395
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java194
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java12
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java20
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java235
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java27
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java153
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/model/impl/AbstractConfiguredObjectImplTest.java188
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/model/impl/BrokerImplTest.java106
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/model/impl/VirtualHostImplTest.java108
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java146
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java348
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java546
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java104
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/NotificationCheckTest.java106
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java43
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java3
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java76
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java10
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java6
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java323
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/transport/ServerConnectionMBeanTest.java231
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java6
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java13
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java16
-rw-r--r--qpid/java/build.deps22
-rw-r--r--qpid/java/build.xml2
-rw-r--r--qpid/java/common.xml4
-rw-r--r--qpid/java/ivy.retrieve.xml10
-rw-r--r--qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedQueue.java44
-rw-r--r--qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java2
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java2
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java35
-rw-r--r--qpid/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ManagementConsoleTest.java123
-rw-r--r--qpid/java/module.xml8
-rw-r--r--qpid/java/systests/build.xml2
-rw-r--r--qpid/java/systests/etc/config-systests-settings.xml3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedConnectionMBeanTest.java278
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageConnectionStatisticsTest.java101
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsConfigurationTest.java162
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsDeliveryTest.java109
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java196
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTestCase.java128
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java2
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java (renamed from qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsReportingTest.java)94
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java6
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java7
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java1
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java89
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java6
-rwxr-xr-xqpid/java/test-profiles/CPPExcludes9
-rw-r--r--qpid/java/test-profiles/Excludes7
-rwxr-xr-xqpid/java/test-profiles/Java010Excludes5
-rw-r--r--qpid/java/test-profiles/JavaPre010Excludes5
-rw-r--r--qpid/java/test-profiles/JavaTransientExcludes3
313 files changed, 23899 insertions, 7481 deletions
diff --git a/qpid/doc/book/src/java-broker/MessageStore-Tool.xml b/qpid/doc/book/src/java-broker/MessageStore-Tool.xml
new file mode 100644
index 0000000000..fdcb3cd560
--- /dev/null
+++ b/qpid/doc/book/src/java-broker/MessageStore-Tool.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<section><title>
+ MessageStore Tool
+ </title><section role="h2" id="MessageStoreTool-MessageStoreTool"><title>
+ MessageStore Tool
+ </title>
+
+ <para>
+ We have a number of implementations of the Qpid MessageStore
+ interface. This tool allows the interrogation of these stores
+ while the broker is offline.
+ </para>
+
+ <section role="h3" id="MessageStoreTool-MessageStoreImplementations"><title>
+ MessageStore
+ Implementations
+ </title>
+
+ <itemizedlist>
+ <listitem><para>
+ <xref linkend="qpid_BDBMessageStore--3rd-Party-"/>
+ </para></listitem>
+ <listitem><para>
+ <xref linkend="qpid_JDBCStore"/>
+ </para></listitem>
+ <listitem><para>
+ <xref linkend="qpid_MemoryMessageStore"/>
+ </para></listitem>
+ </itemizedlist>
+<!--h3--></section>
+
+ <section role="h3" id="MessageStoreTool-Introduction"><title>
+ Introduction
+ </title>
+
+ <para>
+ Each of the MessageStore implementations provide different back
+ end storage for their messages and so would need a different tool
+ to be able to interrogate their contents at the back end.
+ </para><para>
+ What this tool does is to utilise the Java broker code base to
+ access the contents of the storage providing the user with a
+ consistent means to inspect the storage contents in broker
+ memory. The tool allows the current messages in the store to be
+ inspected and copied/moved between queues. The tool uses the
+ message instance in memory for all its access paths, but changes
+ made will be reflected in the physical store (if one exists).
+ </para>
+<!--h3--></section>
+
+ <section role="h3" id="MessageStoreTool-Usage"><title>
+ Usage
+ </title>
+
+ <para>
+ The tools-distribution currently includes a unix shell command
+ 'msTool.sh' this script will launch the java tool.
+ </para><para>
+ The tool loads $QPID_HOME/etc/config.xml by default. If an
+ alternative broker configuration is required this should be
+ provided on the command line as would be done for the broker.
+ </para>
+ <programlisting>
+msTool.sh -c &lt;path to different config.xml&gt;
+</programlisting>
+ <para>
+ On startup the user is present with a command prompt
+ </para>
+ <programlisting>
+$ msTool.sh
+MessageStoreTool - for examining Persistent Qpid Broker MessageStore instances
+bdb$
+</programlisting>
+<!--h3--></section>
+
+ <section role="h3" id="MessageStoreTool-AvailableCommands"><title>
+ Available
+ Commands
+ </title>
+
+ <para>
+ The available commands in the tool can be seen through the use of
+ the 'help' command.
+ </para>
+ <programlisting>
+bdb$ help
++----------------------------------------------------------------+
+| Available Commands |
++----------------------------------------------------------------+
+| Command | Description |
++----------------------------------------------------------------+
+| quit | Quit the tool. |
+| list | list available items. |
+| dump | Dump selected message content. Default: show=content |
+| load | Loads specified broker configuration file. |
+| clear | Clears any selection. |
+| show | Shows the messages headers. |
+| select | Perform a selection. |
+| help | Provides detailed help on commands. |
++----------------------------------------------------------------+
+bdb$
+</programlisting>
+ <para>
+ A brief description is displayed and further usage information is
+ shown with 'help &lt;command&gt;'
+ </para>
+ <programlisting>
+bdb$ help list
+list availble items.
+Usage:list queues [&lt;exchange&gt;] | exchanges | bindings [&lt;exchange&gt;] | all
+bdb$
+</programlisting>
+<!--h3--></section>
+
+
+ <section role="h3" id="MessageStoreTool-FutureWork"><title>
+ Future Work
+ </title>
+
+ <para>
+ Currently the tool only works whilst the broker is offline i.e.
+ it is up, but not accepting AMQP connections. This requires a
+ stop/start of the broker. If this functionality was incorporated
+ into the broker then a telnet functionality could be provided
+ allowing online management.
+ </para>
+<!--h3--></section>
+<!--h2--></section>
+</section>
diff --git a/qpid/java/bdbstore/build.xml b/qpid/java/bdbstore/build.xml
index 7df048c691..7c305c7c2f 100644
--- a/qpid/java/bdbstore/build.xml
+++ b/qpid/java/bdbstore/build.xml
@@ -17,7 +17,7 @@
- under the License.
-->
<project name="bdbstore" xmlns:ivy="antlib:org.apache.ivy.ant" default="build">
- <property name="module.depends" value="management/common common broker" />
+ <property name="module.depends" value="common broker" />
<property name="module.test.depends" value="test client common/test broker/test management/common systests" />
<property name="module.genpom" value="true"/>
diff --git a/qpid/java/bdbstore/jmx/MANIFEST.MF b/qpid/java/bdbstore/jmx/MANIFEST.MF
new file mode 100644
index 0000000000..7046c4326d
--- /dev/null
+++ b/qpid/java/bdbstore/jmx/MANIFEST.MF
@@ -0,0 +1,20 @@
+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-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/qpid/java/broker-plugins/experimental/shutdown/build.xml b/qpid/java/bdbstore/jmx/build.xml
index 96f97ee437..2015b0cbb5 100644
--- a/qpid/java/broker-plugins/experimental/shutdown/build.xml
+++ b/qpid/java/bdbstore/jmx/build.xml
@@ -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
@@ -7,25 +6,24 @@
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
- -
+ -
- http://www.apache.org/licenses/LICENSE-2.0
- -
+ -
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- -
-->
-<project name="AMQ Broker Shutdown Plugin" default="build">
- <property name="module.depends" value="common broker management/common broker-plugins"/>
- <property name="module.test.depends" value="test broker/test management/common client systests"/>
- <property name="module.manifest" value="MANIFEST.MF"/>
- <property name="module.plugin" value="true"/>
+<project name="bdbstore-jmx" default="build">
+ <property name="module.depends" value="common broker broker-plugins broker-plugins/jmx management/common bdbstore" />
+ <property name="module.test.depends" value="test broker/test common/test management/common client systests bdbstore/test" />
- <import file="../../../module.xml"/>
+ <property name="module.manifest" value="MANIFEST.MF" />
+ <property name="module.plugin" value="true" />
- <target name="bundle" depends="bundle-tasks"/>
+ <import file="../../module.xml" />
+ <target name="bundle" depends="bundle-tasks" />
</project>
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreManagerMBean.java b/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java
index c2c7bf4c86..455573f7bc 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreManagerMBean.java
+++ b/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java
@@ -17,14 +17,13 @@
* under the License.
*
*/
-package org.apache.qpid.server.store.berkeleydb;
+package org.apache.qpid.server.store.berkeleydb.jmx;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import javax.management.JMException;
-import javax.management.NotCompliantMBeanException;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
@@ -37,8 +36,19 @@ import javax.management.openmbean.TabularType;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQStoreException;
-import org.apache.qpid.server.management.AMQManagedObject;
-
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore;
+
+/**
+ * Management mbean for BDB HA.
+ * <p>
+ * At runtime, the classloader loading this clas must have visibility of the other Qpid JMX classes. This is
+ * currently arranged through OSGI using the <b>fragment</b> feature so that this bundle shares the
+ * same classloader as broker-plugins-jmx. See the <b>Fragment-Host:</b> header within the MANIFEST.MF
+ * of this bundle.
+ * </p>
+ */
public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements ManagedBDBHAMessageStore
{
private static final Logger LOGGER = Logger.getLogger(BDBHAMessageStoreManagerMBean.class);
@@ -70,10 +80,12 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M
private final BDBHAMessageStore _store;
- protected BDBHAMessageStoreManagerMBean(BDBHAMessageStore store) throws NotCompliantMBeanException
+ protected BDBHAMessageStoreManagerMBean(BDBHAMessageStore store, ManagedObject parent) throws JMException
{
- super(ManagedBDBHAMessageStore.class, ManagedBDBHAMessageStore.TYPE);
+ super(ManagedBDBHAMessageStore.class, ManagedBDBHAMessageStore.TYPE, ((AMQManagedObject)parent).getRegistry());
+ LOGGER.debug("Creating BDBHAMessageStoreManagerMBean");
_store = store;
+ register();
}
@Override
@@ -211,4 +223,10 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M
}
}
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return null;
+ }
+
}
diff --git a/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java b/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java
new file mode 100644
index 0000000000..837da1eef3
--- /dev/null
+++ b/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java
@@ -0,0 +1,73 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store.berkeleydb.jmx;
+
+import javax.management.JMException;
+import javax.management.StandardMBean;
+
+import org.apache.log4j.Logger;
+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}.
+ *
+ */
+public class BDBHAMessageStoreManagerMBeanProvider implements MBeanProvider
+{
+ private static final Logger LOGGER = Logger.getLogger(BDBHAMessageStoreManagerMBeanProvider.class);
+
+ public BDBHAMessageStoreManagerMBeanProvider()
+ {
+ super();
+ }
+
+ @Override
+ public boolean isChildManageableByMBean(ConfiguredObject child)
+ {
+ return (child instanceof VirtualHost
+ && BDBHAMessageStore.BDB_HA_STORE_TYPE.equals(child.getAttribute(VirtualHost.STORE_TYPE)));
+ }
+
+ @Override
+ public StandardMBean createMBean(ConfiguredObject child, StandardMBean parent) throws JMException
+ {
+ 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();
+
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Creating mBean for child " + child);
+ }
+
+ return new BDBHAMessageStoreManagerMBean(messageStore, (ManagedObject) parent);
+ }
+}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/ManagedBDBHAMessageStore.java b/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/ManagedBDBHAMessageStore.java
index 6499ea04e0..b85e44526b 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/ManagedBDBHAMessageStore.java
+++ b/qpid/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/ManagedBDBHAMessageStore.java
@@ -17,7 +17,7 @@
* under the License.
*
*/
-package org.apache.qpid.server.store.berkeleydb;
+package org.apache.qpid.server.store.berkeleydb.jmx;
import java.io.IOException;
diff --git a/qpid/java/bdbstore/jmx/src/main/resources/services/org.apache.qpid.server.jmx.MBeanProvider b/qpid/java/bdbstore/jmx/src/main/resources/services/org.apache.qpid.server.jmx.MBeanProvider
new file mode 100644
index 0000000000..b5bc947612
--- /dev/null
+++ b/qpid/java/bdbstore/jmx/src/main/resources/services/org.apache.qpid.server.jmx.MBeanProvider
@@ -0,0 +1 @@
+org.apache.qpid.server.store.berkeleydb.jmx.BDBHAMessageStoreManagerMBeanProvider
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java b/qpid/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java
index b01f169715..45038bf050 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java
+++ b/qpid/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java
@@ -35,6 +35,7 @@ import javax.management.openmbean.TabularData;
import org.apache.log4j.Logger;
import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.server.store.berkeleydb.jmx.ManagedBDBHAMessageStore;
import org.apache.qpid.test.utils.JMXTestUtils;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java b/qpid/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java
index 294859832f..22877ec36c 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java
+++ b/qpid/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java
@@ -29,6 +29,7 @@ import javax.jms.MessageConsumer;
import javax.jms.Session;
import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.server.store.berkeleydb.jmx.ManagedBDBHAMessageStore;
import org.apache.qpid.test.utils.JMXTestUtils;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreManagerMBeanTest.java b/qpid/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java
index b64a213756..49b3ddd3dc 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreManagerMBeanTest.java
+++ b/qpid/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java
@@ -17,7 +17,7 @@
* under the License.
*
*/
-package org.apache.qpid.server.store.berkeleydb;
+package org.apache.qpid.server.store.berkeleydb.jmx;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
@@ -37,9 +37,14 @@ import javax.management.openmbean.TabularData;
import junit.framework.TestCase;
import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
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.store.berkeleydb.BDBHAMessageStore;
+import org.apache.qpid.server.store.berkeleydb.jmx.BDBHAMessageStoreManagerMBean;
+import org.apache.qpid.server.store.berkeleydb.jmx.ManagedBDBHAMessageStore;
public class BDBHAMessageStoreManagerMBeanTest extends TestCase
{
@@ -54,6 +59,7 @@ public class BDBHAMessageStoreManagerMBeanTest extends TestCase
private BDBHAMessageStore _store;
private BDBHAMessageStoreManagerMBean _mBean;
+ private AMQManagedObject _mBeanParent;
@Override
protected void setUp() throws Exception
@@ -62,7 +68,9 @@ public class BDBHAMessageStoreManagerMBeanTest extends TestCase
CurrentActor.set(new TestLogActor(new SystemOutMessageLogger()));
_store = mock(BDBHAMessageStore.class);
- _mBean = new BDBHAMessageStoreManagerMBean(_store);
+ _mBeanParent = mock(AMQManagedObject.class);
+ when(_mBeanParent.getRegistry()).thenReturn(mock(ManagedObjectRegistry.class));
+ _mBean = new BDBHAMessageStoreManagerMBean(_store, _mBeanParent);
}
@Override
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java
index ab54d7d16a..c40f24dbc3 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java
@@ -105,6 +105,8 @@ 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";
+
private String _groupName;
private String _nodeName;
private String _nodeHostPort;
@@ -113,8 +115,6 @@ public class BDBHAMessageStore extends AbstractBDBMessageStore implements HAMess
private String _name;
- private BDBHAMessageStoreManagerMBean _managedObject;
-
private CommitThreadWrapper _commitThreadWrapper;
private boolean _coalescingSync;
private boolean _designatedPrimary;
@@ -149,8 +149,6 @@ public class BDBHAMessageStore extends AbstractBDBMessageStore implements HAMess
throw new ConfigurationException("Coalescing sync cannot be used with master sync policy " + SyncPolicy.SYNC
+ "! Please set highAvailability.coalescingSync to false in store configuration.");
}
- _managedObject = new BDBHAMessageStoreManagerMBean(this);
- _managedObject.register();
super.configure(name, storeConfig);
}
@@ -394,28 +392,18 @@ public class BDBHAMessageStore extends AbstractBDBMessageStore implements HAMess
@Override
protected void closeInternal() throws Exception
{
+ substituteNoOpStateChangeListenerOn(getReplicatedEnvironment());
+
try
{
- substituteNoOpStateChangeListenerOn(getReplicatedEnvironment());
-
- try
- {
- if(_coalescingSync)
- {
- _commitThreadWrapper.stopCommitThread();
- }
- }
- finally
+ if(_coalescingSync)
{
- super.closeInternal();
+ _commitThreadWrapper.stopCommitThread();
}
}
finally
{
- if (_managedObject != null)
- {
- _managedObject.unregister();
- }
+ super.closeInternal();
}
}
@@ -610,4 +598,10 @@ public class BDBHAMessageStore extends AbstractBDBMessageStore implements HAMess
{
}
}
+
+ @Override
+ public String getStoreType()
+ {
+ return BDB_HA_STORE_TYPE;
+ }
}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java
index d5bf5374bc..82bc3d8564 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java
@@ -42,6 +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";
private CommitThreadWrapper _commitThreadWrapper;
@Override
@@ -103,4 +104,11 @@ public class BDBMessageStore extends AbstractBDBMessageStore
return _commitThreadWrapper.commit(tx, syncCommit);
}
+
+ @Override
+ public String getStoreType()
+ {
+ return BDB_STORE_TYPE;
+ }
+
}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java
index 3265fb6823..97a3d61df1 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java
@@ -45,6 +45,7 @@ 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;
import org.apache.qpid.server.store.berkeleydb.AMQShortStringEncoding;
import org.apache.qpid.server.store.berkeleydb.FieldTableEncoding;
import org.apache.qpid.server.util.MapJsonSerializer;
@@ -93,6 +94,8 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade
private MapJsonSerializer _serializer = new MapJsonSerializer();
+ private static final boolean _moveNonExclusiveQueueOwnerToDescription = Boolean.parseBoolean(System.getProperty("qpid.move_non_exclusive_queue_owner_to_description", Boolean.TRUE.toString()));
+
/**
* Upgrades from a v5 database to a v6 database
*
@@ -554,17 +557,49 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade
private UpgradeConfiguredObjectRecord createQueueConfiguredObjectRecord(String queueName, String owner, boolean exclusive,
FieldTable arguments)
{
+ Map<String, Object> attributesMap = buildQueueArgumentMap(queueName,
+ owner, exclusive, arguments);
+ String json = _serializer.serialize(attributesMap);
+ UpgradeConfiguredObjectRecord configuredObject = new UpgradeConfiguredObjectRecord(Queue.class.getName(), json);
+ return configuredObject;
+ }
+
+ private Map<String, Object> buildQueueArgumentMap(String queueName,
+ String owner, boolean exclusive, FieldTable arguments)
+ {
+
Map<String, Object> attributesMap = new HashMap<String, Object>();
attributesMap.put(Queue.NAME, queueName);
- attributesMap.put(Queue.OWNER, owner);
attributesMap.put(Queue.EXCLUSIVE, exclusive);
+
+ FieldTable argumentsCopy = new FieldTable();
if (arguments != null)
{
- attributesMap.put("ARGUMENTS", FieldTable.convertToMap(arguments));
+ argumentsCopy.addAll(arguments);
}
- String json = _serializer.serialize(attributesMap);
- UpgradeConfiguredObjectRecord configuredObject = new UpgradeConfiguredObjectRecord(Queue.class.getName(), json);
- return configuredObject;
+
+ if (moveNonExclusiveOwnerToDescription(owner, exclusive))
+ {
+ _logger.info("Non-exclusive owner " + owner + " for queue " + queueName + " moved to " + AMQQueueFactory.X_QPID_DESCRIPTION);
+
+ attributesMap.put(Queue.OWNER, null);
+ argumentsCopy.put(AMQShortString.valueOf(AMQQueueFactory.X_QPID_DESCRIPTION), owner);
+ }
+ else
+ {
+ attributesMap.put(Queue.OWNER, owner);
+ }
+ if (!argumentsCopy.isEmpty())
+ {
+ attributesMap.put(Queue.ARGUMENTS, FieldTable.convertToMap(argumentsCopy));
+ }
+ return attributesMap;
+ }
+
+ private boolean moveNonExclusiveOwnerToDescription(String owner,
+ boolean exclusive)
+ {
+ return exclusive == false && owner != null && _moveNonExclusiveQueueOwnerToDescription;
}
private UpgradeConfiguredObjectRecord createExchangeConfiguredObjectRecord(String exchangeName, String exchangeType,
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java
index 687c671566..5cc436a22a 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java
+++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java
@@ -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.
+ *
+ */
package org.apache.qpid.server.store.berkeleydb;
import org.apache.qpid.server.store.DurableConfigurationStoreTest;
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java
index 591bc27d1e..e97323c5f2 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java
+++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java
@@ -55,7 +55,7 @@ import org.apache.qpid.transport.MessageTransfer;
/**
* Subclass of MessageStoreTest which runs the standard tests from the superclass against
- * the BDB Store as well as additional tests specific to the DBB store-implementation.
+ * the BDB Store as well as additional tests specific to the BDB store-implementation.
*/
public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageStoreTest
{
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java
index 36991b90d0..c0d74bc847 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java
+++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java
@@ -52,8 +52,8 @@ public abstract class AbstractUpgradeTestCase extends QpidTestCase
}
public static final String[] QUEUE_NAMES = { "clientid:myDurSubName", "clientid:mySelectorDurSubName", "myUpgradeQueue",
- "queue-non-durable" };
- public static int[] QUEUE_SIZES = { 1, 1, 10, 3 };
+ "queue-non-durable", "nonexclusive-with-erroneous-owner" };
+ public static int[] QUEUE_SIZES = { 1, 1, 10, 3, 0};
public static int TOTAL_MESSAGE_NUMBER = 15;
protected static final LogSubject LOG_SUBJECT = new TestBlankSubject();
@@ -98,7 +98,7 @@ public abstract class AbstractUpgradeTestCase extends QpidTestCase
finally
{
_environment = null;
- deleteDirectoryIfExists(_storeLocation);
+ //deleteDirectoryIfExists(_storeLocation);
}
super.tearDown();
}
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java
index 3f9e4e4aa1..65a8bb03fb 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java
+++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java
@@ -23,10 +23,13 @@ package org.apache.qpid.server.store.berkeleydb.upgrade;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.framing.AMQShortString;
@@ -49,6 +52,7 @@ 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";
@@ -87,6 +91,10 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase
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);
+
+ assertQueueHasOwner(NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER, "misused-owner-as-description");
+
assertContent();
}
@@ -94,7 +102,7 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase
{
UpgradeFrom4To5 upgrade = new UpgradeFrom4To5();
upgrade.performUpgrade(_environment, new StaticAnswerHandler(UpgradeInteractionResponse.NO), getVirtualHostName());
- assertQueues(new HashSet<String>(Arrays.asList(DURABLE_SUBSCRIPTION_QUEUE, DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, DURABLE_QUEUE)));
+ assertQueues(new HashSet<String>(Arrays.asList(DURABLE_SUBSCRIPTION_QUEUE, DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, DURABLE_QUEUE, NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER)));
assertDatabaseRecordCount(DELIVERY_DB_NAME, 12);
assertDatabaseRecordCount(MESSAGE_META_DATA_DB_NAME, 12);
@@ -112,6 +120,9 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase
assertBindingRecord(queueBindings, DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, "amq.topic",
BDBStoreUpgradeTestPreparer.SELECTOR_TOPIC_NAME, "testprop='true'");
assertBindingRecord(queueBindings, DURABLE_QUEUE, "amq.direct", DURABLE_QUEUE, null);
+
+ assertQueueHasOwner(NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER, "misused-owner-as-description");
+
assertContent();
}
@@ -257,7 +268,7 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase
private void assertQueues(Set<String> expectedQueueNames)
{
- List<AMQShortString> durableSubNames = new ArrayList<AMQShortString>();
+ List<AMQShortString> durableSubNames = Collections.emptyList();
final UpgradeFrom4To5.QueueRecordBinding binding = new UpgradeFrom4To5.QueueRecordBinding(durableSubNames);
final Set<String> actualQueueNames = new HashSet<String>();
@@ -278,6 +289,35 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase
assertEquals("Unexpected queue names", expectedQueueNames, actualQueueNames);
}
+ private void assertQueueHasOwner(String queueName, final String expectedOwner)
+ {
+ List<AMQShortString> durableSubNames = Collections.emptyList();
+ final UpgradeFrom4To5.QueueRecordBinding binding = new UpgradeFrom4To5.QueueRecordBinding(durableSubNames);
+ final AtomicReference<String> actualOwner = new AtomicReference<String>();
+ final AtomicBoolean foundQueue = new AtomicBoolean(false);
+
+ CursorOperation queueNameCollector = new CursorOperation()
+ {
+
+ @Override
+ public void processEntry(Database sourceDatabase, Database targetDatabase, Transaction transaction,
+ DatabaseEntry key, DatabaseEntry value)
+ {
+ QueueRecord record = binding.entryToObject(value);
+ String queueName = record.getNameShortString().asString();
+ if (queueName.equals(queueName))
+ {
+ foundQueue.set(true);
+ actualOwner.set(AMQShortString.toString(record.getOwner()));
+ }
+ }
+ };
+ new DatabaseTemplate(_environment, "queueDb_v5", null).run(queueNameCollector);
+
+ assertTrue("Could not find queue in database", foundQueue.get());
+ assertEquals("Queue has unexpected owner", expectedOwner, actualOwner.get());
+ }
+
private void assertContent()
{
final UpgradeFrom4To5.ContentBinding contentBinding = new UpgradeFrom4To5.ContentBinding();
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java
index 5297692820..0031447140 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java
+++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java
@@ -29,6 +29,7 @@ import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.OL
import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.OLD_XID_DB_NAME;
import java.io.File;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -41,6 +42,7 @@ import org.apache.qpid.server.model.Binding;
import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.store.berkeleydb.entry.Xid;
import org.apache.qpid.server.store.berkeleydb.tuple.XidBinding;
import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.CompoundKey;
@@ -260,7 +262,7 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
private void assertDatabaseRecordCounts()
{
- assertDatabaseRecordCount(CONFIGURED_OBJECTS_DB_NAME, 9);
+ assertDatabaseRecordCount(CONFIGURED_OBJECTS_DB_NAME, 12);
assertDatabaseRecordCount(NEW_DELIVERY_DB_NAME, 12);
assertDatabaseRecordCount(NEW_METADATA_DB_NAME, 12);
@@ -270,64 +272,25 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
private void assertConfiguredObjects()
{
Map<UUID, UpgradeConfiguredObjectRecord> configuredObjects = loadConfiguredObjects();
- assertEquals("Unexpected number of configured objects", 9, configuredObjects.size());
-
- Set<Map<String, Object>> expected = new HashSet<Map<String, Object>>(9);
- Map<String, Object> queue1 = new HashMap<String, Object>();
- queue1.put("exclusive", Boolean.FALSE);
- queue1.put("name", "myUpgradeQueue");
- queue1.put("owner", null);
- expected.add(queue1);
- Map<String, Object> queue2 = new HashMap<String, Object>();
- queue2.put("exclusive", Boolean.TRUE);
- queue2.put("name", "clientid:mySelectorDurSubName");
- queue2.put("owner", "clientid");
- expected.add(queue2);
- Map<String, Object> queue3 = new HashMap<String, Object>();
- queue3.put("exclusive", Boolean.TRUE);
- queue3.put("name", "clientid:myDurSubName");
- queue3.put("owner", "clientid");
- expected.add(queue3);
-
- Map<String, Object> queueBinding1 = new HashMap<String, Object>();
- queueBinding1.put("queue", UUIDGenerator.generateUUID("myUpgradeQueue", getVirtualHostName()).toString());
- queueBinding1.put("name", "myUpgradeQueue");
- queueBinding1.put("exchange", UUIDGenerator.generateUUID("<<default>>", getVirtualHostName()).toString());
- expected.add(queueBinding1);
- Map<String, Object> queueBinding2 = new HashMap<String, Object>();
- queueBinding2.put("queue", UUIDGenerator.generateUUID("myUpgradeQueue", getVirtualHostName()).toString());
- queueBinding2.put("name", "myUpgradeQueue");
- queueBinding2.put("exchange", UUIDGenerator.generateUUID("amq.direct", getVirtualHostName()).toString());
- Map<String, Object> arguments2 = new HashMap<String, Object>();
- arguments2.put("x-filter-jms-selector", "");
- queueBinding2.put("arguments", arguments2);
- expected.add(queueBinding2);
- Map<String, Object> queueBinding3 = new HashMap<String, Object>();
- queueBinding3.put("queue", UUIDGenerator.generateUUID("clientid:myDurSubName", getVirtualHostName()).toString());
- queueBinding3.put("name", "myUpgradeTopic");
- queueBinding3.put("exchange", UUIDGenerator.generateUUID("amq.topic", getVirtualHostName()).toString());
- Map<String, Object> arguments3 = new HashMap<String, Object>();
- arguments3.put("x-filter-jms-selector", "");
- queueBinding3.put("arguments", arguments3);
- expected.add(queueBinding3);
- Map<String, Object> queueBinding4 = new HashMap<String, Object>();
- queueBinding4.put("queue", UUIDGenerator.generateUUID("clientid:mySelectorDurSubName", getVirtualHostName()).toString());
- queueBinding4.put("name", "mySelectorUpgradeTopic");
- queueBinding4.put("exchange", UUIDGenerator.generateUUID("amq.topic", getVirtualHostName()).toString());
- Map<String, Object> arguments4 = new HashMap<String, Object>();
- arguments4.put("x-filter-jms-selector", "testprop='true'");
- queueBinding4.put("arguments", arguments4);
- expected.add(queueBinding4);
- Map<String, Object> queueBinding5 = new HashMap<String, Object>();
- queueBinding5.put("queue", UUIDGenerator.generateUUID("clientid:myDurSubName", getVirtualHostName()).toString());
- queueBinding5.put("name", "clientid:myDurSubName");
- queueBinding5.put("exchange", UUIDGenerator.generateUUID("<<default>>", getVirtualHostName()).toString());
- expected.add(queueBinding5);
- Map<String, Object> queueBinding6 = new HashMap<String, Object>();
- queueBinding6.put("queue", UUIDGenerator.generateUUID("clientid:mySelectorDurSubName", getVirtualHostName()).toString());
- queueBinding6.put("name", "clientid:mySelectorDurSubName");
- queueBinding6.put("exchange", UUIDGenerator.generateUUID("<<default>>", getVirtualHostName()).toString());
- expected.add(queueBinding6);
+ assertEquals("Unexpected number of configured objects", 12, configuredObjects.size());
+
+ Set<Map<String, Object>> expected = new HashSet<Map<String, Object>>(12);
+ 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")));
+
+ expected.add(createExpectedQueueBindingMap("myUpgradeQueue","myUpgradeQueue", "<<default>>", null));
+ expected.add(createExpectedQueueBindingMap("myUpgradeQueue", "myUpgradeQueue", "amq.direct", null));
+ expected.add(createExpectedQueueBindingMap("clientid:myDurSubName", "myUpgradeTopic", "amq.topic",
+ Collections.singletonMap("x-filter-jms-selector", "")));
+ expected.add(createExpectedQueueBindingMap("clientid:mySelectorDurSubName", "mySelectorUpgradeTopic", "amq.topic",
+ Collections.singletonMap("x-filter-jms-selector", "testprop='true'")));
+ expected.add(createExpectedQueueBindingMap("clientid:myDurSubName", "clientid:myDurSubName", "<<default>>", null));
+ expected.add(createExpectedQueueBindingMap("clientid:mySelectorDurSubName", "clientid:mySelectorDurSubName", "<<default>>", null));
+ expected.add(createExpectedQueueBindingMap("nonexclusive-with-erroneous-owner", "nonexclusive-with-erroneous-owner", "amq.direct", null));
+ expected.add(createExpectedQueueBindingMap("nonexclusive-with-erroneous-owner","nonexclusive-with-erroneous-owner", "<<default>>", null));
Set<String> expectedTypes = new HashSet<String>();
expectedTypes.add(Queue.class.getName());
@@ -337,11 +300,11 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
for (Entry<UUID, UpgradeConfiguredObjectRecord> entry : configuredObjects.entrySet())
{
UpgradeConfiguredObjectRecord object = entry.getValue();
- UUID key = entry.getKey();
Map<String, Object> deserialized = jsonSerializer.deserialize(object.getAttributes());
assertTrue("Unexpected entry:" + object.getAttributes(), expected.remove(deserialized));
String type = object.getType();
assertTrue("Unexpected type:" + type, expectedTypes.contains(type));
+ UUID key = entry.getKey();
if (type.equals(Exchange.class.getName()) || type.equals(Queue.class.getName()))
{
assertEquals("Unexpected key", key, UUIDGenerator.generateUUID(((String) deserialized.get("name")), getVirtualHostName()));
@@ -354,6 +317,32 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
assertTrue("Not all expected configured objects found:" + expected, expected.isEmpty());
}
+ private Map<String, Object> createExpectedQueueBindingMap(String queue, String bindingName, String exchangeName, Map<String, String> argumentMap)
+ {
+ Map<String, Object> expectedQueueBinding = new HashMap<String, Object>();
+ expectedQueueBinding.put(Binding.QUEUE, UUIDGenerator.generateUUID(queue, getVirtualHostName()).toString());
+ expectedQueueBinding.put(Binding.NAME, bindingName);
+ expectedQueueBinding.put(Binding.EXCHANGE, UUIDGenerator.generateUUID(exchangeName, getVirtualHostName()).toString());
+ if (argumentMap != null)
+ {
+ expectedQueueBinding.put(Binding.ARGUMENTS, argumentMap);
+ }
+ return expectedQueueBinding;
+ }
+
+ private Map<String, Object> createExpectedQueueMap(String name, boolean exclusiveFlag, String owner, Map<String, String> argumentMap)
+ {
+ Map<String, Object> expectedQueueEntry = new HashMap<String, Object>();
+ expectedQueueEntry.put(Queue.NAME, name);
+ expectedQueueEntry.put(Queue.EXCLUSIVE, exclusiveFlag);
+ expectedQueueEntry.put(Queue.OWNER, owner);
+ if (argumentMap != null)
+ {
+ expectedQueueEntry.put(Queue.ARGUMENTS, argumentMap);
+ }
+ return expectedQueueEntry;
+ }
+
private Map<UUID, UpgradeConfiguredObjectRecord> loadConfiguredObjects()
{
final Map<UUID, UpgradeConfiguredObjectRecord> configuredObjectsRecords = new HashMap<UUID, UpgradeConfiguredObjectRecord>();
diff --git a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb
index 167ab7f0ca..f5ed9aa5a2 100644
--- a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb
+++ b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb
Binary files differ
diff --git a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb
index d44b21a83e..f5ed9aa5a2 100644
--- a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb
+++ b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb
Binary files differ
diff --git a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb
index 9b85860c19..d5ae8c1096 100644
--- a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb
+++ b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb
Binary files differ
diff --git a/qpid/java/broker-plugins/access-control/MANIFEST.MF b/qpid/java/broker-plugins/access-control/MANIFEST.MF
index 78072850e4..a8fb99995e 100644
--- a/qpid/java/broker-plugins/access-control/MANIFEST.MF
+++ b/qpid/java/broker-plugins/access-control/MANIFEST.MF
@@ -13,12 +13,10 @@ Bundle-ActivationPolicy: lazy
Import-Package: org.apache.qpid,
org.apache.qpid.exchange,
org.apache.qpid.framing,
- org.apache.qpid.junit.extensions.util,
org.apache.qpid.protocol,
org.apache.qpid.server.configuration,
org.apache.qpid.server.configuration.plugins,
org.apache.qpid.server.exchange,
- org.apache.qpid.server.management,
org.apache.qpid.server.logging,
org.apache.qpid.server.logging.actors,
org.apache.qpid.server.logging.subjects,
diff --git a/qpid/java/broker-plugins/experimental/shutdown/MANIFEST.MF b/qpid/java/broker-plugins/experimental/shutdown/MANIFEST.MF
deleted file mode 100644
index 0bd0a835e4..0000000000
--- a/qpid/java/broker-plugins/experimental/shutdown/MANIFEST.MF
+++ /dev/null
@@ -1,16 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: Experimental Shutdown
-Bundle-Description: Experimental Qpid Broker Shutdown Plugin
-Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
-Bundle-DocURL: http://qpid.apache.org/
-Bundle-SymbolicName: broker-plugins-experimental-shutdown;singleton:=true
-Bundle-Version: 1.0.0
-Bundle-Activator: org.apache.qpid.shutdown.Activator
-Import-Package: javax.management;resolution:=optional,
- org.apache.log4j,
- org.osgi.framework,
- org.apache.qpid.server.management
-Bundle-RequiredExecutionEnvironment: J2SE-1.5
-Bundle-ActivationPolicy: lazy
-
diff --git a/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Activator.java b/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Activator.java
deleted file mode 100644
index 2b7fa33784..0000000000
--- a/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Activator.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.shutdown;
-
-
-import org.apache.log4j.Logger;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-public class Activator implements BundleActivator
-{
- private static final Logger _logger = Logger.getLogger(Activator.class);
-
- private Shutdown _shutdown = null;
-
- /** @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) */
- public void start(BundleContext ctx) throws Exception {
- _shutdown = new Shutdown();
- if (ctx != null)
- {
- ctx.registerService(ShutdownMBean.class.getName(), _shutdown, null);
- }
-
- _shutdown.register();
-
- _logger.info("Shutdown plugin MBean registered");
- }
-
- /** @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) */
- public void stop(BundleContext ctx) throws Exception
- {
- if (_shutdown != null)
- {
- _shutdown.unregister();
- _shutdown = null;
- }
-
- _logger.info("Shutdown plugin MBean unregistered");
- }
-}
diff --git a/qpid/java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd b/qpid/java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd
deleted file mode 100755
index 60af4b89e8..0000000000
--- a/qpid/java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-ver: 0.17.0
-
-Bundle-SymbolicName: qpid-shutdown-plugin
-Bundle-Version: ${ver}
-Export-Package: *;version=${ver}
-Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/qpid/java/broker-plugins/firewall/MANIFEST.MF b/qpid/java/broker-plugins/firewall/MANIFEST.MF
index 6ceea119da..a302921d03 100644
--- a/qpid/java/broker-plugins/firewall/MANIFEST.MF
+++ b/qpid/java/broker-plugins/firewall/MANIFEST.MF
@@ -12,12 +12,10 @@ Bundle-ClassPath: .
Bundle-ActivationPolicy: lazy
Import-Package: org.apache.qpid,
org.apache.qpid.framing,
- org.apache.qpid.junit.extensions.util,
org.apache.qpid.protocol,
org.apache.qpid.server.configuration,
org.apache.qpid.server.configuration.plugins,
org.apache.qpid.server.exchange,
- org.apache.qpid.server.management,
org.apache.qpid.server.plugins,
org.apache.qpid.server.queue,
org.apache.qpid.server.security,
diff --git a/qpid/java/broker-plugins/jmx/MANIFEST.MF b/qpid/java/broker-plugins/jmx/MANIFEST.MF
new file mode 100644
index 0000000000..b13ff7f132
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/MANIFEST.MF
@@ -0,0 +1,65 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Qpid Broker-Plugins JMX
+Bundle-SymbolicName: broker-plugins-jmx
+Bundle-Description: 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.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/qpid/java/broker-plugins/jmx/build.xml b/qpid/java/broker-plugins/jmx/build.xml
new file mode 100644
index 0000000000..4deb0196e7
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/build.xml
@@ -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.
+ -->
+<project name="Qpid Broker-Plugins JMX" default="build">
+
+ <condition property="systests.optional.depends" value="bdbstore" else="">
+ <or>
+ <and>
+ <contains string="${modules.opt}" substring="bdbstore"/>
+ <contains string="${profile}" substring="bdb"/>
+ </and>
+ <and>
+ <istrue value="${optional}"/>
+ <contains string="${profile}" substring="bdb"/>
+ </and>
+ </or>
+ </condition>
+
+ <property name="module.depends" value="common broker broker-plugins broker-plugins-jmx management/common" />
+ <property name="module.test.depends" value="systests test broker/test common/test management/common client ${systests.optional.depends}" />
+
+ <property name="module.manifest" value="MANIFEST.MF" />
+ <property name="module.plugin" value="true" />
+
+ <import file="../../module.xml" />
+
+ <target name="bundle" depends="bundle-tasks" />
+</project>
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/AMQManagedObject.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java
index 5c57c01f6e..5c39a0c26a 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/AMQManagedObject.java
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java
@@ -18,11 +18,9 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
+package org.apache.qpid.server.jmx;
-import org.apache.qpid.server.logging.LogActor;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.ManagementActor;
+import java.util.concurrent.atomic.AtomicLong;
import javax.management.ListenerNotFoundException;
import javax.management.NotCompliantMBeanException;
@@ -32,7 +30,7 @@ import javax.management.NotificationFilter;
import javax.management.NotificationListener;
/**
- * This class provides additinal feature of Notification Broadcaster to the
+ * This class provides additional feature of Notification Broadcaster to the
* DefaultManagedObject.
* @author Bhupendra Bhardwaj
* @version 0.1
@@ -40,19 +38,17 @@ import javax.management.NotificationListener;
public abstract class AMQManagedObject extends DefaultManagedObject
implements NotificationBroadcaster
{
- private NotificationBroadcasterSupport _broadcaster = new NotificationBroadcasterSupport();
+ private final NotificationBroadcasterSupport _broadcaster = new NotificationBroadcasterSupport();
- private long _notificationSequenceNumber = 0;
+ private AtomicLong _notificationSequenceNumber = new AtomicLong();
- private LogActor _logActor;
-
- protected AMQManagedObject(Class<?> managementInterface, String typeName)
+ protected AMQManagedObject(Class<?> managementInterface, String typeName, ManagedObjectRegistry registry)
throws NotCompliantMBeanException
{
- super(managementInterface, typeName);
+ super(managementInterface, typeName, registry);
// CurrentActor will be defined as these objects are created during
// broker startup.
- _logActor = new ManagementActor(CurrentActor.get().getRootMessageLogger());
+
}
// notification broadcaster implementation
@@ -79,27 +75,10 @@ public abstract class AMQManagedObject extends DefaultManagedObject
return _broadcaster;
}
- /**
- * sequence number for notifications
- */
- protected long getNotificationSequenceNumber()
- {
- return _notificationSequenceNumber;
- }
-
- protected void setNotificationSequenceNumber(long notificationSequenceNumber)
- {
- _notificationSequenceNumber = notificationSequenceNumber;
- }
-
protected long incrementAndGetSequenceNumber()
{
- return ++_notificationSequenceNumber;
+ return _notificationSequenceNumber.incrementAndGet();
}
- protected LogActor getLogActor()
- {
- return _logActor;
- }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.java
index 10d7503800..4446f96802 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.java
@@ -18,12 +18,10 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
+package org.apache.qpid.server.jmx;
import org.apache.log4j.Logger;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-
import javax.management.JMException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
@@ -49,15 +47,21 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
private ManagedObjectRegistry _registry;
- protected DefaultManagedObject(Class<?> managementInterface, String typeName)
+ protected DefaultManagedObject(Class<?> managementInterface, String typeName, ManagedObjectRegistry registry)
throws NotCompliantMBeanException
{
super(managementInterface);
+ _registry = registry;
_managementInterface = managementInterface;
_typeName = typeName;
_mbeanInfo = buildMBeanInfo();
}
+ public ManagedObjectRegistry getRegistry()
+ {
+ return _registry;
+ }
+
@Override
public MBeanInfo getMBeanInfo()
{
@@ -74,18 +78,15 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
return _managementInterface;
}
- public ManagedObject getParentObject()
- {
- return null;
- }
+ public abstract ManagedObject getParentObject();
+
public void register() throws JMException
{
- _registry = ApplicationRegistry.getInstance().getManagedObjectRegistry();
_registry.registerObject(this);
}
- public void unregister()
+ public void unregister() throws JMException
{
try
{
@@ -94,10 +95,6 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
_registry.unregisterObject(this);
}
}
- catch (JMException e)
- {
- LOGGER.error("Error unregistering managed object: " + this + ": " + e, e);
- }
finally
{
_registry = null;
@@ -112,7 +109,7 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
/**
* Created the ObjectName as per the JMX Specs
* @return ObjectName
- * @throws MalformedObjectNameException
+ * @throws javax.management.MalformedObjectNameException
*/
public ObjectName getObjectName() throws MalformedObjectNameException
{
diff --git a/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java
new file mode 100644
index 0000000000..c588b40de7
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java
@@ -0,0 +1,136 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.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<ServiceRegistration> _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<ServiceRegistration> registerServices(BundleContext ctx)
+ {
+ if (LOGGER.isInfoEnabled())
+ {
+ LOGGER.info("Registering jmx plugin: " + _bundleName);
+ }
+
+ List<ServiceRegistration> serviceRegistrations = new ArrayList<ServiceRegistration>();
+
+ 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<ServiceRegistration> iterator = _registeredServices.iterator(); iterator.hasNext();)
+ {
+ ServiceRegistration service = iterator.next();
+ service.unregister();
+ }
+ }
+}
diff --git a/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java
new file mode 100644
index 0000000000..dc9a712f90
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.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.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<String> 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/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java
index 869a816cf1..0648235077 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java
@@ -18,8 +18,38 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
+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.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.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;
@@ -38,39 +68,12 @@ import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.UnicastRemoteObject;
-import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-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 org.apache.commons.configuration.ConfigurationException;
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-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.security.auth.rmi.RMIPasswordAuthenticator;
/**
- * 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
@@ -195,8 +198,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
}
//add a JMXAuthenticator implementation the env map to authenticate the RMI based JMX connector server
- RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator();
- rmipa.setAuthenticationManager(appRegistry.getAuthenticationManager(new InetSocketAddress(_jmxPortRegistryServer)));
+ RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator(new InetSocketAddress(_jmxPortRegistryServer));
HashMap<String,Object> env = new HashMap<String,Object>();
env.put(JMXConnectorServer.AUTHENTICATOR, rmipa);
@@ -236,14 +238,14 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
* An instance of NotificationListener (mapCleanupListener) will be responsible for removing these Map
* entries.
*
- * @see javax.management.remote.rmi.RMIJRMPServerImpl#makeClient(java.lang.String, javax.security.auth.Subject)
+ * @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 Principal principal = subject.getPrincipals().iterator().next();
- connectionIdUsernameMap.put(connectionId, principal.getName());
+ final UsernamePrincipal usernamePrincipalFromSubject = UsernamePrincipal.getUsernamePrincipalFromSubject(subject);
+ connectionIdUsernameMap.put(connectionId, usernamePrincipalFromSubject.getName());
return makeClient;
}
};
@@ -252,7 +254,6 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
final NotificationListener mapCleanupListener = new NotificationListener()
{
- @Override
public void handleNotification(Notification notification, Object handback)
{
final String connectionId = ((JMXConnectionNotification) notification).getConnectionId();
@@ -310,6 +311,8 @@ 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
}
@@ -433,6 +436,8 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
//Stops the JMXConnectorServer and RMIRegistry, then unregisters any remaining MBeans from the MBeanServer
public void close()
{
+ _log.debug("close() called");
+
if (_cs != null)
{
// Stopping the JMX ConnectorServer
@@ -443,24 +448,28 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
}
catch (IOException e)
{
- _log.error("Exception while closing the JMX ConnectorServer: " + e.getMessage());
+ _log.error("Exception while closing the JMX ConnectorServer: ", e);
}
}
-
+
if (_rmiRegistry != null)
{
// Stopping the RMI registry
CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _jmxPortRegistryServer));
try
{
- UnicastRemoteObject.unexportObject(_rmiRegistry, false);
+ boolean success = UnicastRemoteObject.unexportObject(_rmiRegistry, false);
+ if (!success)
+ {
+ _log.warn("Failed to unexport object " + _rmiRegistry);
+ }
}
catch (NoSuchObjectException e)
{
- _log.error("Exception while closing the RMI Registry: " + e.getMessage());
+ _log.error("Exception while closing the RMI Registry: ", e);
}
}
-
+
//ObjectName query to gather all Qpid related MBeans
ObjectName mbeanNameQuery = null;
try
diff --git a/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java
new file mode 100644
index 0000000000..7519cea4db
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.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.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.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.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 Map<ConfiguredObject, AMQManagedObject> _children = new HashMap<ConfiguredObject, AMQManagedObject>();
+
+ 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);
+ }
+
+ 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<MBeanProvider> 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
+ * <b>only</b> those classes which are visible to the classloader of this OSGI bundle.
+ */
+ private Iterator<MBeanProvider> getMBeanProviderIterator()
+ {
+ return ServiceLoader.load(MBeanProvider.class, BUNDLE_CLASSLOADER).iterator();
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanIntrospector.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java
index 89b74f939d..79ddc8cfc0 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanIntrospector.java
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
+package org.apache.qpid.server.jmx;
import org.apache.qpid.management.common.mbeans.annotations.MBeanAttribute;
import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
@@ -43,7 +43,8 @@ import java.util.List;
* @author Bhupendra Bhardwaj
* @version 0.1
*/
-class MBeanIntrospector {
+class MBeanIntrospector
+{
private static final String _defaultAttributeDescription = "Management attribute";
private static final String _defaultOerationDescription = "Management operation";
@@ -58,7 +59,7 @@ class MBeanIntrospector {
* Introspects the management interface class for MBean attributes.
* @param interfaceClass
* @return MBeanAttributeInfo[]
- * @throws NotCompliantMBeanException
+ * @throws javax.management.NotCompliantMBeanException
*/
static MBeanAttributeInfo[] getMBeanAttributesInfo(Class interfaceClass)
throws NotCompliantMBeanException
@@ -221,7 +222,7 @@ class MBeanIntrospector {
* @param attribute
* @param list
* @return attribute index no. -1 if attribtue doesn't exist
- * @throws NotCompliantMBeanException
+ * @throws javax.management.NotCompliantMBeanException
*/
private static int getIndexIfAlreadyExists(MBeanAttributeInfo attribute,
List<MBeanAttributeInfo> list)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
index 651372db16..49f06d5121 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
@@ -18,10 +18,11 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
+package org.apache.qpid.server.jmx;
import org.apache.log4j.Logger;
+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;
@@ -174,41 +175,40 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
}
methodName = getMethodName(method, args);
- if (isAccessMethod(methodName) || impact == MBeanOperationInfo.INFO)
- {
- // Check for read-only method invocation permission
+ if (isAccessMethod(methodName) || impact == MBeanOperationInfo.INFO)
+ {
+ // Check for read-only method invocation permission
if (!security.authoriseMethod(Operation.ACCESS, type, methodName))
{
throw new SecurityException("Permission denied: Access " + methodName);
}
- }
- else
- {
- // Check for setting properties permission
- if (!security.authoriseMethod(Operation.UPDATE, type, methodName))
- {
- throw new SecurityException("Permission denied: Update " + methodName);
- }
- }
-
- boolean oldAccessChecksDisabled = false;
- if(_managementRightsInferAllAccess)
- {
- oldAccessChecksDisabled = SecurityManager.setAccessChecksDisabled(true);
- }
-
- try
- {
- // Actually invoke the method
- return method.invoke(_mbs, args);
- }
- finally
- {
- if(_managementRightsInferAllAccess)
- {
- SecurityManager.setAccessChecksDisabled(oldAccessChecksDisabled);
- }
- }
+ }
+ else
+ {
+ // Check for setting properties permission
+ if (!security.authoriseMethod(Operation.UPDATE, type, methodName))
+ {
+ throw new SecurityException("Permission denied: Update " + methodName);
+ }
+ }
+
+ boolean oldAccessChecksDisabled = false;
+ if(_managementRightsInferAllAccess)
+ {
+ oldAccessChecksDisabled = SecurityManager.setAccessChecksDisabled(true);
+ }
+
+ try
+ {
+ return doInvokeWrappingWithManagementActor(method, args);
+ }
+ finally
+ {
+ if(_managementRightsInferAllAccess)
+ {
+ SecurityManager.setAccessChecksDisabled(oldAccessChecksDisabled);
+ }
+ }
}
catch (InvocationTargetException e)
{
@@ -216,25 +216,40 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
}
}
+ private Object doInvokeWrappingWithManagementActor(Method method,
+ Object[] args) throws IllegalAccessException,
+ InvocationTargetException
+ {
+ try
+ {
+ CurrentActor.set(_logActor);
+ return method.invoke(_mbs, args);
+ }
+ finally
+ {
+ CurrentActor.remove();
+ }
+ }
+
private String getType(Method method, Object[] args)
- {
- if (args[0] instanceof ObjectName)
- {
- ObjectName object = (ObjectName) args[0];
- String type = object.getKeyProperty("type");
-
- return type;
- }
- return null;
+ {
+ if (args[0] instanceof ObjectName)
+ {
+ ObjectName object = (ObjectName) args[0];
+ String type = object.getKeyProperty("type");
+
+ return type;
+ }
+ return null;
}
private String getVirtualHost(Method method, Object[] args)
- {
+ {
if (args[0] instanceof ObjectName)
{
ObjectName object = (ObjectName) args[0];
String vhost = object.getKeyProperty("VirtualHost");
-
+
if(vhost != null)
{
try
@@ -253,7 +268,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
}
return null;
}
-
+
private String getMethodName(Method method, Object[] args)
{
String methodName = method.getName();
@@ -274,7 +289,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
methodName = (String) args[1];
}
}
-
+
return methodName;
}
@@ -289,7 +304,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
{
return -1;
}
-
+
try
{
//Get the impact attribute
diff --git a/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java
new file mode 100644
index 0000000000..83909dbe72
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.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.jmx;
+
+import java.util.ServiceLoader;
+
+import javax.management.JMException;
+import javax.management.StandardMBean;
+
+import org.apache.qpid.server.model.ConfiguredObject;
+
+/**
+ * A provider of an mbean implementation.
+ *
+ * Provider implementations are advertised as services and loaded via {@link ServiceLoader}.
+ */
+public interface MBeanProvider
+{
+ /**
+ * Tests whether a <code>child</code> can be managed by the mbean
+ * provided by this provider.
+ */
+ boolean isChildManageableByMBean(ConfiguredObject child);
+
+ /**
+ * Creates a mbean for this child. This method should only be called if
+ * {@link #isChildManageableByMBean(ConfiguredObject)} has previously returned true.
+ *
+ * @return newly created mbean
+ */
+ StandardMBean createMBean(ConfiguredObject child, StandardMBean parent) throws JMException;
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java
index 483b325455..40b778fd93 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java
@@ -18,9 +18,7 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
-
-import org.apache.qpid.AMQException;
+package org.apache.qpid.server.jmx;
import javax.management.JMException;
import javax.management.MalformedObjectNameException;
@@ -46,14 +44,14 @@ public interface ManagedObject
ManagedObject getParentObject();
- void register() throws AMQException, JMException;
+ void register() throws JMException;
- void unregister() throws AMQException;
+ void unregister() throws JMException;
/**
* Returns the ObjectName required for the mbeanserver registration.
* @return ObjectName
- * @throws MalformedObjectNameException
+ * @throws javax.management.MalformedObjectNameException
*/
ObjectName getObjectName() throws MalformedObjectNameException;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java
index b3323c569c..2ae0ac7052 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java
@@ -18,10 +18,9 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
+package org.apache.qpid.server.jmx;
import org.apache.commons.configuration.ConfigurationException;
-
import org.apache.qpid.common.Closeable;
import javax.management.JMException;
diff --git a/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java
new file mode 100644
index 0000000000..4115f9f363
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java
@@ -0,0 +1,196 @@
+package org.apache.qpid.server.jmx.mbeans;
+
+import javax.management.NotCompliantMBeanException;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.VirtualHost;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+abstract class AbstractStatisticsGatheringMBean<T extends ConfiguredObject> extends AMQManagedObject
+{
+ private long _lastStatUpdateTime;
+ private long _statUpdatePeriod = 5000L;
+ private long _lastMessagesReceived;
+ private long _lastMessagesSent;
+ private long _lastBytesReceived;
+ private long _lastBytesSent;
+ private double _messageReceivedRate;
+ private double _messageSentRate;
+ private double _bytesReceivedRate;
+ private double _bytesSentRate;
+ private double _peakMessageReceivedRate;
+ private double _peakMessageSentRate;
+ private double _peakBytesReceivedRate;
+ private double _peakBytesSentRate;
+ private final T _configuredObject;
+
+ protected AbstractStatisticsGatheringMBean(Class<?> managementInterface,
+ String typeName,
+ ManagedObjectRegistry registry,
+ T object) throws NotCompliantMBeanException
+ {
+ super(managementInterface, typeName, registry);
+ _configuredObject = object;
+ initStats();
+ }
+
+ protected void initStats()
+ {
+ _lastStatUpdateTime = System.currentTimeMillis();
+ }
+
+ protected synchronized void updateStats()
+ {
+ long time = System.currentTimeMillis();
+ final long period = time - _lastStatUpdateTime;
+ if(period > _statUpdatePeriod)
+ {
+ long messagesReceived = getStatistic(VirtualHost.MESSAGES_IN);
+ long messagesSent = getStatistic(VirtualHost.MESSAGES_OUT);
+ long bytesReceived = getStatistic(VirtualHost.BYTES_IN);
+ long bytesSent = getStatistic(VirtualHost.BYTES_OUT);
+
+ double messageReceivedRate = (double)(messagesReceived - _lastMessagesReceived) / (double)period;
+ double messageSentRate = (double)(messagesSent - _lastMessagesSent) / (double)period;
+ double bytesReceivedRate = (double)(bytesReceived - _lastBytesReceived) / (double)period;
+ double bytesSentRate = (double)(bytesSent - _lastBytesSent) / (double)period;
+
+ _lastMessagesReceived = messagesReceived;
+ _lastMessagesSent = messagesSent;
+ _lastBytesReceived = bytesReceived;
+ _lastBytesSent = bytesSent;
+
+ _messageReceivedRate = messageReceivedRate;
+ _messageSentRate = messageSentRate;
+ _bytesReceivedRate = bytesReceivedRate;
+ _bytesSentRate = bytesSentRate;
+
+ if(messageReceivedRate > _peakMessageReceivedRate)
+ {
+ _peakMessageReceivedRate = messageReceivedRate;
+ }
+
+ if(messageSentRate > _peakMessageSentRate)
+ {
+ _peakMessageSentRate = messageSentRate;
+ }
+
+ if(bytesReceivedRate > _peakBytesReceivedRate)
+ {
+ _peakBytesReceivedRate = bytesReceivedRate;
+ }
+
+ if(bytesSentRate > _peakBytesSentRate)
+ {
+ _peakBytesSentRate = bytesSentRate;
+ }
+
+ }
+ }
+
+ private long getStatistic(String name)
+ {
+ return (Long) getConfiguredObject().getStatistics().getStatistic(name);
+ }
+
+ public synchronized void resetStatistics() throws Exception
+ {
+ updateStats();
+ //TODO - implement resetStatistics()
+ }
+
+ public synchronized double getPeakMessageDeliveryRate()
+ {
+ updateStats();
+ return _peakMessageSentRate;
+ }
+
+ public synchronized double getPeakDataDeliveryRate()
+ {
+ updateStats();
+ return _peakBytesSentRate;
+ }
+
+ public synchronized double getMessageDeliveryRate()
+ {
+ updateStats();
+ return _messageSentRate;
+ }
+
+ public synchronized double getDataDeliveryRate()
+ {
+ updateStats();
+ return _bytesSentRate;
+ }
+
+ public synchronized long getTotalMessagesDelivered()
+ {
+ updateStats();
+ return getStatistic(Connection.MESSAGES_OUT);
+ }
+
+ public synchronized long getTotalDataDelivered()
+ {
+ updateStats();
+ return getStatistic(Connection.BYTES_OUT);
+ }
+
+ protected final T getConfiguredObject()
+ {
+ return _configuredObject;
+ }
+
+ public synchronized double getPeakMessageReceiptRate()
+ {
+ updateStats();
+ return _peakMessageReceivedRate;
+ }
+
+ public synchronized double getPeakDataReceiptRate()
+ {
+ updateStats();
+ return _peakBytesReceivedRate;
+ }
+
+ public synchronized double getMessageReceiptRate()
+ {
+ updateStats();
+ return _messageReceivedRate;
+ }
+
+ public synchronized double getDataReceiptRate()
+ {
+ updateStats();
+ return _bytesReceivedRate;
+ }
+
+ public synchronized long getTotalMessagesReceived()
+ {
+ updateStats();
+ return getStatistic(Connection.MESSAGES_IN);
+ }
+
+ public synchronized long getTotalDataReceived()
+ {
+ updateStats();
+ return getStatistic(Connection.BYTES_IN);
+ }
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java
index f0ca5dc139..beffb4eaa9 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java
@@ -18,20 +18,24 @@
* under the License.
*
*/
-package org.apache.qpid.server.configuration.management;
+package org.apache.qpid.server.jmx.mbeans;
import org.apache.qpid.management.common.mbeans.ConfigurationManagement;
-import org.apache.qpid.server.management.AMQManagedObject;
+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() throws NotCompliantMBeanException
+ public ConfigurationManagementMBean(ManagedObjectRegistry registry) throws JMException
{
- super(ConfigurationManagement.class, ConfigurationManagement.TYPE);
+ super(ConfigurationManagement.class, ConfigurationManagement.TYPE, registry);
+ register();
}
public String getObjectInstanceName()
@@ -44,4 +48,9 @@ public class ConfigurationManagementMBean extends AMQManagedObject implements Co
ApplicationRegistry.getInstance().getConfiguration().reparseConfigFileSecuritySections();
}
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return null;
+ }
}
diff --git a/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java
new file mode 100644
index 0000000000..024ee39318
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java
@@ -0,0 +1,183 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.jmx.mbeans;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Date;
+import javax.management.JMException;
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import org.apache.qpid.management.common.mbeans.ManagedConnection;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Session;
+import org.apache.qpid.server.model.Statistics;
+
+public class ConnectionMBean extends AbstractStatisticsGatheringMBean<Connection> implements ManagedConnection
+{
+ private static final OpenType[] CHANNEL_ATTRIBUTE_TYPES =
+ { SimpleType.INTEGER, SimpleType.BOOLEAN, SimpleType.STRING, SimpleType.INTEGER, SimpleType.BOOLEAN };
+ private static final CompositeType CHANNEL_TYPE;
+ private static final TabularType CHANNELS_TYPE;
+
+ static
+ {
+ try
+ {
+ CHANNEL_TYPE = new CompositeType("Channel", "Channel Details", COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]),
+ COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]),
+ CHANNEL_ATTRIBUTE_TYPES);
+ CHANNELS_TYPE = new TabularType("Channels", "Channels", CHANNEL_TYPE, (String[]) TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()]));
+ }
+ catch (JMException ex)
+ {
+ // This is not expected to ever occur.
+ throw new RuntimeException("Got JMException in static initializer.", ex);
+ }
+ }
+
+
+ private final VirtualHostMBean _virtualHostMBean;
+
+ public ConnectionMBean(Connection conn, VirtualHostMBean virtualHostMBean) throws JMException
+ {
+ super(ManagedConnection.class, ManagedConnection.TYPE, virtualHostMBean.getRegistry(), conn);
+ _virtualHostMBean = virtualHostMBean;
+ register();
+ }
+
+ public String getObjectInstanceName()
+ {
+ return ObjectName.quote(getRemoteAddress());
+ }
+
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return _virtualHostMBean;
+ }
+
+ public String getClientId()
+ {
+ return (String) getConfiguredObject().getAttribute(Connection.CLIENT_ID);
+ }
+
+ public String getAuthorizedId()
+ {
+ return (String) getConfiguredObject().getAttribute(Connection.PRINCIPAL);
+ }
+
+ public String getVersion()
+ {
+ return (String) getConfiguredObject().getAttribute(Connection.CLIENT_VERSION);
+ }
+
+ public String getRemoteAddress()
+ {
+ return (String) getConfiguredObject().getAttribute(Connection.REMOTE_ADDRESS);
+ }
+
+ public Date getLastIoTime()
+ {
+ Long lastIo = (Long) getConfiguredObject().getStatistics().getStatistic(Connection.LAST_IO_TIME);
+ return new Date(lastIo);
+ }
+
+ public Long getMaximumNumberOfChannels()
+ {
+ return (Long) getConfiguredObject().getAttribute(Connection.SESSION_COUNT_LIMIT);
+ }
+
+ public TabularData channels() throws IOException, JMException
+ {
+ TabularDataSupport sessionTable = new TabularDataSupport(CHANNELS_TYPE);
+ Collection<Session> list = getConfiguredObject().getSessions();
+
+ for (Session session : list)
+ {
+ Statistics statistics = session.getStatistics();
+ Long txnBegins = (Long) statistics.getStatistic(Session.LOCAL_TRANSACTION_BEGINS);
+ Integer channelId = (Integer) session.getAttribute(Session.CHANNEL_ID);
+ int unacknowledgedSize = ((Number) statistics.getStatistic(Session.UNACKNOWLEDGED_MESSAGES)).intValue();
+ boolean blocked = (Boolean) session.getAttribute(Session.PRODUCER_FLOW_BLOCKED);
+ boolean isTransactional = (txnBegins>0l);
+
+ Object[] itemValues =
+ {
+ channelId,
+ isTransactional,
+ null, // TODO - default queue (which is meaningless)
+ unacknowledgedSize,
+ blocked
+ };
+
+ CompositeData sessionData = new CompositeDataSupport(CHANNEL_TYPE,
+ COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues);
+ sessionTable.put(sessionData);
+ }
+
+ return sessionTable;
+ }
+
+ public void commitTransactions(int channelId) throws JMException
+ {
+ throw buildUnsupportedException();
+ }
+
+ public void rollbackTransactions(int channelId) throws JMException
+ {
+ throw buildUnsupportedException();
+ }
+
+ public void closeConnection() throws Exception
+ {
+ getConfiguredObject().delete();
+ }
+
+ public boolean isStatisticsEnabled()
+ {
+ return true;
+ }
+
+ public void setStatisticsEnabled(boolean enabled)
+ {
+ // TODO - Implement setStatisticsEnabled
+ updateStats();
+ }
+
+ private JMException buildUnsupportedException() throws JMException
+ {
+ String msg = "Operation not supported";
+ JMException jmException = new JMException(msg);
+ jmException.initCause(new UnsupportedOperationException(msg));
+ return jmException;
+ }
+}
diff --git a/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java
new file mode 100644
index 0000000000..eb7e716af8
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java
@@ -0,0 +1,323 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.ManagedExchange;
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanOperationParameter;
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObject;
+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.VirtualHost;
+
+import javax.management.JMException;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ExchangeMBean extends AMQManagedObject implements ManagedExchange
+{
+
+ private static final String[] TABULAR_UNIQUE_INDEX_ARRAY =
+ TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()]);
+
+ private static final String[] COMPOSITE_ITEM_NAMES_ARRAY =
+ COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]);
+
+ private static final String[] COMPOSITE_ITEM_DESCRIPTIONS_ARRAY =
+ COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]);
+
+ private static final OpenType[] BINDING_ITEM_TYPES;
+ private static final CompositeType BINDING_DATA_TYPE;
+ private static final OpenType[] HEADERS_BINDING_ITEM_TYPES;
+
+
+ private static final CompositeType HEADERS_BINDING_DATA_TYPE;
+
+ private static final String[] HEADERS_COMPOSITE_ITEM_NAMES_ARRAY =
+ HEADERS_COMPOSITE_ITEM_NAMES.toArray(new String[HEADERS_COMPOSITE_ITEM_NAMES.size()]);
+
+ private static final String[] HEADERS_COMPOSITE_ITEM_DESCS_ARRAY =
+ HEADERS_COMPOSITE_ITEM_DESC.toArray(new String[HEADERS_COMPOSITE_ITEM_DESC.size()]);
+ private static final String[] HEADERS_TABULAR_UNIQUE_INDEX_ARRAY =
+ HEADERS_TABULAR_UNIQUE_INDEX.toArray(new String[HEADERS_TABULAR_UNIQUE_INDEX.size()]);
+ public static final String HEADERS_EXCHANGE_TYPE = "headers";
+
+ static
+ {
+ try
+ {
+ BINDING_ITEM_TYPES = new OpenType[] {SimpleType.STRING, new ArrayType(1, SimpleType.STRING)};
+
+ BINDING_DATA_TYPE= new CompositeType("Exchange Binding", "Binding key and Queue names",
+ COMPOSITE_ITEM_NAMES_ARRAY,
+ COMPOSITE_ITEM_DESCRIPTIONS_ARRAY,
+ BINDING_ITEM_TYPES);
+
+ HEADERS_BINDING_ITEM_TYPES = new OpenType[] {SimpleType.INTEGER,
+ SimpleType.STRING,
+ new ArrayType(1, SimpleType.STRING)};
+
+ HEADERS_BINDING_DATA_TYPE = new CompositeType("Exchange Binding", "Queue name and header bindings",
+ HEADERS_COMPOSITE_ITEM_NAMES_ARRAY,
+ HEADERS_COMPOSITE_ITEM_DESCS_ARRAY,
+ HEADERS_BINDING_ITEM_TYPES);
+
+
+ }
+ catch(OpenDataException e)
+ {
+ throw new RuntimeException("Unexpected Error creating ArrayType", e);
+ }
+ }
+
+
+ private final Exchange _exchange;
+ private final VirtualHostMBean _vhostMBean;
+
+ protected ExchangeMBean(Exchange exchange, VirtualHostMBean virtualHostMBean)
+ throws JMException
+ {
+ super(ManagedExchange.class, ManagedExchange.TYPE, virtualHostMBean.getRegistry());
+ _exchange = exchange;
+ _vhostMBean = virtualHostMBean;
+
+ register();
+ }
+
+ public String getObjectInstanceName()
+ {
+ return ObjectName.quote(getName());
+ }
+
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return _vhostMBean;
+ }
+
+ public ObjectName getObjectName() throws MalformedObjectNameException
+ {
+ String objNameString = super.getObjectName().toString();
+ objNameString = objNameString + ",ExchangeType=" + getExchangeType();
+ return new ObjectName(objNameString);
+ }
+
+
+ public String getName()
+ {
+ return _exchange.getName();
+ }
+
+ public String getExchangeType()
+ {
+ return _exchange.getExchangeType();
+ }
+
+ public Integer getTicketNo()
+ {
+ return 0;
+ }
+
+ public boolean isDurable()
+ {
+ return _exchange.isDurable();
+ }
+
+ public boolean isAutoDelete()
+ {
+ return _exchange.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE;
+ }
+
+ public TabularData bindings() throws IOException, JMException
+ {
+ if(HEADERS_EXCHANGE_TYPE.equals(_exchange.getExchangeType()))
+ {
+ return getHeadersBindings(_exchange.getBindings());
+ }
+ else
+ {
+ return getNonHeadersBindings(_exchange.getBindings());
+ }
+ }
+
+
+ private TabularData getHeadersBindings(Collection<Binding> bindings) throws OpenDataException
+ {
+ TabularType bindinglistDataType =
+ new TabularType("Exchange Bindings", "List of exchange bindings for " + getName(),
+ HEADERS_BINDING_DATA_TYPE,
+ HEADERS_TABULAR_UNIQUE_INDEX_ARRAY);
+
+ TabularDataSupport bindingList = new TabularDataSupport(bindinglistDataType);
+ int count = 1;
+ for (Binding binding : bindings)
+ {
+
+ String queueName = binding.getParent(Queue.class).getName();
+
+
+ Map<String,Object> headerMappings = binding.getArguments();
+
+ final List<String> mappingList = new ArrayList<String>();
+
+ if(headerMappings != null)
+ {
+ for(Map.Entry<String,Object> entry : headerMappings.entrySet())
+ {
+
+ mappingList.add(entry.getKey() + "=" + entry.getValue());
+ }
+ }
+
+
+ Object[] bindingItemValues = {count++, queueName, mappingList.toArray(new String[0])};
+ CompositeData bindingData = new CompositeDataSupport(HEADERS_BINDING_DATA_TYPE,
+ HEADERS_COMPOSITE_ITEM_NAMES_ARRAY,
+ bindingItemValues);
+ bindingList.put(bindingData);
+ }
+
+ return bindingList;
+
+ }
+
+ private TabularData getNonHeadersBindings(Collection<Binding> bindings) throws OpenDataException
+ {
+
+ TabularType bindinglistDataType =
+ new TabularType("Exchange Bindings", "Exchange Bindings for " + getName(),
+ BINDING_DATA_TYPE,
+ TABULAR_UNIQUE_INDEX_ARRAY);
+
+ TabularDataSupport bindingList = new TabularDataSupport(bindinglistDataType);
+
+ Map<String, List<String>> bindingMap = new HashMap<String, List<String>>();
+
+ for (Binding binding : bindings)
+ {
+ String key = "fanout".equals(_exchange.getExchangeType()) ? "*" : binding.getName();
+ List<String> queueList = bindingMap.get(key);
+ if(queueList == null)
+ {
+ queueList = new ArrayList<String>();
+ bindingMap.put(key, queueList);
+ }
+ queueList.add(binding.getParent(Queue.class).getName());
+
+ }
+
+ for(Map.Entry<String, List<String>> entry : bindingMap.entrySet())
+ {
+ Object[] bindingItemValues = {entry.getKey(), entry.getValue().toArray(new String[0])};
+ CompositeData bindingData = new CompositeDataSupport(BINDING_DATA_TYPE,
+ COMPOSITE_ITEM_NAMES_ARRAY,
+ bindingItemValues);
+ bindingList.put(bindingData);
+ }
+
+ return bindingList;
+ }
+
+ public void createNewBinding(String queueName, String binding) throws JMException
+ {
+ final Map<String,Object> arguments = new HashMap<String, Object>();
+
+ if(HEADERS_EXCHANGE_TYPE.equals(_exchange.getExchangeType()))
+ {
+ final String[] bindings = binding.split(",");
+ for (int i = 0; i < bindings.length; i++)
+ {
+ final String[] keyAndValue = bindings[i].split("=");
+ if (keyAndValue == null || keyAndValue.length == 0 || keyAndValue.length > 2 || keyAndValue[0].length() == 0)
+ {
+ throw new JMException("Format for headers binding should be \"<attribute1>=<value1>,<attribute2>=<value2>\" ");
+ }
+
+ if(keyAndValue.length == 1)
+ {
+ //no value was given, only a key. Use an empty value to signal match on key presence alone
+ arguments.put(keyAndValue[0], "");
+ }
+ else
+ {
+ arguments.put(keyAndValue[0], keyAndValue[1]);
+ }
+ }
+ }
+
+ Queue queue = null;
+ VirtualHost vhost = _exchange.getParent(VirtualHost.class);
+ for(Queue aQueue : vhost.getQueues())
+ {
+ if(aQueue.getName().equals(queueName))
+ {
+ queue = aQueue;
+ break;
+ }
+ }
+ _exchange.createBinding(binding, queue, arguments, Collections.EMPTY_MAP);
+ }
+
+ public void removeBinding(String queueName, String bindingKey)
+ throws IOException, JMException
+ {
+ Queue queue = null;
+ VirtualHost vhost = _exchange.getParent(VirtualHost.class);
+ for(Queue aQueue : vhost.getQueues())
+ {
+ if(aQueue.getName().equals(queueName))
+ {
+ queue = aQueue;
+ break;
+ }
+ }
+
+ for(Binding binding : _exchange.getBindings())
+ {
+ if(queue.equals(binding.getParent(Queue.class)) && bindingKey.equals(binding.getName()))
+ {
+ binding.delete();
+ }
+ }
+
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java
index c699dff175..9ff45979ca 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java
@@ -18,7 +18,7 @@
*
*
*/
-package org.apache.qpid.server.logging.management;
+package org.apache.qpid.server.jmx.mbeans;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
@@ -27,16 +27,17 @@ import org.apache.log4j.xml.Log4jEntityResolver;
import org.apache.log4j.xml.QpidLog4JConfigurator;
import org.apache.log4j.xml.QpidLog4JConfigurator.IllegalLoggerLevelException;
import org.apache.log4j.xml.QpidLog4JConfigurator.QpidLog4JSaxErrorHandler;
+import org.apache.qpid.management.common.mbeans.LoggingManagement;
+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.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.apache.qpid.management.common.mbeans.LoggingManagement;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.management.AMQManagedObject;
-
import javax.management.JMException;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
@@ -107,11 +108,14 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
}
}
- public LoggingManagementMBean(String log4jConfigFileName, int log4jLogWatchInterval) throws JMException
+ public LoggingManagementMBean(String log4jConfigFileName,
+ int log4jLogWatchInterval,
+ ManagedObjectRegistry registry) throws JMException
{
- super(LoggingManagement.class, LoggingManagement.TYPE);
+ super(LoggingManagement.class, LoggingManagement.TYPE, registry);
_log4jConfigFileName = log4jConfigFileName;
_log4jLogWatchInterval = log4jLogWatchInterval;
+ register();
}
public String getObjectInstanceName()
@@ -819,4 +823,10 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
LOCK.unlock();
}
}
+
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return null;
+ }
}
diff --git a/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java
new file mode 100644
index 0000000000..76d545a5f7
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java
@@ -0,0 +1,692 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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 java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.management.JMException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.Notification;
+import javax.management.ObjectName;
+import javax.management.OperationsException;
+import javax.management.monitor.MonitorNotification;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+import org.apache.commons.lang.time.FastDateFormat;
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+import org.apache.qpid.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.ConfiguredObjectFinder;
+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.QueueNotificationListener;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.NotificationCheck;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.QueueEntryVisitor;
+
+public class QueueMBean extends AMQManagedObject implements ManagedQueue, QueueNotificationListener
+{
+ private static final String[] VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC_ARRAY =
+ VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.size()]);
+
+ private static final OpenType[] MSG_ATTRIBUTE_TYPES;
+ private static final CompositeType MSG_DATA_TYPE;
+ private static final TabularType MSG_LIST_DATA_TYPE;
+ private static final CompositeType MSG_CONTENT_TYPE;
+ private static final String[] VIEW_MSG_COMPOSIT_ITEM_NAMES_ARRAY = VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(
+ new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]);
+
+ static
+ {
+
+ try
+ {
+ MSG_ATTRIBUTE_TYPES = new OpenType[] {
+ SimpleType.LONG, // For message id
+ new ArrayType(1, SimpleType.STRING), // For header attributes
+ SimpleType.LONG, // For size
+ SimpleType.BOOLEAN, // For redelivered
+ SimpleType.LONG, // For queue position
+ SimpleType.INTEGER // For delivery count}
+ };
+
+ MSG_DATA_TYPE = new CompositeType("Message", "AMQ Message",
+ VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC_ARRAY,
+ VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC_ARRAY, MSG_ATTRIBUTE_TYPES);
+
+ MSG_LIST_DATA_TYPE = new TabularType("Messages", "List of messages", MSG_DATA_TYPE,
+ VIEW_MSGS_TABULAR_UNIQUE_INDEX.toArray(new String[VIEW_MSGS_TABULAR_UNIQUE_INDEX.size()]));
+
+ OpenType[] msgContentAttrs = new OpenType[] {
+ SimpleType.LONG, // For message id
+ SimpleType.STRING, // For MimeType
+ SimpleType.STRING, // For MimeType
+ new ArrayType(SimpleType.BYTE, true) // For message content
+ };
+
+
+ MSG_CONTENT_TYPE = new CompositeType("Message Content", "AMQ Message Content",
+ VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]),
+ VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]),
+ msgContentAttrs);
+
+ }
+ catch (OpenDataException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private final Queue _queue;
+ private final VirtualHostMBean _vhostMBean;
+
+ /** Date/time format used for message expiration and message timestamp formatting */
+ public static final String JMSTIMESTAMP_DATETIME_FORMAT = "MM-dd-yy HH:mm:ss.SSS z";
+
+ private static final FastDateFormat FAST_DATE_FORMAT = FastDateFormat.getInstance(JMSTIMESTAMP_DATETIME_FORMAT);
+
+ public QueueMBean(Queue queue, VirtualHostMBean virtualHostMBean) throws JMException
+ {
+ super(ManagedQueue.class, ManagedQueue.TYPE, virtualHostMBean.getRegistry());
+ _queue = queue;
+ _vhostMBean = virtualHostMBean;
+ register();
+ _queue.setNotificationListener(this);
+ }
+
+ public ManagedObject getParentObject()
+ {
+ return _vhostMBean;
+ }
+
+ public String getObjectInstanceName()
+ {
+ return ObjectName.quote(getName());
+ }
+
+ public String getName()
+ {
+ return _queue.getName();
+ }
+
+
+ public Integer getMessageCount()
+ {
+ return getStatisticValue(Queue.QUEUE_DEPTH_MESSAGES).intValue();
+ }
+
+ private Number getStatisticValue(String name)
+ {
+ final Number statistic = (Number) _queue.getStatistics().getStatistic(name);
+ return statistic == null ? Integer.valueOf(0) : statistic;
+ }
+
+ public Integer getMaximumDeliveryCount()
+ {
+ return (Integer) _queue.getAttribute(Queue.MAXIMUM_DELIVERY_ATTEMPTS);
+ }
+
+ public Long getReceivedMessageCount()
+ {
+ return getStatisticValue(Queue.TOTAL_ENQUEUED_MESSAGES).longValue();
+ }
+
+ public Long getQueueDepth()
+ {
+ return getStatisticValue(Queue.QUEUE_DEPTH_BYTES).longValue();
+ }
+
+ public Integer getActiveConsumerCount()
+ {
+ return getStatisticValue(Queue.CONSUMER_COUNT_WITH_CREDIT).intValue();
+ }
+
+ public Integer getConsumerCount()
+ {
+ return getStatisticValue(Queue.CONSUMER_COUNT).intValue();
+ }
+
+ public String getOwner()
+ {
+ return (String) _queue.getAttribute(Queue.OWNER);
+ }
+
+ @Override
+ public String getQueueType()
+ {
+ return (String) _queue.getAttribute(Queue.TYPE);
+ }
+
+ public boolean isDurable()
+ {
+ return _queue.isDurable();
+ }
+
+ public boolean isAutoDelete()
+ {
+ return _queue.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE;
+ }
+
+ public Long getMaximumMessageAge()
+ {
+ return (Long) _queue.getAttribute(Queue.ALERT_THRESHOLD_MESSAGE_AGE);
+ }
+
+ public void setMaximumMessageAge(Long age)
+ {
+ _queue.setAttribute(Queue.ALERT_THRESHOLD_MESSAGE_AGE, getMaximumMessageAge(), age);
+ }
+
+ public Long getMaximumMessageSize()
+ {
+ return (Long) _queue.getAttribute(Queue.ALERT_THRESHOLD_MESSAGE_SIZE);
+ }
+
+ public void setMaximumMessageSize(Long size)
+ {
+ _queue.setAttribute(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, getMaximumMessageSize(), size);
+ }
+
+ public Long getMaximumMessageCount()
+ {
+ return (Long) _queue.getAttribute(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES);
+ }
+
+ public void setMaximumMessageCount(Long value)
+ {
+ _queue.setAttribute(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, getMaximumMessageCount(), value);
+ }
+
+ public Long getMaximumQueueDepth()
+ {
+ return (Long) _queue.getAttribute(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES);
+ }
+
+ public void setMaximumQueueDepth(Long value)
+ {
+ _queue.setAttribute(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, getMaximumQueueDepth(), value);
+ }
+
+ public Long getCapacity()
+ {
+ return (Long) _queue.getAttribute(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES);
+ }
+
+ public void setCapacity(Long value)
+ {
+ _queue.setAttribute(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, getCapacity(), value);
+ }
+
+ public Long getFlowResumeCapacity()
+ {
+ return (Long) _queue.getAttribute(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES);
+ }
+
+ public void setFlowResumeCapacity(Long value)
+ {
+ _queue.setAttribute(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, getFlowResumeCapacity(), value);
+ }
+
+ public boolean isFlowOverfull()
+ {
+ return (Boolean)_queue.getAttribute(Queue.QUEUE_FLOW_STOPPED);
+ }
+
+ public boolean isExclusive()
+ {
+ return (Boolean) _queue.getAttribute(Queue.EXCLUSIVE);
+ }
+
+ public void setExclusive(boolean exclusive)
+ {
+ _queue.setAttribute(Queue.EXCLUSIVE, isExclusive(), exclusive);
+ }
+
+ public void setAlternateExchange(String exchangeName) throws OperationsException
+ {
+ if (exchangeName == null || "".equals(exchangeName))
+ {
+ _queue.setAttribute(Queue.ALTERNATE_EXCHANGE, getAlternateExchange(), null);
+ }
+ else
+ {
+ VirtualHost virtualHost = _queue.getParent(VirtualHost.class);
+ Exchange exchange = findExchangeFromExchangeName(virtualHost, exchangeName);
+
+ _queue.setAttribute(Queue.ALTERNATE_EXCHANGE, getAlternateExchange(), exchange);
+ }
+ }
+
+ public String getAlternateExchange()
+ {
+ Exchange alternateExchange = (Exchange) _queue.getAttribute(Queue.ALTERNATE_EXCHANGE);
+ return alternateExchange == null ? null : alternateExchange.getName();
+ }
+
+ public TabularData viewMessages(int fromIndex, int toIndex)
+ throws IOException, JMException
+ {
+ return viewMessages((long)fromIndex, (long)toIndex);
+ }
+
+ public TabularData viewMessages(long startPosition, long endPosition)
+ throws IOException, JMException
+ {
+ if ((startPosition > endPosition) || (startPosition < 1))
+ {
+ throw new OperationsException("From Index = " + startPosition + ", To Index = " + endPosition
+ + "\n\"From Index\" should be greater than 0 and less than \"To Index\"");
+ }
+
+ if ((endPosition - startPosition) > Integer.MAX_VALUE)
+ {
+ throw new OperationsException("Specified MessageID interval is too large. Intervals must be less than 2^31 in size");
+ }
+
+
+ List<QueueEntry> messages = getMessages(startPosition, endPosition);
+
+ TabularDataSupport messageTable = new TabularDataSupport(MSG_LIST_DATA_TYPE);
+
+
+ // Create the tabular list of message header contents
+ long position = startPosition;
+
+ for (QueueEntry queueEntry : messages)
+ {
+ ServerMessage serverMsg = queueEntry.getMessage();
+ AMQMessageHeader header = serverMsg.getMessageHeader();
+ String[] headerAttributes =
+ {"reply-to = " + header.getReplyTo(),
+ "propertyFlags = ",
+ "ApplicationID = " + header.getAppId(),
+ "ClusterID = ",
+ "UserId = " + header.getUserId(),
+ "JMSMessageID = " + header.getMessageId(),
+ "JMSCorrelationID = " + header.getCorrelationId(),
+ "JMSDeliveryMode = " + (serverMsg.isPersistent() ? "Persistent" : "Non_Persistent"),
+ "JMSPriority = " + header.getPriority(),
+ "JMSType = " + header.getType(),
+ "JMSExpiration = " + (header.getExpiration() == 0 ? null : FAST_DATE_FORMAT.format(header.getExpiration())),
+ "JMSTimestamp = " + (header.getTimestamp() == 0 ? null : FAST_DATE_FORMAT.format(header.getTimestamp()))
+ };
+
+ Object[] itemValues = new Object[]{ serverMsg.getMessageNumber(),
+ headerAttributes,
+ serverMsg.getSize(),
+ queueEntry.isRedelivered(),
+ position,
+ queueEntry.getDeliveryCount()};
+
+ position++;
+
+ CompositeData messageData =
+ new CompositeDataSupport(MSG_DATA_TYPE, VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC_ARRAY, itemValues);
+ messageTable.put(messageData);
+ }
+
+ return messageTable;
+
+ }
+
+ public CompositeData viewMessageContent(long messageId)
+ throws IOException, JMException
+ {
+ QueueEntry entry = getMessage(messageId);
+ if(entry == null)
+ {
+ throw new OperationsException("AMQMessage with message id = " + messageId + " is not in the " + _queue.getName());
+ }
+
+ ServerMessage serverMsg = entry.getMessage();
+ final int bodySize = (int) serverMsg.getSize();
+
+ byte[] msgContent = new byte[bodySize];
+
+ ByteBuffer buf = ByteBuffer.wrap(msgContent);
+ int position = 0;
+
+ while(position < bodySize)
+ {
+ position += serverMsg.getContent(buf, position);
+
+ }
+
+ AMQMessageHeader header = serverMsg.getMessageHeader();
+
+ String mimeType = null, encoding = null;
+ if (header != null)
+ {
+ mimeType = header.getMimeType();
+
+ encoding = header.getEncoding();
+ }
+
+
+ Object[] itemValues = { messageId, mimeType, encoding, msgContent };
+
+ return new CompositeDataSupport(MSG_CONTENT_TYPE, VIEW_MSG_COMPOSIT_ITEM_NAMES_ARRAY, itemValues);
+
+
+ }
+
+ private QueueEntry getMessage(long messageId)
+ {
+ GetMessageVisitor visitor = new GetMessageVisitor(messageId);
+ _queue.visit(visitor);
+ return visitor.getEntry();
+
+ }
+
+ public void deleteMessageFromTop() throws IOException, JMException
+ {
+ VirtualHost vhost = _queue.getParent(VirtualHost.class);
+ vhost.executeTransaction(new VirtualHost.TransactionalOperation()
+ {
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+ _queue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ if(entry.acquire())
+ {
+ txn.dequeue(entry);
+ return true;
+ }
+ return false;
+ }
+ });
+
+ }
+ });
+
+ }
+
+ public Long clearQueue() throws IOException, JMException
+ {
+ VirtualHost vhost = _queue.getParent(VirtualHost.class);
+ final AtomicLong count = new AtomicLong();
+
+ vhost.executeTransaction(new VirtualHost.TransactionalOperation()
+ {
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+ _queue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ final ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ txn.dequeue(entry);
+ count.incrementAndGet();
+
+ }
+ return false;
+ }
+ });
+
+ }
+ });
+ return count.get();
+ }
+
+ public void moveMessages(final long fromMessageId, final long toMessageId, String toQueue)
+ throws IOException, JMException
+ {
+ if ((fromMessageId > toMessageId) || (fromMessageId < 1))
+ {
+ throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
+ }
+
+ VirtualHost vhost = _queue.getParent(VirtualHost.class);
+ final Queue destinationQueue = findQueueFromQueueName(vhost, toQueue);
+
+ vhost.executeTransaction(new VirtualHost.TransactionalOperation()
+ {
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+ _queue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ final ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ final long messageId = message.getMessageNumber();
+
+ if ((messageId >= fromMessageId)
+ && (messageId <= toMessageId))
+ {
+ txn.move(entry, destinationQueue);
+ }
+
+ }
+ return false;
+ }
+ });
+ }
+ });
+ }
+
+ public void deleteMessages(final long fromMessageId, final long toMessageId)
+ throws IOException, JMException
+ {
+ VirtualHost vhost = _queue.getParent(VirtualHost.class);
+ vhost.executeTransaction(new VirtualHost.TransactionalOperation()
+ {
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+ _queue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ final ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ final long messageId = message.getMessageNumber();
+
+ if ((messageId >= fromMessageId)
+ && (messageId <= toMessageId))
+ {
+ txn.dequeue(entry);
+ return true;
+ }
+ return false;
+ }
+ return true;
+ }
+ });
+ }
+ });
+ }
+
+ public void copyMessages(final long fromMessageId, final long toMessageId, String toQueue)
+ throws IOException, JMException
+ {
+ if ((fromMessageId > toMessageId) || (fromMessageId < 1))
+ {
+ throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
+ }
+
+ VirtualHost vhost = _queue.getParent(VirtualHost.class);
+ final Queue destinationQueue = findQueueFromQueueName(vhost, toQueue);
+
+ vhost.executeTransaction(new VirtualHost.TransactionalOperation()
+ {
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+ _queue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ final ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ final long messageId = message.getMessageNumber();
+
+ if ((messageId >= fromMessageId)
+ && (messageId <= toMessageId))
+ {
+ txn.copy(entry, destinationQueue);
+ }
+
+ }
+ return false;
+ }
+ });
+ }
+ });
+ }
+
+ private List<QueueEntry> getMessages(final long first, final long last)
+ {
+ final List<QueueEntry> messages = new ArrayList<QueueEntry>((int)(last-first)+1);
+ _queue.visit(new QueueEntryVisitor()
+ {
+ private long position = 1;
+
+ public boolean visit(QueueEntry entry)
+ {
+ if(position >= first && position <= last)
+ {
+ messages.add(entry);
+ }
+ position++;
+ return position > last;
+ }
+ });
+ return messages;
+ }
+
+
+ private static class GetMessageVisitor implements QueueEntryVisitor
+ {
+
+ private final long _messageNumber;
+ private QueueEntry _entry;
+
+ public GetMessageVisitor(long messageId)
+ {
+ _messageNumber = messageId;
+ }
+
+ public boolean visit(QueueEntry entry)
+ {
+ if(entry.getMessage().getMessageNumber() == _messageNumber)
+ {
+ _entry = entry;
+ return true;
+ }
+ return false;
+ }
+
+ public QueueEntry getEntry()
+ {
+ return _entry;
+ }
+ }
+
+ @Override
+ public void notifyClients(NotificationCheck notification, Queue queue, String notificationMsg)
+ {
+ notificationMsg = notification.name() + " " + notificationMsg;
+
+ Notification note = new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this,
+ incrementAndGetSequenceNumber(), System.currentTimeMillis(), notificationMsg);
+
+ getBroadcaster().sendNotification(note);
+ }
+
+ /**
+ * returns Notifications sent by this MBean.
+ */
+ @Override
+ public MBeanNotificationInfo[] getNotificationInfo()
+ {
+ String[] notificationTypes = new String[] { MonitorNotification.THRESHOLD_VALUE_EXCEEDED };
+ String name = MonitorNotification.class.getName();
+ String description = "Either Message count or Queue depth or Message size has reached threshold high value";
+ MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description);
+
+ return new MBeanNotificationInfo[] { info1 };
+ }
+
+ @Override
+ public String getDescription()
+ {
+ return (String) _queue.getAttribute(Queue.DESCRIPTION);
+ }
+
+ @Override
+ public void setDescription(String description)
+ {
+ _queue.setAttribute(Queue.DESCRIPTION, getDescription(), description);
+ }
+
+ private Queue findQueueFromQueueName(VirtualHost virtualHost, String queueName) throws OperationsException
+ {
+ Queue queue = ConfiguredObjectFinder.findConfiguredObjectByName(virtualHost.getQueues(), queueName);
+ if (queue == null)
+ {
+ throw new OperationsException("No such queue \""+queueName+"\"");
+ }
+ else
+ {
+ return queue;
+ }
+ }
+
+ private Exchange findExchangeFromExchangeName(VirtualHost virtualHost, String exchangeName) throws OperationsException
+ {
+ Exchange exchange = ConfiguredObjectFinder.findConfiguredObjectByName(virtualHost.getExchanges(), exchangeName);
+ if (exchange == null)
+ {
+ throw new OperationsException("No such exchange \""+exchangeName+"\"");
+ }
+ else
+ {
+ return exchange;
+ }
+ }
+}
diff --git a/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java
new file mode 100644
index 0000000000..597b98ccaa
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.jmx.mbeans;
+
+import java.io.IOException;
+
+import javax.management.JMException;
+import javax.management.NotCompliantMBeanException;
+
+import org.apache.qpid.common.QpidProperties;
+import org.apache.qpid.management.common.mbeans.ServerInformation;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.Broker;
+
+@MBeanDescription("Server Information Interface")
+public class ServerInformationMBean extends AbstractStatisticsGatheringMBean<Broker> implements ServerInformation
+{
+ private String _buildVersion;
+ private String _productVersion;
+
+ public ServerInformationMBean(ManagedObjectRegistry registry, Broker broker)
+ throws NotCompliantMBeanException, JMException
+ {
+ super(ServerInformation.class, ServerInformation.TYPE, registry, broker);
+
+ _buildVersion = QpidProperties.getBuildVersion();
+ _productVersion = QpidProperties.getReleaseVersion();
+
+ register();
+ }
+
+ @Override
+ public String getObjectInstanceName()
+ {
+ return ServerInformation.TYPE;
+ }
+
+ @Override
+ public Integer getManagementApiMajorVersion() throws IOException
+ {
+ return QPID_JMX_API_MAJOR_VERSION;
+ }
+
+ @Override
+ public Integer getManagementApiMinorVersion() throws IOException
+ {
+ return QPID_JMX_API_MINOR_VERSION;
+ }
+
+ @Override
+ public String getBuildVersion() throws IOException
+ {
+ return _buildVersion;
+ }
+
+ @Override
+ public String getProductVersion() throws IOException
+ {
+ return _productVersion;
+ }
+
+ @Override
+ public boolean isStatisticsEnabled()
+ {
+ return false;
+ }
+
+ @Override
+ public ManagedObject getParentObject()
+ {
+ // does not have a parent
+ return null;
+ }
+}
diff --git a/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Shutdown.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java
index cef4a42b64..62733168ef 100644
--- a/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Shutdown.java
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java
@@ -17,8 +17,14 @@
* under the License.
*
*/
-package org.apache.qpid.shutdown;
+package org.apache.qpid.server.jmx.mbeans;
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.jmx.DefaultManagedObject;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+
+import javax.management.JMException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -27,11 +33,6 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
-import javax.management.NotCompliantMBeanException;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.server.management.DefaultManagedObject;
-
/**
* Implementation of the JMX broker shutdown plugin.
*/
@@ -46,9 +47,10 @@ public class Shutdown extends DefaultManagedObject implements ShutdownMBean
private final Runnable _shutdown = new SystemExiter();
- public Shutdown() throws NotCompliantMBeanException
+ public Shutdown(ManagedObjectRegistry registry) throws JMException
{
- super(ShutdownMBean.class, ShutdownMBean.TYPE);
+ super(ShutdownMBean.class, ShutdownMBean.TYPE, registry);
+ register();
}
/** @see ShutdownMBean#shutdown() */
@@ -108,6 +110,12 @@ public class Shutdown extends DefaultManagedObject implements ShutdownMBean
EXECUTOR.schedule(_shutdown, delay, TimeUnit.MILLISECONDS);
}
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return null;
+ }
+
/**
* Shutting down the system in another thread to avoid JMX exceptions being thrown.
*/
@@ -120,9 +128,8 @@ public class Shutdown extends DefaultManagedObject implements ShutdownMBean
}
/**
- * @see org.apache.qpid.server.management.ManagedObject#getObjectInstanceName()
+ * @see ManagedObject#getObjectInstanceName()
*/
- @Override
public String getObjectInstanceName()
{
return "Shutdown";
diff --git a/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/ShutdownMBean.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java
index 5c54fb3e21..ed69c351f7 100644
--- a/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/ShutdownMBean.java
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java
@@ -17,13 +17,13 @@
* under the License.
*
*/
-package org.apache.qpid.shutdown;
-
-import javax.management.MBeanOperationInfo;
+package org.apache.qpid.server.jmx.mbeans;
import org.apache.qpid.management.common.mbeans.annotations.MBeanOperation;
import org.apache.qpid.management.common.mbeans.annotations.MBeanOperationParameter;
+import javax.management.MBeanOperationInfo;
+
/**
* Shutdown plugin JMX MBean interface.
*
@@ -45,7 +45,7 @@ public interface ShutdownMBean
* @param delay the number of ms to wait
*/
@MBeanOperation(name="shutdown", description="Shutdown after the specified delay (ms)", impact = MBeanOperationInfo.ACTION)
- public void shutdown(@MBeanOperationParameter(name="when", description="delay (ms)")long delay);
+ public void shutdown(@MBeanOperationParameter(name = "when", description = "delay (ms)") long delay);
/**
* Broker will be shutdown at the specified date and time.
@@ -53,5 +53,6 @@ public interface ShutdownMBean
* @param when the date and time to shutdown
*/
@MBeanOperation(name="shutdownAt", description="Shutdown at the specified date and time (yyyy/MM/dd HH:mm:ss)", impact = MBeanOperationInfo.ACTION)
- public void shutdownAt(@MBeanOperationParameter(name="when", description="shutdown date/time (yyyy/MM/dd HH:mm:ss)")String when);
+ public void shutdownAt(@MBeanOperationParameter(name = "when",
+ description = "shutdown date/time (yyyy/MM/dd HH:mm:ss)") String when);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java
index 1314a5d6a6..c7aade34b4 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java
@@ -18,16 +18,16 @@
*
*
*/
-package org.apache.qpid.server.security.auth.management;
+package org.apache.qpid.server.jmx.mbeans;
import org.apache.log4j.Logger;
import org.apache.qpid.management.common.mbeans.UserManagement;
import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanOperation;
-import org.apache.qpid.server.management.AMQManagedObject;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+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.model.PasswordCredentialManagingAuthenticationProvider;
import javax.management.JMException;
import javax.management.openmbean.CompositeData;
@@ -40,17 +40,16 @@ import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import javax.security.auth.login.AccountNotFoundException;
+
import java.io.IOException;
-import java.security.Principal;
-import java.util.List;
+import java.util.Map;
-/** MBean class for AMQUserManagementMBean. It implements all the management features exposed for managing users. */
@MBeanDescription("User Management Interface")
-public class AMQUserManagementMBean extends AMQManagedObject implements UserManagement
+public class UserManagementMBean extends AMQManagedObject implements UserManagement
{
- private static final Logger _logger = Logger.getLogger(AMQUserManagementMBean.class);
+ private static final Logger _logger = Logger.getLogger(UserManagementMBean.class);
- private PrincipalDatabase _principalDatabase;
+ private PasswordCredentialManagingAuthenticationProvider _authProvider;
// Setup for the TabularType
private static final TabularType _userlistDataType; // Datatype for representing User Lists
@@ -79,45 +78,46 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
}
}
- public AMQUserManagementMBean() throws JMException
+ public UserManagementMBean(PasswordCredentialManagingAuthenticationProvider provider, ManagedObjectRegistry registry) throws JMException
{
- super(UserManagement.class, UserManagement.TYPE);
+ super(UserManagement.class, UserManagement.TYPE, registry);
+ register();
+ _authProvider = provider;
}
+ @Override
public String getObjectInstanceName()
{
return UserManagement.TYPE;
}
+ @Override
public boolean setPassword(String username, String password)
{
try
{
- //delegate password changes to the Principal Database
- return _principalDatabase.updatePassword(new UsernamePrincipal(username), password.toCharArray());
+ _authProvider.setPassword(username, password);
}
catch (AccountNotFoundException e)
{
- _logger.warn("Attempt to set password of non-existent user'" + username + "'");
+ _logger.warn("Attempt to set password of non-existent user '" + username + "'");
return false;
}
+ return true;
}
+ @Override
public boolean createUser(String username, String password)
{
- if (_principalDatabase.createPrincipal(new UsernamePrincipal(username), password.toCharArray()))
- {
- return true;
- }
-
- return false;
+ return _authProvider.createUser(username, password, null);
}
+ @Override
public boolean deleteUser(String username)
{
try
{
- _principalDatabase.deletePrincipal(new UsernamePrincipal(username));
+ _authProvider.deleteUser(username);
}
catch (AccountNotFoundException e)
{
@@ -128,37 +128,36 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
return true;
}
+ @Override
public boolean reloadData()
{
try
{
- _principalDatabase.reload();
+ _authProvider.reload();
+ return true;
}
catch (IOException e)
{
- _logger.warn("Reload failed due to:", e);
+ _logger.error("Unable to reload user data", e);
return false;
}
- // Reload successful
- return true;
}
-
- @MBeanOperation(name = "viewUsers", description = "All users that are currently available to the system.")
+ @Override
public TabularData viewUsers()
{
- List<Principal> users = _principalDatabase.getUsers();
+ Map<String, Map<String, String>> users = _authProvider.getUsers();
TabularDataSupport userList = new TabularDataSupport(_userlistDataType);
try
{
// Create the tabular list of message header contents
- for (Principal user : users)
+ for (String user : users.keySet())
{
// Create header attributes list
- // Read,Write,Admin items are depcreated and we return always false.
- Object[] itemData = {user.getName(), false, false, false};
+ // Read,Write,Admin items are deprecated and we return always false.
+ Object[] itemData = {user, false, false, false};
CompositeData messageData = new CompositeDataSupport(_userDataType, COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), itemData);
userList.put(messageData);
}
@@ -172,15 +171,9 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
return userList;
}
- /*** Broker Methods **/
-
- /**
- * setPrincipalDatabase
- *
- * @param database set The Database to use for user lookup
- */
- public void setPrincipalDatabase(PrincipalDatabase database)
+ @Override
+ public ManagedObject getParentObject()
{
- _principalDatabase = database;
+ return null;
}
}
diff --git a/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java
new file mode 100644
index 0000000000..85f53d9c0d
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java
@@ -0,0 +1,208 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.server.jmx.AMQManagedObject;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+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.Queue;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.virtualhost.ManagedVirtualHost;
+
+import javax.management.JMException;
+import javax.management.ObjectName;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtualHost, ConfigurationChangeListener
+{
+ private final VirtualHost _virtualHost;
+
+ private final Map<ConfiguredObject, AMQManagedObject> _children =
+ new HashMap<ConfiguredObject, AMQManagedObject>();
+ private VirtualHostManagerMBean _managerMBean;
+
+ public VirtualHostMBean(VirtualHost virtualHost, ManagedObjectRegistry registry) throws JMException
+ {
+ super(ManagedVirtualHost.class, ManagedVirtualHost.TYPE, registry);
+ _virtualHost = virtualHost;
+ virtualHost.addChangeListener(this);
+
+ initQueues();
+ initExchanges();
+ initConnections();
+
+ //This is the actual JMX bean for this 'VirtualHostMBean', leave it alone.
+ _managerMBean = new VirtualHostManagerMBean(this);
+ }
+
+ private void initQueues() throws JMException
+ {
+ synchronized (_children)
+ {
+ for(Queue queue : _virtualHost.getQueues())
+ {
+ if(!_children.containsKey(queue))
+ {
+ _children.put(queue, new QueueMBean(queue, this));
+ }
+ }
+ }
+ }
+
+ private void initExchanges() throws JMException
+ {
+ synchronized (_children)
+ {
+ for(Exchange exchange : _virtualHost.getExchanges())
+ {
+ if(!_children.containsKey(exchange))
+ {
+ _children.put(exchange, new ExchangeMBean(exchange, this));
+ }
+ }
+ }
+ }
+
+ private void initConnections() throws JMException
+ {
+ synchronized (_children)
+ {
+ for(Connection conn : _virtualHost.getConnections())
+ {
+ if(!_children.containsKey(conn))
+ {
+ _children.put(conn, new ConnectionMBean(conn, this));
+ }
+ }
+ }
+ }
+
+ public String getObjectInstanceName()
+ {
+ return ObjectName.quote(_virtualHost.getName());
+ }
+
+ public String getName()
+ {
+ return _virtualHost.getName();
+ }
+
+ public void stateChanged(ConfiguredObject object, State oldState, State newState)
+ {
+ // ignore
+ }
+
+ public void childAdded(ConfiguredObject object, ConfiguredObject child)
+ {
+ synchronized (_children)
+ {
+ try
+ {
+ if(child instanceof Queue)
+ {
+ QueueMBean queueMB = new QueueMBean((Queue)child, this);
+ _children.put(child, queueMB);
+
+ }
+ else if(child instanceof Exchange)
+ {
+ ExchangeMBean exchangeMBean = new ExchangeMBean((Exchange)child, this);
+ _children.put(child, exchangeMBean);
+
+ }
+ else if(child instanceof Connection)
+ {
+ ConnectionMBean connectionMBean = new ConnectionMBean((Connection)child, this);
+ _children.put(child, connectionMBean);
+
+ }
+ else
+ {
+ // TODO
+ }
+
+ }
+ catch(JMException e)
+ {
+ e.printStackTrace(); //TODO - report error on adding child MBean
+ }
+ }
+ }
+
+ public void childRemoved(ConfiguredObject object, ConfiguredObject child)
+ {
+ synchronized (_children)
+ {
+ AMQManagedObject mbean = _children.remove(child);
+ if(mbean != null)
+ {
+ try
+ {
+ mbean.unregister();
+ }
+ catch(JMException e)
+ {
+ e.printStackTrace(); //TODO - report error on removing child MBean
+ }
+ }
+ }
+ }
+
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return null;
+ }
+
+ protected VirtualHost getVirtualHost()
+ {
+ return _virtualHost;
+ }
+
+ public Collection<QueueMBean> getQueues()
+ {
+ Collection<AMQManagedObject> children;
+ synchronized (_children)
+ {
+ children = new ArrayList<AMQManagedObject>(_children.values());
+ }
+ Collection<QueueMBean> queues = new ArrayList<QueueMBean>();
+
+ for(AMQManagedObject child : children)
+ {
+ if(child instanceof QueueMBean)
+ {
+ queues.add((QueueMBean) child);
+ }
+ }
+
+ return queues;
+ }
+}
diff --git a/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java
new file mode 100644
index 0000000000..7ccb706c80
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java
@@ -0,0 +1,239 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.jmx.mbeans;
+
+import java.io.IOException;
+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 javax.management.JMException;
+import javax.management.MBeanException;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.management.common.mbeans.ManagedBroker;
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanOperationParameter;
+import org.apache.qpid.server.jmx.ManagedObject;
+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.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+
+@MBeanDescription("This MBean exposes the broker level management features")
+public class VirtualHostManagerMBean extends AbstractStatisticsGatheringMBean<VirtualHost> implements ManagedBroker
+{
+ private static final Logger LOGGER = Logger.getLogger(VirtualHostManagerMBean.class);
+
+ private static final boolean _moveNonExclusiveQueueOwnerToDescription = Boolean.parseBoolean(System.getProperty("qpid.move_non_exclusive_queue_owner_to_description", Boolean.TRUE.toString()));
+
+ private final VirtualHostMBean _virtualHostMBean;
+
+ @MBeanConstructor("Creates the Broker Manager MBean")
+ public VirtualHostManagerMBean(VirtualHostMBean virtualHostMBean) throws JMException
+ {
+ super(ManagedBroker.class, ManagedBroker.TYPE, virtualHostMBean.getRegistry(), virtualHostMBean.getVirtualHost());
+ _virtualHostMBean = virtualHostMBean;
+ register();
+ }
+
+
+ public String getObjectInstanceName()
+ {
+ return ObjectName.quote(_virtualHostMBean.getName());
+ }
+
+ @Override
+ public ManagedObject getParentObject()
+ {
+ return _virtualHostMBean;
+ }
+
+ public String[] getExchangeTypes() throws IOException
+ {
+ Collection<String> exchangeTypes = _virtualHostMBean.getVirtualHost().getExchangeTypes();
+ return exchangeTypes.toArray(new String[exchangeTypes.size()]);
+ }
+
+ public List<String> retrieveQueueAttributeNames() throws IOException
+ {
+ return ManagedQueue.QUEUE_ATTRIBUTES;
+ }
+
+ public List<List<Object>> retrieveQueueAttributeValues(
+ @MBeanOperationParameter(name = "attributes", description = "Attributes to retrieve") String[] attributes)
+ throws IOException
+ {
+ int attributesLength = attributes.length;
+
+ List<List<Object>> queueAttributesList = new ArrayList<List<Object>>();
+
+ for(QueueMBean queue : _virtualHostMBean.getQueues())
+ {
+
+ if(queue == null)
+ {
+ continue;
+ }
+
+ List<Object> attributeValues = new ArrayList<Object>(attributesLength);
+
+ for(int i=0; i < attributesLength; i++)
+ {
+ try
+ {
+ attributeValues.add(queue.getAttribute(attributes[i]));
+ }
+ catch (Exception e)
+ {
+ attributeValues.add("-");
+ }
+ }
+
+ queueAttributesList.add(attributeValues);
+ }
+
+ return queueAttributesList;
+
+ }
+
+ public void createNewExchange(String name, String type, boolean durable)
+ throws IOException, JMException, MBeanException
+ {
+ getConfiguredObject().createExchange(name, State.ACTIVE, durable,
+ LifetimePolicy.PERMANENT, 0l, type, Collections.EMPTY_MAP);
+
+ }
+
+ public void unregisterExchange(String exchangeName)
+ throws IOException, JMException, MBeanException
+ {
+ Exchange theExchange = null;
+ for(Exchange exchange : _virtualHostMBean.getVirtualHost().getExchanges())
+ {
+ if(exchange.getName().equals(exchangeName))
+ {
+ theExchange = exchange;
+ break;
+ }
+ }
+ if(theExchange != null)
+ {
+ try
+ {
+ theExchange.delete();
+ }
+ catch (IllegalStateException ex)
+ {
+ final JMException jme = new JMException(ex.toString());
+ throw new MBeanException(jme, "Error in unregistering exchange " + exchangeName);
+ }
+ }
+ }
+
+ public void createNewQueue(String queueName, String owner, boolean durable)
+ throws IOException, JMException, MBeanException
+ {
+ createNewQueue(queueName, owner, durable, Collections.EMPTY_MAP);
+ }
+
+ public void createNewQueue(String queueName, String owner, boolean durable, Map<String, Object> originalArguments)
+ throws IOException, JMException
+ {
+ final Map<String, Object> createArgs = processNewQueueArguments(queueName, owner, originalArguments);
+ getConfiguredObject().createQueue(queueName, State.ACTIVE, durable, false, LifetimePolicy.PERMANENT, 0l, createArgs);
+ }
+
+
+ /**
+ * Some users have been abusing the owner field to store a queue description. As the owner field
+ * only makes sense if exclusive=true, and it is currently impossible to create an exclusive queue via
+ * the JMX interface, if the user specifies a owner, then we assume that they actually mean to pass a description.
+ */
+ private Map<String, Object> processNewQueueArguments(String queueName,
+ String owner, Map<String, Object> arguments)
+ {
+ final Map<String, Object> argumentsCopy;
+ if (_moveNonExclusiveQueueOwnerToDescription && owner != null)
+ {
+ argumentsCopy = new HashMap<String, Object>(arguments == null ? new HashMap<String, Object>() : arguments);
+ if (!argumentsCopy.containsKey(AMQQueueFactory.X_QPID_DESCRIPTION))
+ {
+ LOGGER.warn("Non-exclusive owner " + owner + " for new queue " + queueName + " moved to " + AMQQueueFactory.X_QPID_DESCRIPTION);
+
+ argumentsCopy.put(AMQQueueFactory.X_QPID_DESCRIPTION, owner);
+ }
+ else
+ {
+ LOGGER.warn("Non-exclusive owner " + owner + " for new queue " + queueName + " ignored.");
+ }
+ }
+ else
+ {
+ argumentsCopy = arguments;
+ }
+ return argumentsCopy;
+ }
+
+ public void deleteQueue(
+ @MBeanOperationParameter(name = ManagedQueue.TYPE, description = "Queue Name") String queueName)
+ throws IOException, JMException, MBeanException
+ {
+ Queue theQueue = null;
+ for(Queue queue : _virtualHostMBean.getVirtualHost().getQueues())
+ {
+ if(queue.getName().equals(queueName))
+ {
+ theQueue = queue;
+ break;
+ }
+ }
+ if(theQueue != null)
+ {
+ theQueue.delete();
+ }
+ }
+
+
+ @Override
+ public ObjectName getObjectName() throws MalformedObjectNameException
+ {
+ return getObjectNameForSingleInstanceMBean();
+ }
+
+
+ public synchronized boolean isStatisticsEnabled()
+ {
+ updateStats();
+ return false; //TODO - implement isStatisticsEnabled
+ }
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.java
index e77350c3e4..a2631bab7f 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java
+++ b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.java
@@ -18,29 +18,18 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
-
-import org.apache.log4j.Logger;
+package org.apache.qpid.server.jmx;
import javax.management.JMException;
-/**
- * This managed object registry does not actually register MBeans. This can be used in tests when management is
- * not required or when management has been disabled.
- *
- */
public class NoopManagedObjectRegistry implements ManagedObjectRegistry
{
- private static final Logger _log = Logger.getLogger(NoopManagedObjectRegistry.class);
-
public NoopManagedObjectRegistry()
{
- _log.info("Management is disabled");
}
public void start()
{
- //no-op
}
public void registerObject(ManagedObject managedObject) throws JMException
@@ -53,6 +42,5 @@ public class NoopManagedObjectRegistry implements ManagedObjectRegistry
public void close()
{
-
}
}
diff --git a/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java
new file mode 100644
index 0000000000..f294c85c99
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java
@@ -0,0 +1,235 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.Date;
+
+import javax.management.JMException;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.qpid.management.common.mbeans.ManagedConnection;
+import org.apache.qpid.server.jmx.ManagedObject;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Session;
+import org.apache.qpid.server.model.Statistics;
+
+public class ConnectionMBeanTest extends TestCase
+{
+ private ConnectionMBean _connectionMBean;
+ private Connection _mockConnection;
+ private VirtualHostMBean _mockVirtualHostMBean;
+ private ManagedObjectRegistry _mockManagedObjectRegistry;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _mockConnection = mock(Connection.class);
+ _mockVirtualHostMBean = mock(VirtualHostMBean.class);
+
+ _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class);
+ when(_mockVirtualHostMBean.getRegistry()).thenReturn(_mockManagedObjectRegistry);
+
+ _connectionMBean = new ConnectionMBean(_mockConnection, _mockVirtualHostMBean);
+ }
+
+ public void testMBeanRegistersItself() throws Exception
+ {
+ ConnectionMBean connectionMBean = new ConnectionMBean(_mockConnection, _mockVirtualHostMBean);
+ verify(_mockManagedObjectRegistry).registerObject(connectionMBean);
+ }
+
+ public void testCloseConnection() throws Exception
+ {
+ _connectionMBean.closeConnection();
+ verify(_mockConnection).delete();
+ }
+
+ public void testCommitTransactions()
+ {
+ try
+ {
+ _connectionMBean.commitTransactions(0);
+ fail("Exception not thrown");
+ }
+ catch(JMException e)
+ {
+ assertTrue("Cause should be an UnsupportedOperationException", e.getCause() instanceof UnsupportedOperationException);
+ }
+ }
+
+ public void testRollbackTransactions()
+ {
+ try
+ {
+ _connectionMBean.rollbackTransactions(0);
+ fail("Exception not thrown");
+ }
+ catch(JMException e)
+ {
+ assertTrue("Cause should be an UnsupportedOperationException", e.getCause() instanceof UnsupportedOperationException);
+ }
+ }
+
+ public void testChannelsWithSingleTransactionalSession() throws Exception
+ {
+ int channelId = 10;
+ int unacknowledgedMessages = 2;
+ long localTransactionBegins = 1;
+ boolean transactional = true;
+ boolean blocked = false;
+
+ Session mockSession = createMockedSession(channelId, unacknowledgedMessages, localTransactionBegins, blocked);
+
+ when(_mockConnection.getSessions()).thenReturn(Collections.singletonList(mockSession));
+
+ TabularData table = _connectionMBean.channels();
+ assertEquals("Unexpected number of rows in table", 1, table.size());
+
+ final CompositeData row = table.get(new Integer[] {channelId} );
+ assertChannelRow(row, channelId, unacknowledgedMessages, transactional, blocked);
+ }
+
+ public void testChannelsWithSingleNonTransactionalSession() throws Exception
+ {
+ int channelId = 10;
+ int unacknowledgedMessages = 2;
+ long localTransactionBegins = 0;
+ boolean transactional = false;
+ boolean blocked = false;
+
+ Session mockSession = createMockedSession(channelId, unacknowledgedMessages, localTransactionBegins, blocked);
+
+ when(_mockConnection.getSessions()).thenReturn(Collections.singletonList(mockSession));
+
+ TabularData table = _connectionMBean.channels();
+ assertEquals("Unexpected number of rows in table", 1, table.size());
+
+ final CompositeData row = table.get(new Integer[] {channelId} );
+ assertChannelRow(row, channelId, unacknowledgedMessages, transactional, blocked);
+ }
+
+ public void testChannelsWithSessionBlocked() throws Exception
+ {
+ int channelId = 10;
+ int unacknowledgedMessages = 2;
+ long localTransactionBegins = 0;
+ boolean transactional = false;
+ boolean blocked = true;
+
+ Session mockSession = createMockedSession(channelId, unacknowledgedMessages, localTransactionBegins, blocked);
+
+ when(_mockConnection.getSessions()).thenReturn(Collections.singletonList(mockSession));
+
+ TabularData table = _connectionMBean.channels();
+ assertEquals("Unexpected number of rows in table", 1, table.size());
+
+ final CompositeData row = table.get(new Integer[] {channelId} );
+ assertChannelRow(row, channelId, unacknowledgedMessages, transactional, blocked);
+ }
+
+ public void testParentObjectIsVirtualHost()
+ {
+ ManagedObject parent = _connectionMBean.getParentObject();
+ assertEquals(_mockVirtualHostMBean, parent);
+ }
+
+ public void testGetObjectInstanceName()
+ {
+ String remoteAddress = "testRemoteAddress";
+ String quotedRemoteAddress = "\"testRemoteAddress\"";
+ when(_mockConnection.getAttribute(Connection.REMOTE_ADDRESS)).thenReturn(remoteAddress);
+ String objectInstanceName = _connectionMBean.getObjectInstanceName();
+ assertEquals(quotedRemoteAddress, objectInstanceName);
+ }
+
+ public void testGetAuthorizedId() throws Exception
+ {
+ assertAttribute("authorizedId", "testAuthorizedId", Connection.PRINCIPAL);
+ }
+
+ public void testGetVersion() throws Exception
+ {
+ assertAttribute("version", "testVersion", Connection.CLIENT_VERSION);
+ }
+
+ public void testGetRemoteAddress() throws Exception
+ {
+ assertAttribute("remoteAddress", "testRemoteAddress", Connection.REMOTE_ADDRESS);
+ }
+
+ public void testGetLastIoTime()
+ {
+ Statistics mockStatistics = mock(Statistics.class);
+ when(_mockConnection.getStatistics()).thenReturn(mockStatistics);
+ when(mockStatistics.getStatistic(Connection.LAST_IO_TIME)).thenReturn(1L);
+
+ Object actualValue = _connectionMBean.getLastIoTime();
+ assertEquals("Unexpected lastIoTime", new Date(1L), actualValue);
+ }
+
+ public void testGetMaximumNumberOfChannels() throws Exception
+ {
+ assertAttribute("maximumNumberOfChannels", 10l, Connection.SESSION_COUNT_LIMIT);
+ }
+
+ public void testIsStatisticsEnabledAlwaysTrue() throws Exception
+ {
+ assertTrue(_connectionMBean.isStatisticsEnabled());
+ }
+
+ private void assertAttribute(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception
+ {
+ when(_mockConnection.getAttribute(underlyingAttributeName)).thenReturn(expectedValue);
+
+ Object actualValue = PropertyUtils.getSimpleProperty(_connectionMBean, jmxAttributeName);
+ assertEquals("Unexpected " + jmxAttributeName, expectedValue, actualValue);
+ }
+
+ private void assertChannelRow(final CompositeData row, int channelId, int unacknowledgedMessages, boolean isTransactional, boolean flowBlocked)
+ {
+ assertNotNull("No row for channel id " + channelId, row);
+ assertEquals("Unexpected channel id", channelId, row.get(ManagedConnection.CHAN_ID));
+ 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 Session createMockedSession(int channelId, int unacknowledgedMessages, long localTransactionBegins, boolean blocked)
+ {
+ Session mockSession = mock(Session.class);
+ Statistics mockSessionStatistics = mock(Statistics.class);
+ when(mockSessionStatistics.getStatistic(Session.LOCAL_TRANSACTION_BEGINS)).thenReturn(localTransactionBegins);
+ when(mockSessionStatistics.getStatistic(Session.UNACKNOWLEDGED_MESSAGES)).thenReturn(unacknowledgedMessages);
+
+ when(mockSession.getStatistics()).thenReturn(mockSessionStatistics);
+ when(mockSession.getAttribute(Session.CHANNEL_ID)).thenReturn(channelId);
+ when(mockSession.getAttribute(Session.PRODUCER_FLOW_BLOCKED)).thenReturn(blocked);
+ return mockSession;
+ }
+}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/management/LoggingManagementMBeanTest.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java
index f9ad81ae74..64b942c9a9 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/management/LoggingManagementMBeanTest.java
+++ b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java
@@ -14,15 +14,18 @@
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
- * under the License.
+ * under the License.
+ *
*
- *
*/
-package org.apache.qpid.server.logging.management;
+package org.apache.qpid.server.jmx.mbeans;
+
+import static org.mockito.Mockito.*;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_LEVEL;
@@ -41,6 +44,7 @@ import java.util.Map;
public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
{
+
private static final String TEST_LOGGER = "LoggingManagementMBeanTestLogger";
private static final String TEST_LOGGER_CHILD1 = "LoggingManagementMBeanTestLogger.child1";
private static final String TEST_LOGGER_CHILD2 = "LoggingManagementMBeanTestLogger.child2";
@@ -53,13 +57,15 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
private File _testConfigFile;
+ private ManagedObjectRegistry _registry = mock(ManagedObjectRegistry.class);
+
@Override
public void setUp() throws Exception
{
super.setUp();
_testConfigFile = createTempTestLog4JConfig();
}
-
+
@Override
public void tearDown() throws Exception
{
@@ -68,9 +74,9 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
{
oldTestConfigFile.delete();
}
-
+
_testConfigFile.delete();
-
+
super.tearDown();
}
@@ -89,7 +95,7 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
writer.write("<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">"+NEWLINE);
writer.write("<log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\" debug=\"null\" " +
- "threshold=\"null\">"+NEWLINE);
+ "threshold=\"null\">"+NEWLINE);
writer.write(" <appender class=\"org.apache.log4j.ConsoleAppender\" name=\"STDOUT\">"+NEWLINE);
writer.write(" <layout class=\"org.apache.log4j.PatternLayout\">"+NEWLINE);
@@ -137,13 +143,13 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
//******* Test Methods ******* //
-
+
public void testSetRuntimeLoggerLevel()
{
LoggingManagementMBean lm = null;
try
{
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0);
+ lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0, _registry);
}
catch (JMException e)
{
@@ -156,26 +162,26 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
//create child1 test logger, check its *effective* level is the same as the parent, "info"
Logger log1 = Logger.getLogger(TEST_LOGGER_CHILD1);
- assertTrue("Test logger's level was not the expected value",
+ assertTrue("Test logger's level was not the expected value",
log1.getEffectiveLevel().toString().equalsIgnoreCase("info"));
//now change its level to "warn"
assertTrue("Failed to set logger level", lm.setRuntimeLoggerLevel(TEST_LOGGER_CHILD1, "warn"));
//check the change, see its actual level is "warn
- assertTrue("Test logger's level was not the expected value",
+ assertTrue("Test logger's level was not the expected value",
log1.getLevel().toString().equalsIgnoreCase("warn"));
//try an invalid level
assertFalse("Trying to set an invalid level succeded", lm.setRuntimeLoggerLevel(TEST_LOGGER_CHILD1, "made.up.level"));
}
-
+
public void testSetRuntimeRootLoggerLevel()
{
LoggingManagementMBean lm = null;
try
{
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0);
+ lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0, _registry);
}
catch (JMException e)
{
@@ -183,27 +189,27 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
}
Logger log = Logger.getRootLogger();
-
+
//get current root logger level
Level origLevel = log.getLevel();
-
+
//change level twice to ensure a new level is actually selected
-
+
//set root loggers level to info
assertTrue("Failed to set root logger level", lm.setRuntimeRootLoggerLevel("debug"));
//check it is now actually info
Level currentLevel = log.getLevel();
assertTrue("Logger level was not expected value", currentLevel.equals(Level.toLevel("debug")));
-
+
//try an invalid level
assertFalse("Trying to set an invalid level succeded", lm.setRuntimeRootLoggerLevel("made.up.level"));
-
+
//set root loggers level to warn
assertTrue("Failed to set logger level", lm.setRuntimeRootLoggerLevel("info"));
//check it is now actually warn
currentLevel = log.getLevel();
assertTrue("Logger level was not expected value", currentLevel.equals(Level.toLevel("info")));
-
+
//restore original level
log.setLevel(origLevel);
}
@@ -213,7 +219,7 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
LoggingManagementMBean lm = null;
try
{
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0);
+ lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0, _registry);
}
catch (JMException e)
{
@@ -221,18 +227,18 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
}
Logger log = Logger.getRootLogger();
-
+
//get current root logger level
Level origLevel = log.getLevel();
-
+
//change level twice to ensure a new level is actually selected
-
+
//set root loggers level to debug
log.setLevel(Level.toLevel("debug"));
//check it is now actually debug
assertTrue("Logger level was not expected value", lm.getRuntimeRootLoggerLevel().equalsIgnoreCase("debug"));
-
-
+
+
//set root loggers level to warn
log.setLevel(Level.toLevel("info"));
//check it is now actually warn
@@ -241,13 +247,13 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
//restore original level
log.setLevel(origLevel);
}
-
+
public void testViewEffectiveRuntimeLoggerLevels()
{
LoggingManagementMBean lm = null;
try
{
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0);
+ lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0, _registry);
}
catch (JMException e)
{
@@ -257,7 +263,7 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
//(re)create a parent test logger, set its level explicitly
Logger log = Logger.getLogger(TEST_LOGGER);
log.setLevel(Level.toLevel("info"));
-
+
//retrieve the current effective runtime logger level values
TabularDataSupport levels = (TabularDataSupport) lm.viewEffectiveRuntimeLoggerLevels();
Collection<Object> records = levels.values();
@@ -267,13 +273,13 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
CompositeData data = (CompositeData) o;
list.put(data.get(LOGGER_NAME).toString(), data.get(LOGGER_LEVEL).toString());
}
-
+
//check child2 does not exist already
assertFalse("Did not expect this logger to exist already", list.containsKey(TEST_LOGGER_CHILD2));
//create child2 test logger
Logger log2 = Logger.getLogger(TEST_LOGGER_CHILD2);
-
+
//retrieve the current effective runtime logger level values
levels = (TabularDataSupport) lm.viewEffectiveRuntimeLoggerLevels();
records = levels.values();
@@ -287,14 +293,14 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
//verify the parent and child2 loggers are present in returned values
assertTrue(TEST_LOGGER + " logger was not in the returned list", list.containsKey(TEST_LOGGER));
assertTrue(TEST_LOGGER_CHILD2 + " logger was not in the returned list", list.containsKey(TEST_LOGGER_CHILD2));
-
+
//check child2's effective level is the same as the parent, "info"
- assertTrue("Test logger's level was not the expected value",
+ assertTrue("Test logger's level was not the expected value",
list.get(TEST_LOGGER_CHILD2).equalsIgnoreCase("info"));
//now change its level explicitly to "warn"
log2.setLevel(Level.toLevel("warn"));
-
+
//retrieve the current effective runtime logger level values
levels = (TabularDataSupport) lm.viewEffectiveRuntimeLoggerLevels();
records = levels.values();
@@ -306,7 +312,7 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
}
//check child2's effective level is now "warn"
- assertTrue("Test logger's level was not the expected value",
+ assertTrue("Test logger's level was not the expected value",
list.get(TEST_LOGGER_CHILD2).equalsIgnoreCase("warn"));
}
@@ -315,7 +321,7 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
LoggingManagementMBean lm =null;
try
{
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0);
+ lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0, _registry);
}
catch (JMException e)
{
@@ -378,13 +384,13 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
assertTrue(TEST_CATEGORY_LEVEL + " logger's level was incorrect", list.get(TEST_CATEGORY_LEVEL).equalsIgnoreCase("error"));
assertTrue(TEST_LOGGER_LEVEL + " logger's level was incorrect", list.get(TEST_LOGGER_LEVEL).equalsIgnoreCase("trace"));
}
-
+
public void testGetAndSetConfigFileRootLoggerLevel() throws Exception
{
LoggingManagementMBean lm =null;
try
{
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0);
+ lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0, _registry);
}
catch (JMException e)
{
@@ -399,7 +405,7 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
//try an invalid level
assertFalse("Use of an invalid RootLogger level was successfull", lm.setConfigFileRootLoggerLevel("made.up.level"));
-
+
//change the level to warn
assertTrue("Failed to set new RootLogger level", lm.setConfigFileRootLoggerLevel("warn"));
@@ -415,7 +421,7 @@ public class LoggingManagementMBeanTest extends InternalBrokerBaseCase
LoggingManagementMBean lm =null;
try
{
- lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 5000);
+ lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 5000, _registry);
}
catch (JMException e)
{
diff --git a/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java
new file mode 100644
index 0000000000..ceaad0d29b
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.jmx.mbeans;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Matchers.argThat;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import javax.management.ListenerNotFoundException;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.OperationsException;
+
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+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.NotificationCheck;
+import org.mockito.ArgumentMatcher;
+
+import junit.framework.TestCase;
+
+public class QueueMBeanTest extends TestCase
+{
+ private static final String QUEUE_NAME = "QUEUE_NAME";
+ private static final String QUEUE_DESCRIPTION = "QUEUE_DESCRIPTION";
+ private static final String QUEUE_TYPE = "QUEUE_TYPE";
+ private static final String QUEUE_ALTERNATE_EXCHANGE = "QUEUE_ALTERNATE_EXCHANGE";
+
+ private Queue _mockQueue;
+ private VirtualHostMBean _mockVirtualHostMBean;
+ private ManagedObjectRegistry _mockManagedObjectRegistry;
+ private QueueMBean _queueMBean;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _mockQueue = mock(Queue.class);
+ when(_mockQueue.getName()).thenReturn(QUEUE_NAME);
+ _mockVirtualHostMBean = mock(VirtualHostMBean.class);
+
+ _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class);
+ when(_mockVirtualHostMBean.getRegistry()).thenReturn(_mockManagedObjectRegistry);
+
+ _queueMBean = new QueueMBean(_mockQueue, _mockVirtualHostMBean);
+ }
+
+ public void testQueueName()
+ {
+ assertEquals(QUEUE_NAME, _queueMBean.getName());
+ }
+
+ public void testGetQueueDescription()
+ {
+ when(_mockQueue.getAttribute(Queue.DESCRIPTION)).thenReturn(QUEUE_DESCRIPTION);
+
+ assertEquals(QUEUE_DESCRIPTION, _queueMBean.getDescription());
+ }
+
+ public void testSetQueueDescription()
+ {
+ _queueMBean.setDescription(QUEUE_DESCRIPTION);
+ verify(_mockQueue).setAttribute(Queue.DESCRIPTION, null, QUEUE_DESCRIPTION);
+ }
+
+ public void testQueueType()
+ {
+ when(_mockQueue.getAttribute(Queue.TYPE)).thenReturn(QUEUE_TYPE);
+
+ assertEquals(QUEUE_TYPE, _queueMBean.getQueueType());
+ }
+
+ public void testGetAlternateExchange()
+ {
+ Exchange mockAlternateExchange = mock(Exchange.class);
+ when(mockAlternateExchange.getName()).thenReturn(QUEUE_ALTERNATE_EXCHANGE);
+
+ when(_mockQueue.getAttribute(Queue.ALTERNATE_EXCHANGE)).thenReturn(mockAlternateExchange);
+
+ assertEquals(QUEUE_ALTERNATE_EXCHANGE, _queueMBean.getAlternateExchange());
+ }
+
+ public void testGetAlternateExchangeWhenQueueHasNone()
+ {
+ when(_mockQueue.getAttribute(Queue.ALTERNATE_EXCHANGE)).thenReturn(null);
+
+ assertNull(_queueMBean.getAlternateExchange());
+ }
+
+ public void testSetAlternateExchange() throws Exception
+ {
+ Exchange mockExchange1 = mock(Exchange.class);
+ when(mockExchange1.getName()).thenReturn("exchange1");
+
+ Exchange mockExchange2 = mock(Exchange.class);
+ when(mockExchange2.getName()).thenReturn("exchange2");
+
+ Exchange mockExchange3 = mock(Exchange.class);
+ when(mockExchange3.getName()).thenReturn("exchange3");
+
+ VirtualHost mockVirtualHost = mock(VirtualHost.class);
+ when(mockVirtualHost.getExchanges()).thenReturn(Arrays.asList(new Exchange[] {mockExchange1, mockExchange2, mockExchange3}));
+ when(_mockQueue.getParent(VirtualHost.class)).thenReturn(mockVirtualHost);
+
+ _queueMBean.setAlternateExchange("exchange2");
+ verify(_mockQueue).setAttribute(Queue.ALTERNATE_EXCHANGE, null, mockExchange2);
+ }
+
+ public void testSetAlternateExchangeWithUnknownExchangeName() throws Exception
+ {
+ Exchange mockExchange = mock(Exchange.class);
+ when(mockExchange.getName()).thenReturn("exchange1");
+
+ VirtualHost mockVirtualHost = mock(VirtualHost.class);
+ when(mockVirtualHost.getExchanges()).thenReturn(Collections.singletonList(mockExchange));
+ when(_mockQueue.getParent(VirtualHost.class)).thenReturn(mockVirtualHost);
+
+ try
+ {
+ _queueMBean.setAlternateExchange("notknown");
+ fail("Exception not thrown");
+ }
+ catch(OperationsException oe)
+ {
+ // PASS
+ }
+ }
+
+ public void testRemoveAlternateExchange() throws Exception
+ {
+ _queueMBean.setAlternateExchange("");
+ verify(_mockQueue).setAttribute(Queue.ALTERNATE_EXCHANGE, null, null);
+ }
+
+ public void testNotificationListenerCalled() throws Exception
+ {
+ NotificationListener listener = mock(NotificationListener.class);
+ _queueMBean.addNotificationListener(listener, null, null);
+
+ NotificationCheck notification = mock(NotificationCheck.class);
+ String notificationMsg = "Test notification message";
+
+ _queueMBean.notifyClients(notification, _mockQueue, notificationMsg);
+ verify(listener).handleNotification(isNotificationWithMessage(notificationMsg),
+ isNull());
+ }
+
+ public void testAddRemoveNotificationListener() throws Exception
+ {
+ NotificationListener listener1 = mock(NotificationListener.class);
+ _queueMBean.addNotificationListener(listener1, null, null);
+ _queueMBean.removeNotificationListener(listener1);
+ }
+
+ public void testRemoveUnknownNotificationListener() throws Exception
+ {
+ NotificationListener listener1 = mock(NotificationListener.class);
+ try
+ {
+ _queueMBean.removeNotificationListener(listener1);
+ fail("Exception not thrown");
+ }
+ catch (ListenerNotFoundException e)
+ {
+ // PASS
+ }
+ }
+
+ private Notification isNotificationWithMessage(final String expectedMessage)
+ {
+ return argThat( new ArgumentMatcher<Notification>()
+ {
+ @Override
+ public boolean matches(Object argument)
+ {
+ Notification actual = (Notification) argument;
+ return actual.getMessage().endsWith(expectedMessage);
+ }
+ });
+ }
+}
diff --git a/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.java
new file mode 100644
index 0000000000..8ca6c521eb
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.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.server.jmx.mbeans;
+
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+import javax.security.auth.login.AccountNotFoundException;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.common.mbeans.UserManagement;
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+
+public class UserManagementMBeanTest extends TestCase
+{
+ private UserManagementMBean _userManagement;
+ private ManagedObjectRegistry _mockRegistry;
+ private PasswordCredentialManagingAuthenticationProvider _mockProvider;
+
+ private static final String TEST_USERNAME = "testuser";
+ private static final String TEST_PASSWORD = "password";
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+
+ _mockProvider = mock(PasswordCredentialManagingAuthenticationProvider.class);
+ _mockRegistry = mock(ManagedObjectRegistry.class);
+ _userManagement = new UserManagementMBean(_mockProvider, _mockRegistry);
+ }
+
+ public void testMBeanRegistersItself() throws Exception
+ {
+ UserManagementMBean userManagementMBean = new UserManagementMBean(_mockProvider, _mockRegistry);
+ verify(_mockRegistry).registerObject(userManagementMBean);
+ }
+
+ public void testDeleteUser() throws Exception
+ {
+ boolean deleteSuccess = _userManagement.deleteUser(TEST_USERNAME);
+ assertTrue("Expected successful delete", deleteSuccess);
+
+ verify(_mockProvider).deleteUser(TEST_USERNAME);
+ }
+
+ public void testDeleteUserWhereUserDoesNotExist() throws Exception
+ {
+ doThrow(AccountNotFoundException.class).when(_mockProvider).deleteUser(TEST_USERNAME);
+
+ boolean deleteSuccess = _userManagement.deleteUser(TEST_USERNAME);
+ assertFalse("Expected unsuccessful delete", deleteSuccess);
+ }
+
+ public void testCreateUser() throws Exception
+ {
+ when(_mockProvider.createUser(TEST_USERNAME, TEST_PASSWORD, null)).thenReturn(true);
+
+ boolean createSuccess = _userManagement.createUser(TEST_USERNAME, TEST_PASSWORD);
+ assertTrue(createSuccess);
+ }
+
+ public void testCreateUserWhereUserAlreadyExists()
+ {
+ when(_mockProvider.createUser(TEST_USERNAME, TEST_PASSWORD, null)).thenReturn(false);
+
+ boolean createSuccess = _userManagement.createUser(TEST_USERNAME, TEST_PASSWORD);
+ assertFalse(createSuccess);
+ }
+
+ public void testSetPassword() throws Exception
+ {
+ boolean setPasswordSuccess = _userManagement.setPassword(TEST_USERNAME, TEST_PASSWORD);
+ assertTrue(setPasswordSuccess);
+
+ assertTrue("Set password should return true to flag successful change", setPasswordSuccess);
+
+ verify(_mockProvider).setPassword(TEST_USERNAME, TEST_PASSWORD);
+ }
+
+ public void testSetPasswordWhereUserDoesNotExist() throws Exception
+ {
+ doThrow(AccountNotFoundException.class).when(_mockProvider).setPassword(TEST_USERNAME, TEST_PASSWORD);
+
+ boolean setPasswordSuccess = _userManagement.setPassword(TEST_USERNAME, TEST_PASSWORD);
+
+ assertFalse("Set password should return false to flag unsuccessful change", setPasswordSuccess);
+ }
+
+ public void testReload() throws Exception
+ {
+ boolean reloadSuccess = _userManagement.reloadData();
+
+ assertTrue("Reload should return true to flag succesful update", reloadSuccess);
+
+ verify(_mockProvider).reload();
+ }
+
+ public void testReloadFails() throws Exception
+ {
+ doThrow(IOException.class).when(_mockProvider).reload();
+
+ boolean reloadSuccess = _userManagement.reloadData();
+
+ assertFalse("Expected reload to fail", reloadSuccess);
+ }
+
+ public void testViewUsers() throws Exception
+ {
+ Map<String,String> args = Collections.emptyMap();
+ when(_mockProvider.getUsers()).thenReturn(Collections.singletonMap(TEST_USERNAME, args));
+
+ TabularData userList = _userManagement.viewUsers();
+
+ assertNotNull(userList);
+ assertEquals("Unexpected number of users in user list", 1, userList.size());
+ assertTrue(userList.containsKey(new Object[]{TEST_USERNAME}));
+
+ // Check the deprecated read, write and admin items continue to exist but return false.
+ CompositeData userRec = userList.get(new Object[]{TEST_USERNAME});
+ assertTrue(userRec.containsKey(UserManagement.RIGHTS_READ_ONLY));
+ assertEquals(false, userRec.get(UserManagement.RIGHTS_READ_ONLY));
+ assertEquals(false, userRec.get(UserManagement.RIGHTS_READ_WRITE));
+ assertTrue(userRec.containsKey(UserManagement.RIGHTS_READ_WRITE));
+ assertTrue(userRec.containsKey(UserManagement.RIGHTS_ADMIN));
+ assertEquals(false, userRec.get(UserManagement.RIGHTS_ADMIN));
+ }
+}
diff --git a/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java
new file mode 100644
index 0000000000..7f021bdb32
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.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.jmx.mbeans;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import java.util.Collections;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.server.jmx.ManagedObjectRegistry;
+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.queue.AMQQueueFactory;
+
+public class VirtualHostManagerMBeanTest extends TestCase
+{
+ private static final String TEST_QUEUE_NAME = "QUEUE_NAME";
+ private static final String TEST_OWNER = "OWNER";
+ private static final String TEST_DESCRIPTION = "DESCRIPTION";
+
+ private static final Map<String, Object> EMPTY_ARGUMENT_MAP = Collections.emptyMap();
+
+ private VirtualHost _mockVirtualHost;
+ private ManagedObjectRegistry _mockManagedObjectRegistry;
+ private VirtualHostManagerMBean _virtualHostManagerMBean;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _mockVirtualHost = mock(VirtualHost.class);
+ _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class);
+
+ _virtualHostManagerMBean = new VirtualHostManagerMBean(new VirtualHostMBean(_mockVirtualHost, _mockManagedObjectRegistry));
+ }
+
+ public void testCreateQueueWithNoOwner() throws Exception
+ {
+ _virtualHostManagerMBean.createNewQueue(TEST_QUEUE_NAME, null, true);
+
+ verify(_mockVirtualHost).createQueue(TEST_QUEUE_NAME, State.ACTIVE, true, false, LifetimePolicy.PERMANENT, 0, EMPTY_ARGUMENT_MAP);
+ }
+
+ /**
+ * Some users have been abusing the owner parameter as a description. Decision has been taken to map this parameter
+ * through to the description field (if the description field is passed, the owner is discarded).
+ */
+ public void testCreateQueueWithOwnerMappedThroughToDescription() throws Exception
+ {
+ _virtualHostManagerMBean.createNewQueue(TEST_QUEUE_NAME, TEST_OWNER, true);
+
+ Map<String, Object> expectedArguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_OWNER);
+ verify(_mockVirtualHost).createQueue(TEST_QUEUE_NAME, State.ACTIVE, true, false, LifetimePolicy.PERMANENT, 0, expectedArguments);
+ }
+
+ public void testCreateQueueWithOwnerAndDescriptionDiscardsOwner() throws Exception
+ {
+ Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_DESCRIPTION);
+ _virtualHostManagerMBean.createNewQueue(TEST_QUEUE_NAME, TEST_OWNER, true, arguments);
+
+ Map<String, Object> expectedArguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_DESCRIPTION);
+ verify(_mockVirtualHost).createQueue(TEST_QUEUE_NAME, State.ACTIVE, true, false, LifetimePolicy.PERMANENT, 0, expectedArguments);
+ }
+
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedBrokerMBeanTest.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java
index ba0f955d76..5e6c570e8c 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedBrokerMBeanTest.java
+++ b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java
@@ -16,26 +16,22 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpid.management.jmx;
+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.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.test.utils.JMXTestUtils;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import javax.management.MBeanException;
import javax.management.ObjectName;
-import java.util.Collections;
-import java.util.Map;
/**
* Tests the JMX API for the Managed Broker.
*
*/
-public class ManagedBrokerMBeanTest extends QpidBrokerTestCase
+public class BrokerManagementTest extends QpidBrokerTestCase
{
/**
* Test virtual host
@@ -140,25 +136,4 @@ public class ManagedBrokerMBeanTest extends QpidBrokerTestCase
assertNotNull("Exchange should exist", defaultExchange);
}
- /**
- * 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<String, Object> args = Collections.singletonMap(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, (Object)deliveryCount);
- managedBroker.createNewQueue(queueName, "testowner", true, args);
-
- // 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());
- }
-
}
diff --git a/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java
new file mode 100644
index 0000000000..28d7bf4aed
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/test/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<ManagedConnection> 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<ManagedConnection> 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<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) 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/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java
index 0e2875235f..47b38381c5 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java
+++ b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpid.management.jmx;
+package org.apache.qpid.systest.management.jmx;
import org.apache.qpid.management.common.mbeans.ManagedBroker;
import org.apache.qpid.management.common.mbeans.ManagedConnection;
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
index c8a6d02761..6100d5a23e 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java
+++ b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
@@ -18,10 +18,11 @@
* under the License.
*
*/
-package org.apache.qpid.server.logging;
+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;
@@ -177,7 +178,7 @@ public class ManagementLoggingTest extends AbstractTestLogging
if (isJavaBroker())
{
startBrokerAndCreateMonitor(true, false);
-
+
List<String> results = waitAndFindMatches("MNG-1002");
// Validation
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
index 244e547e02..ad6777d0ea 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedQueueMBeanTest.java
+++ b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
@@ -16,15 +16,20 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpid.management.jmx;
+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.AMQQueueMBean;
+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;
@@ -34,12 +39,16 @@ 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.management.Notification;
+import javax.management.NotificationListener;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -49,14 +58,19 @@ 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 ManagedQueueMBeanTest extends QpidBrokerTestCase
+public class QueueManagementTest extends QpidBrokerTestCase
{
- protected static final Logger LOGGER = Logger.getLogger(ManagedQueueMBeanTest.class);
+
+ 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;
@@ -69,6 +83,7 @@ public class ManagedQueueMBeanTest extends QpidBrokerTestCase
private ManagedQueue _managedSourceQueue;
private ManagedQueue _managedDestinationQueue;
+
public void setUp() throws Exception
{
_jmxUtils = new JMXTestUtils(this);
@@ -102,6 +117,218 @@ public class ManagedQueueMBeanTest extends QpidBrokerTestCase
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<String, Object> 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<String, Object> 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<String, Object> 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 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 = "amq.fanout";
+ 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.
*/
@@ -129,7 +356,7 @@ public class ManagedQueueMBeanTest extends QpidBrokerTestCase
final Map<String, String> headers = headerArrayToMap(headerArray);
final String expectedJMSMessageID = isBroker010() ? sentMessage.getJMSMessageID().replace("ID:", "") : sentMessage.getJMSMessageID();
- final String expectedFormattedJMSTimestamp = FastDateFormat.getInstance(AMQQueueMBean.JMSTIMESTAMP_DATETIME_FORMAT).format(sentMessage.getJMSTimestamp());
+ 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"));
@@ -224,7 +451,7 @@ public class ManagedQueueMBeanTest extends QpidBrokerTestCase
asyncConnection.stop();
// The exact number of messages moved will be non deterministic, as the number of messages processed
- // by the consumer cannot be predicited. There is also the possibility that a message can remain
+ // 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.
//
@@ -342,4 +569,41 @@ public class ManagedQueueMBeanTest extends QpidBrokerTestCase
((AMQSession<?,?>)session).sync();
}
+ private final class RecordingNotificationListener implements NotificationListener
+ {
+ private final CountDownLatch _notificationReceivedLatch;
+ private final AtomicInteger _numberOfNotifications;
+ private final AtomicReference<Notification> _lastNotification;
+
+ private RecordingNotificationListener(int expectedNumberOfNotifications)
+ {
+ _notificationReceivedLatch = new CountDownLatch(expectedNumberOfNotifications);
+ _numberOfNotifications = new AtomicInteger(0);
+ _lastNotification = new AtomicReference<Notification>();
+ }
+
+ @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/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java
new file mode 100644
index 0000000000..c3fff94923
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.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<ManagedConnection> 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/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java
new file mode 100644
index 0000000000..62b1b554a9
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.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.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<? extends PrincipalDatabase> 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/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java
new file mode 100644
index 0000000000..84a66232ce
--- /dev/null
+++ b/qpid/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.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.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<? extends PrincipalDatabase> getPrincipalDatabaseImplClass()
+ {
+ return Base64MD5PasswordFilePrincipalDatabase.class;
+ }
+
+}
diff --git a/qpid/java/broker-plugins/management/MANIFEST.MF b/qpid/java/broker-plugins/management/MANIFEST.MF
new file mode 100644
index 0000000000..d817ac5302
--- /dev/null
+++ b/qpid/java/broker-plugins/management/MANIFEST.MF
@@ -0,0 +1,66 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Qpid Broker-Plugins Management
+Bundle-SymbolicName: broker-plugins-management
+Bundle-Description: 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.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.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.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/qpid/java/broker-plugins/management/build.xml b/qpid/java/broker-plugins/management/build.xml
new file mode 100644
index 0000000000..4a28ff2659
--- /dev/null
+++ b/qpid/java/broker-plugins/management/build.xml
@@ -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.
+ -->
+<project name="Qpid Broker-Plugins Management" default="build">
+ <property name="module.depends" value="common broker broker-plugins broker-plugins-management" />
+ <property name="module.test.depends" value="test broker/test common/test management/common" />
+
+ <property name="module.manifest" value="MANIFEST.MF" />
+ <property name="module.plugin" value="true" />
+
+ <import file="../../module.xml" />
+
+ <target name="precompile">
+ <unwar src="${project.root}/${dojo}" dest="${module.classes}/resources/dojo">
+ <patternset>
+ <exclude name="META-INF/**"/>
+ <exclude name="WEB-INF/**"/>
+ <exclude name="**/*.uncompressed.js"/>
+ </patternset>
+ </unwar>
+ </target>
+
+ <target name="bundle" depends="bundle-tasks" />
+</project>
diff --git a/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/Management.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/Management.java
new file mode 100644
index 0000000000..589f46749d
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/Management.java
@@ -0,0 +1,155 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Collection;
+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.*;
+import org.apache.qpid.server.model.*;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.SessionManager;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+
+public class Management
+{
+
+ private final Logger _logger = Logger.getLogger(Management.class);
+
+ private Broker _broker;
+
+ private Collection<Server> _servers = new ArrayList<Server>();
+
+
+ public Management()
+ {
+ _broker = ApplicationRegistry.getInstance().getBroker();
+
+ Collection<Port> ports = _broker.getPorts();
+ for(Port port : ports)
+ {
+ // TODO - cover cases where more than just HTTP supported, and SSL as a transport
+ if(port.getProtocols().contains(Protocol.HTTP))
+ {
+ if(port.getTransports().contains(Transport.TCP))
+ {
+ int portNumber = port.getPort();
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Creating web server on port " + portNumber);
+ }
+ _servers.add(createServer(portNumber));
+ }
+ }
+ }
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.info(_servers.size() + " server(s) defined");
+ }
+
+ }
+
+ private Server createServer(int port)
+ {
+ _logger.info("Starting up web server on port " + port);
+
+ Server server = new Server(port);
+ SocketAddress socketAddress = new InetSocketAddress(port);
+
+ 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", socketAddress);
+ addRestServlet(root, "virtualhost", socketAddress, VirtualHost.class);
+ addRestServlet(root, "authenticationprovider", socketAddress, AuthenticationProvider.class);
+ addRestServlet(root, "user", socketAddress, AuthenticationProvider.class, User.class);
+ addRestServlet(root, "exchange", socketAddress, VirtualHost.class, Exchange.class);
+ addRestServlet(root, "queue", socketAddress, VirtualHost.class, Queue.class);
+ addRestServlet(root, "connection", socketAddress, VirtualHost.class, Connection.class);
+ addRestServlet(root, "binding", socketAddress, VirtualHost.class, Exchange.class, Queue.class, Binding.class);
+ addRestServlet(root, "port", socketAddress, Port.class);
+ addRestServlet(root, "session", socketAddress, VirtualHost.class, Connection.class, Session.class);
+
+ root.addServlet(new ServletHolder(new StructureServlet(_broker, socketAddress)), "/rest/structure");
+ root.addServlet(new ServletHolder(new MessageServlet(_broker, socketAddress)), "/rest/message/*");
+ root.addServlet(new ServletHolder(new MessageContentServlet(_broker, socketAddress)), "/rest/message-content/*");
+
+ root.addServlet(new ServletHolder(new LogRecordsServlet(_broker, socketAddress)), "/rest/logrecords");
+
+
+ root.addServlet(new ServletHolder(new SaslServlet(_broker, socketAddress)), "/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, SocketAddress socketAddress, Class<? extends ConfiguredObject>... hierarchy)
+ {
+ root.addServlet(new ServletHolder(new RestServlet(_broker, socketAddress, 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();
+ }
+ }
+
+}
diff --git a/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java
new file mode 100644
index 0000000000..2600d8a7bf
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.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.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())
+ {
+ _logger.info("Management plugin is diabled!");
+ 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/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java
new file mode 100644
index 0000000000..3866da8f89
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.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.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<String> 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/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java
new file mode 100644
index 0000000000..d66555787f
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java
@@ -0,0 +1,79 @@
+package org.apache.qpid.server.management.plugin.servlet;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class DefinedFileServlet extends HttpServlet
+{
+
+ private static final String FILENAME_INIT_PARAMETER = "filename";
+
+ private String _filename;
+
+ public DefinedFileServlet()
+ {
+ super();
+ }
+
+ public DefinedFileServlet(String filename)
+ {
+ _filename = filename;
+ }
+
+ @Override
+ public void init() throws ServletException
+ {
+ ServletConfig config = getServletConfig();
+ String fileName = config.getInitParameter(FILENAME_INIT_PARAMETER);
+ if (fileName != null && !"".equals(fileName))
+ {
+ _filename = fileName;
+ }
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ final ServletOutputStream output = response.getOutputStream();
+ InputStream fileInput = getClass().getResourceAsStream("/resources/"+_filename);
+
+ if(fileInput != null)
+ {
+ byte[] buffer = new byte[1024];
+ response.setStatus(HttpServletResponse.SC_OK);
+ int read = 0;
+
+ while((read = fileInput.read(buffer)) > 0)
+ {
+ output.write(buffer, 0, read);
+ }
+ }
+ else
+ {
+ response.sendError(404, "unknown file: "+ _filename);
+ }
+ }
+}
diff --git a/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java
new file mode 100644
index 0000000000..f8ca082d79
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.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.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;
+import java.util.Map;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class FileServlet extends HttpServlet
+{
+ public static final FileServlet INSTANCE = new FileServlet();
+
+ private static final Map<String, String> CONTENT_TYPES;
+
+ static
+ {
+
+ Map<String, String> contentTypes = new HashMap<String, String>();
+ contentTypes.put("js", "application/javascript");
+ contentTypes.put("html", "text/html");
+ contentTypes.put("css", "text/css");
+ contentTypes.put("json", "application/json");
+ contentTypes.put("jpg", "image/jpg");
+ contentTypes.put("png", "image/png");
+ contentTypes.put("gif", "image/gif");
+ CONTENT_TYPES = Collections.unmodifiableMap(contentTypes);
+ }
+
+
+ public FileServlet()
+ {
+ }
+
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ String filename = request.getServletPath();
+ if(filename.contains("."))
+ {
+ String suffix = filename.substring(filename.lastIndexOf('.')+1);
+ String contentType = CONTENT_TYPES.get(suffix);
+ if(contentType != null)
+ {
+ response.setContentType(contentType);
+ }
+ }
+ URL resourceURL = getClass().getResource("/resources" + filename);
+ if(resourceURL != null)
+ {
+ response.setStatus(HttpServletResponse.SC_OK);
+ InputStream fileInput = resourceURL.openStream();
+ try
+ {
+ byte[] buffer = new byte[1024];
+ int read = 0;
+ ServletOutputStream output = response.getOutputStream();
+ try
+ {
+ while((read = fileInput.read(buffer)) != -1)
+ {
+ output.write(buffer, 0, read);
+ }
+ }
+ finally
+ {
+ output.close();
+ }
+ }
+ finally
+ {
+ fileInput.close();
+ }
+ }
+ else
+ {
+ response.sendError(404, "unknown file: "+ filename);
+ }
+
+ }
+
+}
diff --git a/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java
new file mode 100644
index 0000000000..a3c5ec68a2
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java
@@ -0,0 +1,208 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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<VirtualHost> vhosts = _broker.getVirtualHosts();
+ Collection<Exchange> exchanges = new ArrayList<Exchange>();
+ Collection<Map<String,Object>> outputObject = new ArrayList<Map<String,Object>>();
+
+ 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<String,Object> convertToObject(final Exchange exchange)
+ {
+ Map<String, Object> object = new LinkedHashMap<String, Object>();
+ 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<String,Object> arguments = new HashMap<String, Object>();
+ 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<String,Object> 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<String, Object> attributes = new HashMap<String, Object>(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/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java
new file mode 100644
index 0000000000..b2c0fcfe52
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java
@@ -0,0 +1,118 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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<VirtualHost> vhosts = _broker.getVirtualHosts();
+
+
+
+ final PrintWriter writer = response.getWriter();
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ if(request.getPathInfo() == null || request.getPathInfo().length()==0)
+ {
+
+ LinkedHashMap<String, Object> vhostObject = new LinkedHashMap<String, Object>();
+ List<Map> vhostList = new ArrayList<Map>();
+
+ for(VirtualHost vhost : vhosts)
+ {
+ vhostList.add(Collections.singletonMap("name", vhost.getName()));
+ }
+ mapper.writeValue(writer, vhostList);
+ }
+ else
+ {
+ LinkedHashMap<String, Object> vhostObject = new LinkedHashMap<String, Object>();
+ 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/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
new file mode 100644
index 0000000000..123f352ec1
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
@@ -0,0 +1,215 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.InetSocketAddress;
+import java.net.SocketAddress;
+import java.security.Principal;
+import java.util.Collections;
+import javax.security.auth.Subject;
+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.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.auth.manager.AnonymousAuthenticationManager;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+
+public abstract class AbstractServlet extends HttpServlet
+{
+ private final Broker _broker;
+ private SocketAddress _socketAddress;
+
+ protected AbstractServlet()
+ {
+ super();
+ _broker = ApplicationRegistry.getInstance().getBroker();
+ _socketAddress = null;
+ }
+
+ protected AbstractServlet(Broker broker, SocketAddress socketAddress)
+ {
+ _broker = broker;
+ _socketAddress = socketAddress;
+ }
+
+ @Override
+ protected final void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException
+ {
+ setAuthorizedSubject(request);
+ try
+ {
+ onGet(request, resp);
+ }
+ finally
+ {
+ clearAuthorizedSubject();
+ }
+ }
+
+ protected void onGet(HttpServletRequest request, HttpServletResponse resp) throws IOException, ServletException
+ {
+ super.doGet(request, resp);
+ }
+
+ private void clearAuthorizedSubject()
+ {
+ org.apache.qpid.server.security.SecurityManager.setThreadSubject(null);
+ }
+
+
+ private void setAuthorizedSubject(HttpServletRequest request)
+ {
+ HttpSession session = request.getSession(true);
+ Subject subject = (Subject) session.getAttribute("subject");
+
+ if(subject == null)
+ {
+ Principal principal = request.getUserPrincipal();
+ if(principal != null)
+ {
+ subject = new Subject(false, Collections.singleton(principal),Collections.emptySet(),
+ Collections.emptySet());
+ }
+ else
+ {
+ String header = request.getHeader("Authorization");
+
+ /*
+ * TODO - Should configure whether basic authentication is allowed... and in particular whether it
+ * should be allowed over non-ssl connections
+ * */
+
+ if (header != null)
+ {
+ String[] tokens = header.split("\\s");
+ if(tokens.length >= 2
+ && "BASIC".equalsIgnoreCase(tokens[0]))
+ {
+ String[] credentials = (new String(Base64.decodeBase64(tokens[1].getBytes()))).split(":",2);
+ if(credentials.length == 2)
+ {
+ SocketAddress address = getSocketAddress(request);
+ AuthenticationManager authenticationManager =
+ ApplicationRegistry.getInstance().getAuthenticationManager(address);
+ AuthenticationResult authResult =
+ authenticationManager.authenticate(credentials[0], credentials[1]);
+ subject = authResult.getSubject();
+
+ }
+ }
+ }
+ }
+ }
+ if (subject == null)
+ {
+ subject = AnonymousAuthenticationManager.ANONYMOUS_SUBJECT;
+ }
+ org.apache.qpid.server.security.SecurityManager.setThreadSubject(subject);
+
+ }
+
+ protected Subject getSubject(HttpSession session)
+ {
+ return (Subject)session.getAttribute("subject");
+ }
+
+ @Override
+ protected final void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ setAuthorizedSubject(req);
+ try
+ {
+ onPost(req, resp);
+ }
+ finally
+ {
+ clearAuthorizedSubject();
+ }
+
+ }
+
+ protected void onPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ super.doPost(req, resp);
+ }
+
+ @Override
+ protected final void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ setAuthorizedSubject(req);
+ try
+ {
+ onPut(req, resp);
+
+ }
+ finally
+ {
+ clearAuthorizedSubject();
+ }
+ }
+
+ protected void onPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException
+ {
+ super.doPut(req,resp);
+ }
+
+ @Override
+ protected final void doDelete(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException
+ {
+ setAuthorizedSubject(req);
+ try
+ {
+ onDelete(req, resp);
+ }
+ finally
+ {
+ clearAuthorizedSubject();
+ }
+ }
+
+ protected void onDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ super.doDelete(req, resp);
+ }
+
+
+ protected Broker getBroker()
+ {
+ return _broker;
+ }
+
+ protected SocketAddress getSocketAddress(HttpServletRequest request)
+ {
+ if (_socketAddress == null)
+ {
+ return InetSocketAddress.createUnresolved(request.getServerName(), request.getServerPort());
+ }
+ return _socketAddress;
+ }
+}
diff --git a/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.java
new file mode 100644
index 0000000000..3d862ce321
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.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.management.plugin.servlet.rest;
+
+import java.util.Comparator;
+import java.util.Map;
+
+class KeyComparator implements Comparator<Map>
+{
+ private String _key;
+
+ public KeyComparator(final String key)
+ {
+ _key = key;
+ }
+
+ public int compare(final Map o1, final Map o2)
+ {
+ Comparable left = (Comparable) o1.get(_key);
+ Comparable right = (Comparable) o2.get(_key);
+
+ int result;
+ if(left == null)
+ {
+ result = right == null ? 0 : -1;
+ }
+ else
+ {
+ result = left.compareTo(right);
+ }
+
+ return result;
+
+ }
+}
diff --git a/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java
new file mode 100644
index 0000000000..7a4b92f907
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.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.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+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;
+
+public class LogRecordsServlet extends AbstractServlet
+{
+ public LogRecordsServlet()
+ {
+ super(ApplicationRegistry.getInstance().getBroker(), null);
+ }
+
+ public LogRecordsServlet(Broker broker, SocketAddress socketaddress)
+ {
+ super(broker, socketaddress);
+ }
+
+ @Override
+ protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+
+ ApplicationRegistry applicationRegistry = (ApplicationRegistry) ApplicationRegistry.getInstance();
+ List<Map<String,Object>> logRecords = new ArrayList<Map<String, Object>>();
+
+ for(LogRecorder.Record record : applicationRegistry.getLogRecorder())
+ {
+ logRecords.add(logRecordToObject(record));
+ }
+
+ final PrintWriter writer = response.getWriter();
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, logRecords);
+
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ }
+
+ private Map<String, Object> logRecordToObject(LogRecorder.Record record)
+ {
+ Map<String, Object> recordMap = new LinkedHashMap<String, Object>();
+ recordMap.put("id",record.getId());
+ recordMap.put("timestamp", record.getTimestamp());
+ recordMap.put("level", record.getLevel());
+ recordMap.put("thread", record.getThreadName());
+ recordMap.put("logger", record.getLogger());
+ recordMap.put("message", record.getMessage());
+ return recordMap;
+ }
+
+}
diff --git a/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.java
new file mode 100644
index 0000000000..84d987813b
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.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.servlet.rest;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Map;
+
+class MapComparator implements Comparator<Map>
+{
+ private Comparator<Map>[] _sortKeys;
+
+ public MapComparator(final String[] sortKeys)
+ {
+ _sortKeys = parseKeys(sortKeys);
+ }
+
+ private static Comparator<Map>[] parseKeys(final String[] sortKeys)
+ {
+ Comparator<Map>[] comparators = new Comparator[sortKeys.length];
+ for(int i = 0; i < sortKeys.length; i++)
+ {
+ String key = sortKeys[i];
+
+ if(key.startsWith("+") || key.startsWith(" "))
+ {
+ comparators[i] = new KeyComparator(key.substring(1));
+ }
+ else if(key.startsWith("-"))
+ {
+ comparators[i] = Collections.reverseOrder(new KeyComparator(key.substring(1)));
+ }
+ else
+ {
+ comparators[i] = new KeyComparator(key);
+ }
+ }
+ return comparators;
+ }
+
+
+ public int compare(final Map o1, final Map o2)
+ {
+ int result = 0;
+ for(int i = 0; i < _sortKeys.length; i++)
+ {
+ result = _sortKeys[i].compare(o1, o2);
+ if(result != 0)
+ {
+ return result;
+ }
+ }
+ return 0;
+ }
+
+}
diff --git a/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java
new file mode 100644
index 0000000000..4d58a9f3b0
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.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.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+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;
+import org.apache.qpid.server.queue.QueueEntryVisitor;
+
+public class MessageContentServlet extends AbstractServlet
+{
+ public MessageContentServlet()
+ {
+ super();
+ }
+
+ public MessageContentServlet(Broker broker, SocketAddress socketaddress)
+ {
+ super(broker, socketaddress);
+ }
+
+ @Override
+ protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0 && request.getPathInfo().substring(1).split("/").length > 2)
+ {
+ getMessageContent(request, response);
+ }
+
+ }
+
+ private void getMessageContent(HttpServletRequest request, HttpServletResponse response) throws IOException
+ {
+ Queue queue = getQueueFromRequest(request);
+ String path[] = request.getPathInfo().substring(1).split("/");
+ MessageFinder finder = new MessageFinder(Long.parseLong(path[2]));
+ queue.visit(finder);
+ if(finder.isFound())
+ {
+ response.setContentType(finder.getMimeType());
+ response.setContentLength((int) finder.getSize());
+ response.getOutputStream().write(finder.getContent());
+
+ }
+
+ }
+
+ private Queue getQueueFromRequest(HttpServletRequest request)
+ {
+ List<String> names = new ArrayList<String>();
+ // TODO - validation that there is a vhost and queue and only those in the path
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0)
+ {
+ String path = request.getPathInfo().substring(1);
+ names.addAll(Arrays.asList(path.split("/")));
+ }
+ String vhostName = names.get(0);
+ String queueName = names.get(1);
+
+ VirtualHost vhost = null;
+
+ for(VirtualHost vh : getBroker().getVirtualHosts())
+ {
+ if(vh.getName().equals(vhostName))
+ {
+ vhost = vh;
+ break;
+ }
+ }
+
+ return getQueueFromVirtualHost(queueName, vhost);
+ }
+
+ private Queue getQueueFromVirtualHost(String queueName, VirtualHost vhost)
+ {
+ Queue queue = null;
+
+ for(Queue q : vhost.getQueues())
+ {
+ if(q.getName().equals(queueName))
+ {
+ queue = q;
+ break;
+ }
+ }
+ return queue;
+ }
+
+ private class MessageFinder implements QueueEntryVisitor
+ {
+ private final long _messageNumber;
+ private String _mimeType;
+ private long _size;
+ private byte[] _content;
+ private boolean _found;
+
+ private MessageFinder(long messageNumber)
+ {
+ _messageNumber = messageNumber;
+ }
+
+
+ public boolean visit(QueueEntry entry)
+ {
+ ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ if(_messageNumber == message.getMessageNumber())
+ {
+ MessageReference reference = message.newReference();
+
+ _mimeType = message.getMessageHeader().getMimeType();
+ _size = message.getSize();
+ _content = new byte[(int)_size];
+ _found = true;
+ message.getContent(ByteBuffer.wrap(_content),0);
+ reference.release();
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ public String getMimeType()
+ {
+ return _mimeType;
+ }
+
+ public long getSize()
+ {
+ return _size;
+ }
+
+ public byte[] getContent()
+ {
+ return _content;
+ }
+
+ public boolean isFound()
+ {
+ return _found;
+ }
+ }
+
+
+}
diff --git a/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java
new file mode 100644
index 0000000000..b47dc8b28e
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java
@@ -0,0 +1,503 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.PrintWriter;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+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;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
+
+public class MessageServlet extends AbstractServlet
+{
+ private static final Logger LOGGER = Logger.getLogger(MessageServlet.class);
+
+ public MessageServlet()
+ {
+ super();
+ }
+
+ public MessageServlet(Broker broker, SocketAddress socketaddress)
+ {
+ super(broker, socketaddress);
+ }
+
+ @Override
+ protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0 && request.getPathInfo().substring(1).split("/").length > 2)
+ {
+ getMessageContent(request, response);
+ }
+ else
+ {
+ getMessageList(request, response);
+ }
+
+ }
+
+ private void getMessageContent(HttpServletRequest request, HttpServletResponse response) throws IOException
+ {
+ Queue queue = getQueueFromRequest(request);
+ String path[] = request.getPathInfo().substring(1).split("/");
+ MessageFinder messageFinder = new MessageFinder(Long.parseLong(path[2]));
+ queue.visit(messageFinder);
+
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+
+ final PrintWriter writer = response.getWriter();
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, messageFinder.getMessageObject());
+ }
+
+ private void getMessageList(HttpServletRequest request, HttpServletResponse response) throws IOException
+ {
+ Queue queue = getQueueFromRequest(request);
+
+ int first = -1;
+ int last = -1;
+ String range = request.getHeader("Range");
+ if(range != null)
+ {
+ String[] boundaries = range.split("=")[1].split("-");
+ first = Integer.parseInt(boundaries[0]);
+ last = Integer.parseInt(boundaries[1]);
+ }
+ final MessageCollector messageCollector = new MessageCollector(first, last);
+ queue.visit(messageCollector);
+
+ response.setContentType("application/json");
+ final List<Map<String, Object>> messages = messageCollector.getMessages();
+ int queueSize = ((Number) queue.getStatistics().getStatistic(Queue.QUEUE_DEPTH_MESSAGES)).intValue();
+ String min = messages.isEmpty() ? "0" : messages.get(0).get("position").toString();
+ String max = messages.isEmpty() ? "0" : messages.get(messages.size()-1).get("position").toString();
+ response.setHeader("Content-Range", (min + "-" + max + "/" + queueSize));
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+
+ final PrintWriter writer = response.getWriter();
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, messages);
+ }
+
+ private Queue getQueueFromRequest(HttpServletRequest request)
+ {
+ List<String> names = new ArrayList<String>();
+ // TODO - validation that there is a vhost and queue and only those in the path
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0)
+ {
+ String path = request.getPathInfo().substring(1);
+ names.addAll(Arrays.asList(path.split("/")));
+ }
+ String vhostName = names.get(0);
+ String queueName = names.get(1);
+
+ VirtualHost vhost = null;
+
+ for(VirtualHost vh : getBroker().getVirtualHosts())
+ {
+ if(vh.getName().equals(vhostName))
+ {
+ vhost = vh;
+ break;
+ }
+ }
+
+ return getQueueFromVirtualHost(queueName, vhost);
+ }
+
+ private Queue getQueueFromVirtualHost(String queueName, VirtualHost vhost)
+ {
+ Queue queue = null;
+
+ for(Queue q : vhost.getQueues())
+ {
+
+ if(q.getName().equals(queueName))
+ {
+ queue = q;
+ break;
+ }
+ }
+ return queue;
+ }
+
+ private abstract static class QueueEntryTransaction implements VirtualHost.TransactionalOperation
+ {
+ private final Queue _sourceQueue;
+ private final List _messageIds;
+
+ protected QueueEntryTransaction(Queue sourceQueue, List messageIds)
+ {
+ _sourceQueue = sourceQueue;
+ _messageIds = messageIds;
+ }
+
+
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+
+ _sourceQueue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ final ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ final long messageId = message.getMessageNumber();
+ if (_messageIds.remove(messageId) || (messageId <= (long) Integer.MAX_VALUE
+ && _messageIds.remove(Integer.valueOf((int)messageId))))
+ {
+ updateEntry(entry, txn);
+ }
+ }
+ return _messageIds.isEmpty();
+ }
+ });
+ }
+
+
+ protected abstract void updateEntry(QueueEntry entry, VirtualHost.Transaction txn);
+ }
+
+ private static class MoveTransaction extends QueueEntryTransaction
+ {
+ private final Queue _destinationQueue;
+
+ public MoveTransaction(Queue sourceQueue, List<Long> messageIds, Queue destinationQueue)
+ {
+ super(sourceQueue, messageIds);
+ _destinationQueue = destinationQueue;
+ }
+
+ protected void updateEntry(QueueEntry entry, VirtualHost.Transaction txn)
+ {
+ txn.move(entry, _destinationQueue);
+ }
+ }
+
+ private static class CopyTransaction extends QueueEntryTransaction
+ {
+ private final Queue _destinationQueue;
+
+ public CopyTransaction(Queue sourceQueue, List<Long> messageIds, Queue destinationQueue)
+ {
+ super(sourceQueue, messageIds);
+ _destinationQueue = destinationQueue;
+ }
+
+ protected void updateEntry(QueueEntry entry, VirtualHost.Transaction txn)
+ {
+ txn.copy(entry, _destinationQueue);
+ }
+ }
+
+ private static class DeleteTransaction extends QueueEntryTransaction
+ {
+ public DeleteTransaction(Queue sourceQueue, List<Long> messageIds)
+ {
+ super(sourceQueue, messageIds);
+ }
+
+ protected void updateEntry(QueueEntry entry, VirtualHost.Transaction txn)
+ {
+ txn.dequeue(entry);
+ }
+ }
+
+
+
+ private class MessageCollector implements QueueEntryVisitor
+ {
+ private final int _first;
+ private final int _last;
+ private int _position = -1;
+ private final List<Map<String, Object>> _messages = new ArrayList<Map<String, Object>>();
+
+ private MessageCollector(int first, int last)
+ {
+ _first = first;
+ _last = last;
+ }
+
+
+ public boolean visit(QueueEntry entry)
+ {
+
+ _position++;
+ if((_first == -1 || _position >= _first) && (_last == -1 || _position <= _last))
+ {
+ final Map<String, Object> messageObject = convertToObject(entry, false);
+ messageObject.put("position", _position);
+ _messages.add(messageObject);
+ }
+ return _last != -1 && _position > _last;
+ }
+
+ public List<Map<String, Object>> getMessages()
+ {
+ return _messages;
+ }
+ }
+
+
+ private class MessageFinder implements QueueEntryVisitor
+ {
+ private final long _messageNumber;
+ private Map<String, Object> _messageObject;
+
+ private MessageFinder(long messageNumber)
+ {
+ _messageNumber = messageNumber;
+ }
+
+
+ public boolean visit(QueueEntry entry)
+ {
+ ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ if(_messageNumber == message.getMessageNumber())
+ {
+ MessageReference reference = message.newReference();
+ _messageObject = convertToObject(entry, true);
+ reference.release();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Map<String, Object> getMessageObject()
+ {
+ return _messageObject;
+ }
+ }
+
+ private Map<String, Object> convertToObject(QueueEntry entry, boolean includeContent)
+ {
+ Map<String, Object> object = new LinkedHashMap<String, Object>();
+ object.put("size", entry.getSize());
+ object.put("deliveryCount", entry.getDeliveryCount());
+ object.put("state",entry.isAvailable()
+ ? "Available"
+ : entry.isAcquired()
+ ? "Acquired"
+ : "");
+ final Subscription deliveredSubscription = entry.getDeliveredSubscription();
+ object.put("deliveredTo", deliveredSubscription == null ? null : deliveredSubscription.getSubscriptionID());
+ ServerMessage message = entry.getMessage();
+
+ if(message != null)
+ {
+ convertMessageProperties(object, message);
+ if(includeContent)
+ {
+ convertMessageHeaders(object, message);
+ }
+ }
+
+ return object;
+ }
+
+ private void convertMessageProperties(Map<String, Object> object, ServerMessage message)
+ {
+ object.put("id", message.getMessageNumber());
+ object.put("arrivalTime",message.getArrivalTime());
+ object.put("persistent", message.isPersistent());
+
+ final AMQMessageHeader messageHeader = message.getMessageHeader();
+ if(messageHeader != null)
+ {
+ addIfPresent(object, "messageId", messageHeader.getMessageId());
+ addIfPresent(object, "expirationTime", messageHeader.getExpiration());
+ addIfPresent(object, "applicationId", messageHeader.getAppId());
+ addIfPresent(object, "correlationId", messageHeader.getCorrelationId());
+ addIfPresent(object, "encoding", messageHeader.getEncoding());
+ addIfPresent(object, "mimeType", messageHeader.getMimeType());
+ addIfPresent(object, "priority", messageHeader.getPriority());
+ addIfPresent(object, "replyTo", messageHeader.getReplyTo());
+ addIfPresent(object, "timestamp", messageHeader.getTimestamp());
+ addIfPresent(object, "type", messageHeader.getType());
+ addIfPresent(object, "userId", messageHeader.getUserId());
+ }
+
+ }
+
+ private void addIfPresent(Map<String, Object> object, String name, Object property)
+ {
+ if(property != null)
+ {
+ object.put(name, property);
+ }
+ }
+
+ private void convertMessageHeaders(Map<String, Object> object, ServerMessage message)
+ {
+ final AMQMessageHeader messageHeader = message.getMessageHeader();
+ if(messageHeader != null)
+ {
+ Map<String, Object> headers = new HashMap<String,Object>();
+ for(String headerName : messageHeader.getHeaderNames())
+ {
+ headers.put(headerName, messageHeader.getHeader(headerName));
+ }
+ object.put("headers", headers);
+ }
+ }
+
+ /*
+ * 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
+ {
+
+ try
+ {
+ final Queue sourceQueue = getQueueFromRequest(request);
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ @SuppressWarnings("unchecked")
+ Map<String,Object> providedObject = mapper.readValue(request.getInputStream(), LinkedHashMap.class);
+
+ String destQueueName = (String) providedObject.get("destinationQueue");
+ Boolean move = (Boolean) providedObject.get("move");
+
+ final VirtualHost vhost = sourceQueue.getParent(VirtualHost.class);
+
+ boolean isMoveTransaction = move != null && Boolean.valueOf(move);
+
+ // 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()))
+ {
+ final Queue destinationQueue = getQueueFromVirtualHost(destQueueName, vhost);
+ final List messageIds = new ArrayList((List) providedObject.get("messages"));
+ QueueEntryTransaction txn =
+ isMoveTransaction
+ ? new MoveTransaction(sourceQueue, messageIds, destinationQueue)
+ : new CopyTransaction(sourceQueue, messageIds, destinationQueue);
+ vhost.executeTransaction(txn);
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+ else
+ {
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ }
+ catch(RuntimeException e)
+ {
+ LOGGER.error("Failure to perform message opertion", e);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+
+ /*
+ * DELETE removes messages from the queue
+ */
+ @Override
+ protected void onDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+
+ final Queue sourceQueue = getQueueFromRequest(request);
+
+ final VirtualHost vhost = sourceQueue.getParent(VirtualHost.class);
+
+
+ final List<Long> messageIds = new ArrayList<Long>();
+ for(String idStr : request.getParameterValues("id"))
+ {
+ messageIds.add(Long.valueOf(idStr));
+ }
+
+ // 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()))
+ {
+ vhost.executeTransaction(new DeleteTransaction(sourceQueue, messageIds));
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+ else
+ {
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+
+ }
+
+ private boolean isQueueUpdateMethodAuthorized(String methodName, String virtualHost)
+ {
+ SecurityManager securityManager = getSecurityManager(virtualHost);
+ 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/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
new file mode 100644
index 0000000000..96e260da56
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
@@ -0,0 +1,576 @@
+package org.apache.qpid.server.management.plugin.servlet.rest;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.SocketAddress;
+import java.util.*;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.qpid.AMQSecurityException;
+import org.apache.qpid.server.model.*;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class RestServlet extends AbstractServlet
+{
+ /**
+ * An initialization parameter to specify hierarchy
+ */
+ private static final String HIERARCHY_INIT_PARAMETER = "hierarchy";
+
+ public static final String DEPTH_PARAM = "depth";
+ public static final String SORT_PARAM = "sort";
+
+ public static final Set<String> RESERVED_PARAMS = new HashSet<String>(Arrays.asList(DEPTH_PARAM, SORT_PARAM));
+
+ private Class<? extends ConfiguredObject>[] _hierarchy;
+
+ private volatile boolean initializationRequired = false;
+
+ public RestServlet()
+ {
+ super();
+ initializationRequired = true;
+ }
+
+ public RestServlet(Broker broker, SocketAddress socketaddress, Class<? extends ConfiguredObject>... hierarchy)
+ {
+ super(broker, socketaddress);
+ _hierarchy = hierarchy;
+ }
+
+ @Override
+ public void init() throws ServletException
+ {
+ if (initializationRequired)
+ {
+ doInitialization();
+ initializationRequired = false;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void doInitialization() throws ServletException
+ {
+ ServletConfig config = getServletConfig();
+ String hierarchy = config.getInitParameter(HIERARCHY_INIT_PARAMETER);
+ if (hierarchy != null && !"".equals(hierarchy))
+ {
+ List<Class<? extends ConfiguredObject>> classes = new ArrayList<Class<? extends ConfiguredObject>>();
+ String[] hierarchyItems = hierarchy.split(",");
+ for (String item : hierarchyItems)
+ {
+ Class<?> itemClass = null;
+ try
+ {
+ itemClass = Class.forName(item);
+ }
+ catch (ClassNotFoundException e)
+ {
+ try
+ {
+ itemClass = Class.forName("org.apache.qpid.server.model." + item);
+ }
+ catch (ClassNotFoundException e1)
+ {
+ throw new ServletException("Unknown configured object class '" + item
+ + "' is specified in hierarchy for " + config.getServletName());
+ }
+ }
+ Class<? extends ConfiguredObject> clazz = (Class<? extends ConfiguredObject>)itemClass;
+ classes.add(clazz);
+ }
+ Class<? extends ConfiguredObject>[] hierachyClasses = (Class<? extends ConfiguredObject>[])new Class[classes.size()];
+ _hierarchy = classes.toArray(hierachyClasses);
+ }
+ else
+ {
+ _hierarchy = (Class<? extends ConfiguredObject>[])new Class[0];
+ }
+ }
+
+ protected Collection<ConfiguredObject> getObjects(HttpServletRequest request)
+ {
+ List<String> names = new ArrayList<String>();
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0)
+ {
+ String path = request.getPathInfo().substring(1);
+ names.addAll(Arrays.asList(path.split("/")));
+
+ if(names.size() > _hierarchy.length)
+ {
+ throw new IllegalArgumentException("Too many entries in path");
+ }
+ }
+
+ Collection<ConfiguredObject> parents = Collections.singleton((ConfiguredObject) getBroker());
+ Collection<ConfiguredObject> children = new ArrayList<ConfiguredObject>();
+
+ Map<Class<? extends ConfiguredObject>, String> filters =
+ new HashMap<Class<? extends ConfiguredObject>, String>();
+
+ for(int i = 0; i < _hierarchy.length; i++)
+ {
+ if(i == 0 || Model.getChildTypes(_hierarchy[i - 1]).contains(_hierarchy[i]))
+ {
+
+ for(ConfiguredObject parent : parents)
+ {
+ if(names.size() > i
+ && names.get(i) != null
+ && !names.get(i).equals("*")
+ && names.get(i).trim().length() != 0)
+ {
+ for(ConfiguredObject child : parent.getChildren(_hierarchy[i]))
+ {
+ if(child.getName().equals(names.get(i)))
+ {
+ children.add(child);
+ }
+ }
+ }
+ else
+ {
+ children.addAll(parent.getChildren(_hierarchy[i]));
+ }
+ }
+ }
+ else
+ {
+ children = parents;
+ if(names.size() > i
+ && names.get(i) != null
+ && !names.get(i).equals("*")
+ && names.get(i).trim().length() != 0)
+ {
+ filters.put(_hierarchy[i], names.get(i));
+ }
+ }
+
+ parents = children;
+ children = new ArrayList<ConfiguredObject>();
+ }
+
+ if(!filters.isEmpty())
+ {
+ Collection<ConfiguredObject> potentials = parents;
+ parents = new ArrayList<ConfiguredObject>();
+
+ for(ConfiguredObject o : potentials)
+ {
+
+ boolean match = true;
+
+ for(Map.Entry<Class<? extends ConfiguredObject>, String> entry : filters.entrySet())
+ {
+ Collection<? extends ConfiguredObject> ancestors =
+ getAncestors(getConfiguredClass(),entry.getKey(), o);
+ match = false;
+ for(ConfiguredObject ancestor : ancestors)
+ {
+ if(ancestor.getName().equals(entry.getValue()))
+ {
+ match = true;
+ break;
+ }
+ }
+ if(!match)
+ {
+ break;
+ }
+ }
+ if(match)
+ {
+ parents.add(o);
+ }
+
+ }
+ }
+
+ return filter(parents, request);
+ }
+
+ private Collection<ConfiguredObject> filter(Collection<ConfiguredObject> objects, HttpServletRequest request)
+ {
+
+
+ Map<String, Collection<String>> filters = new HashMap<String, Collection<String>>();
+
+ for(String param : (Collection<String>) Collections.list(request.getParameterNames()))
+ {
+ if(!RESERVED_PARAMS.contains(param))
+ {
+ filters.put(param, Arrays.asList(request.getParameterValues(param)));
+ }
+ }
+
+ if(filters.isEmpty())
+ {
+ return objects;
+ }
+
+ Collection<ConfiguredObject> filteredObj = new ArrayList<ConfiguredObject>(objects);
+
+ Iterator<ConfiguredObject> iter = filteredObj.iterator();
+
+ while(iter.hasNext())
+ {
+ ConfiguredObject obj = iter.next();
+ for(Map.Entry<String, Collection<String>> entry : filters.entrySet())
+ {
+ Object value = obj.getAttribute(entry.getKey());
+ if(!entry.getValue().contains(String.valueOf(value)))
+ {
+ iter.remove();
+ }
+ }
+
+ }
+
+ return filteredObj;
+ }
+
+ private Collection<? extends ConfiguredObject> getAncestors(Class<? extends ConfiguredObject> childType,
+ Class<? extends ConfiguredObject> ancestorType,
+ ConfiguredObject child)
+ {
+ Collection<ConfiguredObject> ancestors = new HashSet<ConfiguredObject>();
+ Collection<Class<? extends ConfiguredObject>> parentTypes = Model.getParentTypes(childType);
+
+ for(Class<? extends ConfiguredObject> parentClazz : parentTypes)
+ {
+ if(parentClazz == ancestorType)
+ {
+ ConfiguredObject parent = child.getParent(parentClazz);
+ if(parent != null)
+ {
+ ancestors.add(parent);
+ }
+ }
+ else
+ {
+ ConfiguredObject parent = child.getParent(parentClazz);
+ if(parent != null)
+ {
+ ancestors.addAll(getAncestors(parentClazz, ancestorType, parent));
+ }
+ }
+ }
+
+ return ancestors;
+ }
+
+
+ protected Map<String, Object> convertObjectToMap(final ConfiguredObject confObject,
+ Class<? extends ConfiguredObject> clazz,
+ int depth)
+ {
+ Map<String, Object> object = new LinkedHashMap<String, Object>();
+
+ for(String name : confObject.getAttributeNames())
+ {
+ Object value = confObject.getAttribute(name);
+ if(value != null)
+ {
+ object.put(name, value);
+ }
+ }
+
+ Statistics statistics = confObject.getStatistics();
+ Map<String, Object> statMap = new HashMap<String, Object>();
+ for(String name : statistics.getStatisticNames())
+ {
+ Object value = statistics.getStatistic(name);
+ if(value != null)
+ {
+ statMap.put(name, value);
+ }
+ }
+
+ if(!statMap.isEmpty())
+ {
+ object.put("statistics", statMap);
+ }
+
+ if(depth > 0)
+ {
+ for(Class<? extends ConfiguredObject> childClass : Model.getChildTypes(clazz))
+ {
+ Collection<? extends ConfiguredObject> children = confObject.getChildren(childClass);
+ if(children != null)
+ {
+ List<Map<String, Object>> childObjects = new ArrayList<Map<String, Object>>();
+
+ for(ConfiguredObject child : children)
+ {
+ childObjects.add(convertObjectToMap(child, childClass, depth-1));
+ }
+
+ if(!childObjects.isEmpty())
+ {
+ object.put(childClass.getSimpleName().toLowerCase()+"s",childObjects);
+ }
+ }
+ }
+ }
+ return object;
+ }
+
+ @Override
+ protected void onGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+
+ Collection<ConfiguredObject> allObjects = getObjects(request);
+
+ @SuppressWarnings("unchecked")
+ Map params = new HashMap(request.getParameterMap());
+
+ int depth = 1;
+ try
+ {
+ depth = Integer.parseInt(String.valueOf(params.remove("depth")));
+ }
+ catch (NumberFormatException e)
+ {
+ // Ignore
+ }
+
+ List<Map<String, Object>> output = new ArrayList<Map<String, Object>>();
+
+ // TODO - depth and sort special params, everything else should act as a filter
+ if(request.getParameter(DEPTH_PARAM)!=null)
+ {
+ try
+ {
+ depth = Integer.parseInt(request.getParameter(DEPTH_PARAM));
+ }
+ catch (NumberFormatException e)
+ {
+
+ }
+ }
+
+ for(ConfiguredObject configuredObject : allObjects)
+ {
+ output.add(convertObjectToMap(configuredObject, getConfiguredClass(),depth));
+ }
+
+ final PrintWriter writer = response.getWriter();
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, output);
+
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ }
+
+ private Class<? extends ConfiguredObject> getConfiguredClass()
+ {
+ return _hierarchy.length == 0 ? Broker.class : _hierarchy[_hierarchy.length-1];
+ }
+
+ @Override
+ protected void onPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ response.setContentType("application/json");
+
+ ObjectMapper mapper = new ObjectMapper();
+ @SuppressWarnings("unchecked")
+ Map<String,Object> providedObject = mapper.readValue(request.getInputStream(), LinkedHashMap.class);
+
+
+ List<String> names = new ArrayList<String>();
+ if(request.getPathInfo() != null && request.getPathInfo().length()>0)
+ {
+ String path = request.getPathInfo().substring(1);
+ names.addAll(Arrays.asList(path.split("/")));
+
+ if(names.size() != _hierarchy.length)
+ {
+ throw new IllegalArgumentException("Path to object to create must be fully specified");
+ }
+ }
+
+
+ providedObject.put("name", names.get(names.size()-1));
+
+ @SuppressWarnings("unchecked")
+ Collection<ConfiguredObject>[] objects = new Collection[_hierarchy.length];
+ if(_hierarchy.length == 1)
+ {
+ try
+ {
+ getBroker().createChild(_hierarchy[0], providedObject);
+ }
+ catch (RuntimeException e)
+ {
+ setResponseStatus(response, e);
+ return;
+ }
+
+ }
+ else
+ {
+ for(int i = 0; i < _hierarchy.length-1; i++)
+ {
+ objects[i] = new HashSet<ConfiguredObject>();
+ if(i == 0)
+ {
+ for(ConfiguredObject object : getBroker().getChildren(_hierarchy[0]))
+ {
+ if(object.getName().equals(names.get(0)))
+ {
+ objects[0].add(object);
+ break;
+ }
+ }
+ }
+ else
+ {
+ for(int j = i-1; j >=0; j--)
+ {
+ if(Model.getChildTypes(_hierarchy[j]).contains(_hierarchy[i]))
+ {
+ for(ConfiguredObject parent : objects[j])
+ {
+ for(ConfiguredObject object : parent.getChildren(_hierarchy[i]))
+ {
+ if(object.getName().equals(names.get(i)))
+ {
+ objects[i].add(object);
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ }
+ List<ConfiguredObject> parents = new ArrayList<ConfiguredObject>();
+ Class<? extends ConfiguredObject> objClass = getConfiguredClass();
+ Collection<Class<? extends ConfiguredObject>> parentClasses = Model.getParentTypes(objClass);
+ for(int i = _hierarchy.length-2; i >=0 ; i--)
+ {
+ if(parentClasses.contains(_hierarchy[i]))
+ {
+ if(objects[i].size() == 1)
+ {
+ parents.add(objects[i].iterator().next());
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot deduce parent of class "
+ + _hierarchy[i].getSimpleName());
+ }
+ }
+
+ }
+ ConfiguredObject theParent = parents.remove(0);
+ ConfiguredObject[] otherParents = parents.toArray(new ConfiguredObject[parents.size()]);
+
+ try
+ {
+
+ Collection<? extends ConfiguredObject> existingChildren = theParent.getChildren(objClass);
+ for(ConfiguredObject obj: existingChildren)
+ {
+ if((providedObject.containsKey("id") && String.valueOf(providedObject.get("id")).equals(obj.getId().toString()))
+ || (obj.getName().equals(providedObject.get("name")) && equalParents(obj, otherParents)))
+ {
+ doUpdate(obj, providedObject);
+ }
+ }
+ theParent.createChild(objClass, providedObject, otherParents);
+ }
+ catch (RuntimeException e)
+ {
+ setResponseStatus(response, e);
+ return;
+ }
+
+ }
+ response.setStatus(HttpServletResponse.SC_CREATED);
+ }
+
+ private void doUpdate(ConfiguredObject obj, Map<String, Object> providedObject)
+ {
+ for(Map.Entry<String,Object> entry : providedObject.entrySet())
+ {
+ obj.setAttribute(entry.getKey(), obj.getAttribute(entry.getKey()), entry.getValue());
+ }
+ //TODO - Implement.
+ }
+
+ private boolean equalParents(ConfiguredObject obj, ConfiguredObject[] otherParents)
+ {
+ if(otherParents == null || otherParents.length == 0)
+ {
+ return true;
+ }
+ return false; //TODO - Implement.
+ }
+
+ private void setResponseStatus(HttpServletResponse response, RuntimeException e) throws IOException
+ {
+ if (e.getCause() instanceof AMQSecurityException)
+ {
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ else
+ {
+ // TODO
+ response.setStatus(HttpServletResponse.SC_CONFLICT);
+ }
+ }
+
+ @Override
+ protected void onDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+ try
+ {
+ Collection<ConfiguredObject> allObjects = getObjects(request);
+ for(ConfiguredObject o : allObjects)
+ {
+ o.setDesiredState(o.getActualState(), State.DELETED);
+ }
+
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+ catch(RuntimeException e)
+ {
+ setResponseStatus(response, e);
+ }
+ }
+}
diff --git a/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
new file mode 100644
index 0000000000..4ca2d270dd
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
@@ -0,0 +1,253 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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 org.apache.commons.codec.binary.Base64;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
+
+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 javax.security.auth.Subject;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.SocketAddress;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Random;
+
+public class SaslServlet extends AbstractServlet
+{
+
+ private static final SecureRandom SECURE_RANDOM = new SecureRandom();
+ private static final String ATTR_RANDOM = "SaslServlet.Random";
+ private static final String ATTR_ID = "SaslServlet.ID";
+ private static final String ATTR_SASL_SERVER = "SaslServlet.SaslServer";
+ private static final String ATTR_EXPIRY = "SaslServlet.Expiry";
+ private static final long SASL_EXCHANGE_EXPIRY = 1000L;
+
+
+ public SaslServlet()
+ {
+ super();
+ }
+
+ public SaslServlet(Broker broker, SocketAddress socketaddress)
+ {
+ super(broker, socketaddress);
+ }
+
+ protected void onGet(HttpServletRequest request, HttpServletResponse response) throws
+ ServletException,
+ IOException
+ {
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+
+ HttpSession session = request.getSession();
+ Random rand = getRandom(session);
+
+ AuthenticationManager authManager = ApplicationRegistry.getInstance().getAuthenticationManager(getSocketAddress(request));
+ String[] mechanisms = authManager.getMechanisms().split(" ");
+ Map<String, Object> outputObject = new LinkedHashMap<String, Object>();
+ final Subject subject = (Subject) session.getAttribute("subject");
+ if(subject != null)
+ {
+ final Principal principal = subject.getPrincipals().iterator().next();
+ outputObject.put("user", principal.getName());
+ }
+
+ outputObject.put("mechanisms", (Object) mechanisms);
+
+ final PrintWriter writer = response.getWriter();
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, outputObject);
+
+ }
+
+ private Random getRandom(final HttpSession session)
+ {
+ Random rand = (Random) session.getAttribute(ATTR_RANDOM);
+ if(rand == null)
+ {
+ synchronized (SECURE_RANDOM)
+ {
+ rand = new Random(SECURE_RANDOM.nextLong());
+ }
+ session.setAttribute(ATTR_RANDOM, rand);
+ }
+ return rand;
+ }
+
+
+ @Override
+ protected void onPost(final HttpServletRequest request, final HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ try
+ {
+ response.setContentType("application/json");
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader("Expires", 0);
+
+ HttpSession session = request.getSession();
+
+ String mechanism = request.getParameter("mechanism");
+ String id = request.getParameter("id");
+ String saslResponse = request.getParameter("response");
+
+ AuthenticationManager authManager = ApplicationRegistry.getInstance().getAuthenticationManager(getSocketAddress(request));
+
+ if(mechanism != null)
+ {
+ if(id == null)
+ {
+ SaslServer saslServer = authManager.createSaslServer(mechanism, request.getServerName(), null/*TODO*/);
+ evaluateSaslResponse(response, session, saslResponse, saslServer);
+ }
+ else
+ {
+ response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
+ session.removeAttribute(ATTR_ID);
+ session.removeAttribute(ATTR_SASL_SERVER);
+ session.removeAttribute(ATTR_EXPIRY);
+
+ }
+
+ }
+ else
+ {
+ if(id != null)
+ {
+ 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);
+
+ }
+ else
+ {
+ response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
+ session.removeAttribute(ATTR_ID);
+ session.removeAttribute(ATTR_SASL_SERVER);
+ session.removeAttribute(ATTR_EXPIRY);
+ }
+ }
+ else
+ {
+ response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
+ session.removeAttribute(ATTR_ID);
+ session.removeAttribute(ATTR_SASL_SERVER);
+ session.removeAttribute(ATTR_EXPIRY);
+
+ }
+ }
+ }
+ catch(IOException e)
+ {
+ //TODO
+ e.printStackTrace();
+ throw e;
+ }
+ catch(RuntimeException e)
+ {
+ //TODO
+ e.printStackTrace();
+ throw e;
+ }
+
+ }
+
+ private void evaluateSaslResponse(final HttpServletResponse response,
+ final HttpSession session,
+ final String saslResponse, final SaslServer saslServer) throws IOException
+ {
+ final String id;
+ byte[] challenge;
+ try
+ {
+ challenge = saslServer.evaluateResponse(saslResponse == null ? new byte[0] : Base64.decodeBase64(saslResponse.getBytes()));
+ }
+ catch(SaslException e)
+ {
+
+ session.removeAttribute(ATTR_ID);
+ session.removeAttribute(ATTR_SASL_SERVER);
+ session.removeAttribute(ATTR_EXPIRY);
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+
+ return;
+ }
+
+ if(saslServer.isComplete())
+ {
+ final Subject subject = new Subject();
+ subject.getPrincipals().add(new UsernamePrincipal(saslServer.getAuthorizationID()));
+ session.setAttribute("subject", subject);
+ session.removeAttribute(ATTR_ID);
+ session.removeAttribute(ATTR_SASL_SERVER);
+ session.removeAttribute(ATTR_EXPIRY);
+
+ response.setStatus(HttpServletResponse.SC_OK);
+
+
+ }
+ else
+ {
+ Random rand = getRandom(session);
+ id = String.valueOf(rand.nextLong());
+ session.setAttribute(ATTR_ID, id);
+ session.setAttribute(ATTR_SASL_SERVER, saslServer);
+ session.setAttribute(ATTR_EXPIRY, System.currentTimeMillis() + SASL_EXCHANGE_EXPIRY);
+
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ Map<String, Object> outputObject = new LinkedHashMap<String, Object>();
+ outputObject.put("id", id);
+ outputObject.put("challenge", new String(Base64.encodeBase64(challenge)));
+
+ final PrintWriter writer = response.getWriter();
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, outputObject);
+
+ }
+ }
+}
diff --git a/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java
new file mode 100644
index 0000000000..6295d74b42
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java
@@ -0,0 +1,104 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.io.PrintWriter;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Model;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
+
+public class StructureServlet extends AbstractServlet
+{
+ public StructureServlet()
+ {
+ super();
+ }
+
+ public StructureServlet(Broker broker, SocketAddress socketaddress)
+ {
+ super(broker, socketaddress);
+ }
+
+ @Override
+ protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ response.setHeader("Cache-Control","no-cache");
+ response.setHeader("Pragma","no-cache");
+ response.setDateHeader ("Expires", 0);
+
+ Map<String,Object> structure = generateStructure(getBroker(), Broker.class);
+
+ final PrintWriter writer = response.getWriter();
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, structure);
+
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ }
+
+ private Map<String, Object> generateStructure(ConfiguredObject object, Class<? extends ConfiguredObject> clazz)
+ {
+ Map<String, Object> structure = new LinkedHashMap<String, Object>();
+ structure.put("id", object.getId());
+ structure.put("name", object.getName());
+
+ for(Class<? extends ConfiguredObject> childClass : Model.getChildTypes(clazz))
+ {
+ Collection<? extends ConfiguredObject> children = object.getChildren(childClass);
+ if(children != null)
+ {
+ List<Map<String, Object>> childObjects = new ArrayList<Map<String, Object>>();
+
+ for(ConfiguredObject child : children)
+ {
+ childObjects.add(generateStructure(child, childClass));
+ }
+
+ if(!childObjects.isEmpty())
+ {
+ structure.put(pluralize(childClass),childObjects);
+ }
+ }
+ }
+
+ return structure;
+ }
+
+ private String pluralize(Class<? extends ConfiguredObject> childClass)
+ {
+ String name = childClass.getSimpleName().toLowerCase();
+ return name + (name.endsWith("s") ? "es" : "s");
+ }
+}
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/addBinding.html b/qpid/java/broker-plugins/management/src/main/java/resources/addBinding.html
new file mode 100644
index 0000000000..8dbd219c8d
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/addBinding.html
@@ -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.
+ -->
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Add Binding'" id="addBinding">
+ <form id="formAddBinding" method="post" dojoType="dijit.form.Form">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>Exchange Name*: </strong></td>
+ <td><div id="addBinding.selectExchangeDiv"></div></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Queue Name*: </strong></td>
+ <td><div id="addBinding.selectQueueDiv"></div></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Binding Key*: </strong></td>
+ <td><input type="text" required="true" name="name" id="formAddbinding.bindingKey" placeholder="Binding Key"
+ dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" /></td>
+ </tr>
+ </table>
+ <br/>
+
+ <!-- submit buttons -->
+ <input type="submit" value="Create Binding" label="Create Binding" dojoType="dijit.form.Button" />
+
+ </form>
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/addExchange.html b/qpid/java/broker-plugins/management/src/main/java/resources/addExchange.html
new file mode 100644
index 0000000000..cccdfbd00c
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/addExchange.html
@@ -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.
+ -
+ -->
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Add Exchange'" id="addExchange">
+ <form id="formAddExchange" method="post" dojoType="dijit.form.Form">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>Exchange Name*: </strong></td>
+ <td><input type="text" required="true" name="name" id="formAddExchange.name" placeholder="Exchange Name"
+ dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" /></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Durable? </strong></td>
+ <td><input type="checkbox" name="durable" id="formAddExchange.durable" value="durable" checked="checked" dojoType="dijit.form.CheckBox" /></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Exchange Type: </strong></td>
+ <td>
+ <select name="type" id="formAddExchange.type" dojoType="dijit.form.FilteringSelect">
+ <option value="direct">direct</option>
+ <option value="topic">topic</option>
+ <option value="headers">headers</option>
+ <option value="fanout">fanout</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ <br/>
+
+ <!-- submit buttons -->
+ <input type="submit" value="Create Exchange" label="Create Exchange" dojoType="dijit.form.Button" />
+
+ </form>
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/addQueue.html b/qpid/java/broker-plugins/management/src/main/java/resources/addQueue.html
new file mode 100644
index 0000000000..8154f053cd
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/addQueue.html
@@ -0,0 +1,174 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Add Queue'" id="addQueue">
+ <form id="formAddQueue" method="post" dojoType="dijit.form.Form">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>Queue Name*: </strong></td>
+ <td><input type="text" required="true" name="name" id="formAddQueue.name" placeholder="Queue Name"
+ dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" /></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Durable? </strong></td>
+ <td><input type="checkbox" name="durable" id="formAddQueue.durable" value="durable" checked="checked" dojoType="dijit.form.CheckBox" /></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Queue Type: </strong></td>
+ <td>
+ <input type="radio" id="formAddQueueTypeStandard" name="type" value="standard" checked="checked" dojoType="dijit.form.RadioButton" />
+ <label for="formAddQueueTypeStandard">Standard</label>
+ &nbsp;&nbsp;
+ <input type="radio" id="formAddQueueTypePriority" name="type" value="priority" dojoType="dijit.form.RadioButton" />
+ <label for="formAddQueueTypePriority">Priority</label>
+ &nbsp;&nbsp;
+ <input type="radio" id="formAddQueueTypeLVQ" name="type" value="lvq" dojoType="dijit.form.RadioButton" />
+ <label for="formAddQueueTypeLVQ">LVQ</label>
+ &nbsp;&nbsp;
+ <input type="radio" id="formAddQueueTypeSorted" name="type" value="sorted" dojoType="dijit.form.RadioButton" />
+ <label for="formAddQueueTypeSorted">Sorted</label>
+ </td>
+ </tr>
+ </table>
+ <br/>
+
+ <div id="formAddQueueTypePriority:fields" style="display:none"
+ data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Priority Queue Settings'">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>Priorities: </strong></td>
+ <td><input data-dojo-type="dijit.form.NumberSpinner" id="formAddQueue.priorities"
+ name="numPriorities" value="3" smallDelta="1" constraints="{min:1,max:10,places:0}"/>
+ </tr>
+ </table>
+ </div>
+
+
+ <div id="formAddQueueTypeLVQ:fields" style="display:none"
+ data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Last Value Queue Settings'">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>LVQ Message Property: </strong></td>
+ <td><input type="text" name="lvqKey" id="formAddQueue.lvqkey"
+ placeholder="qpid.LVQ_key" dojoType="dijit.form.ValidationTextBox" /></td>
+ </tr>
+ </table>
+ </div>
+
+ <div id="formAddQueueTypeSorted:fields" style="display:none"
+ data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Sorted Queue Settings'">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>Sort Message Property: </strong></td>
+ <td><input type="text" name="sortKey" id="formAddQueue.sortkey"
+ placeholder="" dojoType="dijit.form.ValidationTextBox" /></td>
+ </tr>
+ </table>
+ </div>
+
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Flow Control Settings', open: false">
+ <table cellpadding="0" cellspacing="2">
+
+ <!-- x-qpid-capacity -->
+ <tr>
+ <td valign="top"><strong>Capacity: </strong></td>
+ <td><input type="text" required="false" name="queueFlowControlSizeBytes" id="formAddQueue.capacity" placeholder="Size in bytes"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="(^[0-9]+(b|K(b)?|M(b)?|G(b)?)?$)"
+ invalidMessage= "Invalid value"/></td>
+ </tr>
+ <!-- x-qpid-flow-resume-capacity -->
+ <tr>
+ <td valign="top"><strong>Resume Capacity: </strong></td>
+ <td><input type="text" required="false" name="queueFlowResumeSizeBytes" id="formAddQueue.flowResumeCapacity" placeholder="Size in bytes"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="(^[0-9]+(b|K(b)?|M(b)?|G(b)?)?$)"
+ invalidMessage= "Invalid value"/></td>
+ </tr>
+ </table>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Alerting Settings', open: false">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>Maximum Message Age: </strong></td>
+ <td><input type="text" required="false" name="alertThresholdMessageAge" id="formAddQueue.maximumMessageAge" placeholder="Time in ms"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="(^[0-9]+(s(ec(ond(s)?)?)?|m(in(ute)?(s)?)?|h|d|w|M|y)?$)"
+ invalidMessage= "Invalid value" /></td>
+ </tr>
+ <!-- x-qpid-maximum-message-size -->
+ <tr>
+ <td valign="top"><strong>Maximum Message Size: </strong></td>
+ <td><input type="text" required="false" name="alertThresholdMessageSize" id="formAddQueue.maximumMessageSize" placeholder="Size in bytes"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="(^[0-9]+(b|K(b)?|M(b)?|G(b)?)?$)"
+ invalidMessage= "Invalid value" /></td>
+ </tr>
+ <!-- x-qpid-maximum-message-count -->
+ <tr>
+ <td valign="top"><strong>Maximum Number in Queue: </strong></td>
+ <td><input type="text" required="false" name="alertThresholdQueueDepthMessages" id="formAddQueue.maximumMessageCount" placeholder="Count of messages"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="[0-9]+"
+ invalidMessage= "Invalid value"/></td>
+ </tr>
+ <!-- x-qpid-minimum-alert-repeat-gap -->
+ <tr>
+ <td valign="top"><strong>Gap between alerts: </strong></td>
+ <td><input type="text" required="false" name="alertRepeatGap" id="formAddQueue.minimumAlertRepeatGap" placeholder="Time in ms"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="(^[0-9]+(s(ec(ond(s)?)?)?|m(in(ute)?(s)?)?|h|d|w|M|y)?$)"
+ invalidMessage= "Invalid value" /></td>
+ </tr>
+ </table>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Other Settings', open: false">
+ <table cellpadding="0" cellspacing="2">
+
+ <!-- x-qpid-maximum-delivery-count -->
+ <tr>
+ <td valign="top"><strong>Maximum Delivery Retries: </strong></td>
+ <td><input type="text" required="false" name="maximumDeliveryAttempts" id="formAddQueue.maximumDeliveryCount"
+ dojoType="dijit.form.ValidationTextBox"
+ trim="true"
+ regexp="[0-9]+"
+ invalidMessage= "Invalid value"/></td>
+ </tr>
+
+
+ </table>
+ </div>
+ <br/>
+ <!-- submit buttons -->
+ <input type="submit" value="Create Queue" label="Create Queue" dojoType="dijit.form.Button" />
+
+ </form>
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/authenticationprovider/addUser.html b/qpid/java/broker-plugins/management/src/main/java/resources/authenticationprovider/addUser.html
new file mode 100644
index 0000000000..785605f694
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/authenticationprovider/addUser.html
@@ -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.
+ -
+ -->
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Add User'" id="addUser">
+ <form id="formAddUser" method="post" dojoType="dijit.form.Form">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>User Name*: </strong></td>
+ <td><input type="text" required="true" name="name" id="formAddUser.name" placeholder="User Name"
+ dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" /></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Password*</strong></td>
+ <td><input type="password" required="true" name="password" id="formAddUser.password" dojoType="dijit.form.ValidationTextBox"/></td>
+ </tr>
+ </table>
+ <br/>
+
+ <!-- submit buttons -->
+ <input type="submit" value="Create User" label="Create User" dojoType="dijit.form.Button" />
+
+ </form>
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/authenticationprovider/setPassword.html b/qpid/java/broker-plugins/management/src/main/java/resources/authenticationprovider/setPassword.html
new file mode 100644
index 0000000000..3d67463abd
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/authenticationprovider/setPassword.html
@@ -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.
+ -
+ -->
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Set Password'" id="setPassword">
+ <form id="formSetPassword" method="post" dojoType="dijit.form.Form">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>User Name: </strong></td>
+ <td><input type="text" required="true" name="name" id="formSetPassword.name" placeholder="User Name"
+ dojoType="dijit.form.TextBox" enabled="false" /></td>
+ </tr>
+ <tr>
+ <td valign="top"><strong>Password*</strong></td>
+ <td><input type="password" required="true" name="password" id="formSetPassword.password" dojoType="dijit.form.ValidationTextBox"/></td>
+ </tr>
+ </table>
+ <br/>
+
+ <!-- submit buttons -->
+ <input type="submit" value="Set Password" label="Set Password" dojoType="dijit.form.Button" />
+
+ </form>
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html b/qpid/java/broker-plugins/management/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html
new file mode 100644
index 0000000000..baadc8c35f
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html
@@ -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.
+ -
+ -->
+<div class="PrincipalDatabaseAuthenticationManager">
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Users'">
+ <div class="users"></div>
+ <button data-dojo-type="dijit.form.Button" class="addUserButton">Add User</button>
+ <button data-dojo-type="dijit.form.Button" class="deleteUserButton">Delete Users</button>
+
+ </div>
+
+</div>
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/css/common.css b/qpid/java/broker-plugins/management/src/main/java/resources/css/common.css
new file mode 100644
index 0000000000..78780edcd9
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/css/common.css
@@ -0,0 +1,92 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+* {
+ outline: none !important;
+}
+
+html, body {
+ height: 100%;
+ margin: 0;
+ margin-right: 40px;
+ padding: 0;
+ overflow: hidden;
+ font-family: Lucida Sans,Lucida Grande,Arial !important;
+ font-size: 13px !important;
+ background: white;
+ color: #333;
+}
+
+#pageLayout {
+ height: 100%;
+}
+button {
+ -webkit-transition: background-color 0.2s linear;
+ border-radius:4px;
+ -moz-border-radius: 4px 4px 4px 4px;
+ -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15);
+ background-color: #E4F2FF;
+ background-image: url("../dojo/dijit/themes/claro/form/images/button.png");
+ background-position: center top;
+ background-repeat: repeat-x;
+ border: 1px solid #769DC0;
+ padding: 2px 8px 4px;
+ font-size:1em;
+}
+
+button:hover {
+ background-color: #AFD9FF;
+ color: #000000;
+}
+
+h1 {
+ font-size:1.5em;
+}
+
+.header {
+ height:100px;
+ background:url("../images/qpid-logo.png") left center no-repeat
+}
+
+.logo {
+ text-align:left;
+ vertical-align: top;
+ font-weight:600;
+ height: 90px;
+ padding-left: 200px;
+ padding-top: 1px;
+ padding-bottom: 10px;
+ font-size:14px;
+ font-family:"Verdana", cursive;
+}
+
+.footer {
+ color:#000000;
+ clear:both;
+ text-align:center;
+ font-size:11px;
+ line-height:17px;
+
+}
+
+div .messages {
+ width: 100%;
+ height: 350px;
+} \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/footer.html b/qpid/java/broker-plugins/management/src/main/java/resources/footer.html
new file mode 100644
index 0000000000..fa84825e80
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/footer.html
@@ -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.
+ -
+ -->
+
+<div class="footer"><p>&#xA9; 2004-<span class="currentYear">2012</span> The Apache Software Foundation.
+ <br/>
+ Apache Qpid, Qpid, Apache, the Apache feather logo, and the Apache Qpid project logo are trademarks of
+ The Apache Software Foundation.
+ <br/>
+ All other marks mentioned may be trademarks or registered trademarks of their respective owners.
+</div> \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/images/qpid-logo.png b/qpid/java/broker-plugins/management/src/main/java/resources/images/qpid-logo.png
new file mode 100644
index 0000000000..95d49ea469
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/images/qpid-logo.png
Binary files differ
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/authorization/sasl.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/authorization/sasl.js
new file mode 100644
index 0000000000..152504da86
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/authorization/sasl.js
@@ -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.
+ *
+ */
+require(["dijit/form/DropDownButton", "dijit/TooltipDialog", "dijit/form/TextBox",
+ "dojo/_base/xhr", "dojox/encoding/base64", "dojox/encoding/digests/_base", "dojox/encoding/digests/MD5"]);
+var button;
+var usernameSpan;
+
+var encodeUTF8 = function encodeUTF8(str) {
+ var byteArray = [];
+ for (var i = 0; i < str.length; i++) {
+ if (str.charCodeAt(i) <= 0x7F) {
+ byteArray.push(str.charCodeAt(i));
+ }
+ else {
+ var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
+ for (var j = 0; j < h.length; j++)
+ byteArray.push(parseInt(h[j], 16));
+ }
+ }
+ return byteArray;
+};
+
+var decodeUTF8 = function decodeUTF8(byteArray)
+{
+ var str = '';
+ for (var i = 0; i < byteArray.length; i++)
+ str += byteArray[i] <= 0x7F?
+ byteArray[i] === 0x25 ? "%25" :
+ String.fromCharCode(byteArray[i]) :
+ "%" + byteArray[i].toString(16).toUpperCase();
+ return decodeURIComponent(str);
+};
+
+
+var saslPlain = function saslPlain(user, password)
+{
+ var responseArray = [ 0 ].concat(encodeUTF8( user )).concat( [ 0 ] ).concat( encodeUTF8( password ) );
+ var plainResponse = dojox.encoding.base64.encode(responseArray);
+
+ // Using dojo.xhrGet, as very little information is being sent
+ dojo.xhrPost({
+ // The URL of the request
+ url: "rest/sasl",
+ content: {
+ mechanism: "PLAIN",
+ response: plainResponse
+ },
+ handleAs: "json",
+ failOk: true
+ }).then(function()
+ {
+ updateAuthentication();
+ },
+ function(error)
+ {
+ if(error.status == 401)
+ {
+ alert("Authentication Failed");
+ }
+ else
+ {
+ alert(error);
+ }
+ updateAuthentication();
+ });
+};
+
+var saslCramMD5 = function saslCramMD5(user, password)
+{
+
+ // Using dojo.xhrGet, as very little information is being sent
+ dojo.xhrPost({
+ // The URL of the request
+ url: "rest/sasl",
+ content: {
+ mechanism: "CRAM-MD5"
+ },
+ handleAs: "json",
+ failOk: true
+ }).then(function(data)
+ {
+
+ var challengeBytes = dojox.encoding.base64.decode(data.challenge);
+ var wa=[];
+ var bitLength = challengeBytes.length*8;
+ for(var i=0; i<bitLength; i+=8)
+ {
+ wa[i>>5] |= (challengeBytes[i/8] & 0xFF)<<(i%32);
+ }
+ var challengeStr = dojox.encoding.digests.wordToString(wa).substring(0,challengeBytes.length);
+
+ var digest = user + " " + dojox.encoding.digests.MD5._hmac(challengeStr, password, dojox.encoding.digests.outputTypes.Hex);
+ var id = data.id;
+
+ var response = dojox.encoding.base64.encode(encodeUTF8( digest ));
+
+ dojo.xhrPost({
+ // The URL of the request
+ url: "rest/sasl",
+ content: {
+ id: id,
+ response: response
+ },
+ handleAs: "json",
+ failOk: true
+ }).then(function()
+ {
+ updateAuthentication();
+ },
+ function(error)
+ {
+ if(error.status == 401)
+ {
+ alert("Authentication Failed");
+ }
+ else
+ {
+ alert(error);
+ }
+ updateAuthentication();
+ });
+
+ },
+ function(error)
+ {
+ if(error.status == 401)
+ {
+ alert("Authentication Failed");
+ }
+ else
+ {
+ alert(error);
+ }
+ });
+};
+
+var doAuthenticate = function doAuthenticate()
+{
+ saslCramMD5(dojo.byId("username").value, dojo.byId("pass").value);
+ updateAuthentication();
+};
+
+
+var updateAuthentication = function updateAuthentication()
+{
+ dojo.xhrGet({
+ // The URL of the request
+ url: "rest/sasl",
+ handleAs: "json"
+ }).then(function(data)
+ {
+ if(data.user)
+ {
+ dojo.byId("authenticatedUser").innerHTML = data.user;
+ dojo.style(button.domNode, {visibility: 'hidden'});
+ dojo.style(usernameSpan, {visibility: 'visible'});
+ }
+ else
+ {
+ dojo.style(button.domNode, {visibility: 'visible'});
+ dojo.style(usernameSpan, {visibility: 'hidden'});
+ }
+ }
+ );
+};
+
+require(["dijit/form/DropDownButton", "dijit/TooltipDialog", "dijit/form/TextBox", "dojo/_base/xhr", "dojo/dom", "dojo/dom-construct", "dojo/domReady!"],
+ function(DropDownButton, TooltipDialog, TextBox, xhr, dom, domConstruct){
+ var dialog = new TooltipDialog({
+ content:
+ '<strong><label for="username" style="display:inline-block;width:100px;">Username:</label></strong>' +
+ '<div data-dojo-type="dijit.form.TextBox" id="username"></div><br/>' +
+ '<strong><label for="pass" style="display:inline-block;width:100px;">Password:</label></strong>' +
+ '<div data-dojo-type="dijit.form.TextBox" type="password" id="pass"></div><br/>' +
+ '<button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:doAuthenticate" type="submit">Login</button>'
+ });
+
+ button = new DropDownButton({
+ label: "Login",
+ dropDown: dialog
+ });
+
+ usernameSpan = domConstruct.create("span", { innerHTML: '<strong>User: </strong><span id="authenticatedUser"></span>',
+ style: { visibility: "hidden" }});
+
+
+ var loginDiv = dom.byId("login");
+ loginDiv.appendChild(button.domNode);
+ loginDiv.appendChild(usernameSpan);
+
+
+
+
+ updateAuthentication();
+}); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/UpdatableStore.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/UpdatableStore.js
new file mode 100644
index 0000000000..f7ede1a7f7
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/UpdatableStore.js
@@ -0,0 +1,110 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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/store/Memory",
+ "dojox/grid/DataGrid",
+ "dojo/data/ObjectStore",
+ "dojo/store/Observable"], function (Memory, DataGrid, ObjectStore, Observable) {
+
+ function UpdatableStore( data, divName, structure, func, props, Grid ) {
+
+ var that = this;
+ var GridType = DataGrid;
+
+ that.store = Observable(Memory({data: data, idProperty: "id"}));
+ that.dataStore = ObjectStore({objectStore: that.store});
+
+ var gridProperties = { store: that.dataStore,
+ structure: structure,
+ autoHeight: true
+ };
+ if(props) {
+ for(var prop in props) {
+ if(props.hasOwnProperty(prop))
+ {
+ gridProperties[ prop ] = props[ prop ];
+ }
+ }
+ }
+
+ if(Grid)
+ {
+ GridType = Grid;
+ }
+
+ that.grid = new GridType(gridProperties, divName);
+
+ // since we created this grid programmatically, call startup to render it
+ that.grid.startup();
+
+ if( func )
+ {
+ func(that);
+ }
+
+ }
+
+ UpdatableStore.prototype.update = function(data)
+ {
+
+ var store = this.store;
+ var theItem;
+
+ // handle deletes
+ // iterate over existing store... if not in new data then remove
+ store.query({ }).forEach(function(object) {
+ if(data) {
+ for(var i=0; i < data.length; i++) {
+ if(data[i].id == object.id) {
+ return;
+ }
+ }
+ }
+ store.remove(object.id);
+
+ });
+
+ // iterate over data...
+ if(data) {
+ for(var i=0; i < data.length; i++) {
+ if(theItem = store.get(data[i].id)) {
+ var modified;
+ for(var propName in data[i]) {
+ if(data[i].hasOwnProperty(propName)) {
+ if(theItem[ propName ] != data[i][ propName ]) {
+ theItem[ propName ] = data[i][ propName ];
+ modified = true;
+ }
+ }
+ }
+ if(modified) {
+ // ... check attributes for updates
+ store.notify(theItem, data[i].id);
+ }
+ } else {
+ // ,,, if not in the store then add
+ store.put(data[i]);
+ }
+ }
+ }
+
+ };
+ return UpdatableStore;
+});
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/footer.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/footer.js
new file mode 100644
index 0000000000..ea13b1fc53
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/footer.js
@@ -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.
+ *
+ */
+define(["dojo/_base/xhr", "dojo/query", "dojo/domReady!"], function (xhr, query) {
+ query('div[qpid-type="footer"]').forEach(function(node, index, arr) {
+ xhr.get({url: "footer.html",
+ sync: true,
+ load: function(data) {
+ node.innerHTML = data;
+ } });
+ });
+});
+
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/formatter.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/formatter.js
new file mode 100644
index 0000000000..2f8683ee1c
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/formatter.js
@@ -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.
+ *
+ */
+
+define(function () {
+ return {
+
+ formatBytes: function formatBytes(amount)
+ {
+ var returnVal = { units: "B",
+ value: "0"};
+
+
+ if(amount < 1000)
+ {
+ returnVal.value = amount.toPrecision(3);;
+ }
+ else if(amount < 1000 * 1024)
+ {
+ returnVal.units = "KB";
+ returnVal.value = (amount / 1024).toPrecision(3);
+ }
+ else if(amount < 1000 * 1024 * 1024)
+ {
+ returnVal.units = "MB";
+ returnVal.value = (amount / (1024 * 1024)).toPrecision(3);
+ }
+ else if(amount < 1000 * 1024 * 1024 * 1024)
+ {
+ returnVal.units = "GB";
+ returnVal.value = (amount / (1024 * 1024 * 1024)).toPrecision(3);
+ }
+
+ return returnVal;
+
+ },
+
+ formatTime: function formatTime(amount)
+ {
+ var returnVal = { units: "ms",
+ value: "0"};
+
+ if(amount < 1000)
+ {
+ returnVal.units = "ms";
+ returnVal.value = amount.toString();
+ }
+ else if(amount < 1000 * 60)
+ {
+ returnVal.units = "s";
+ returnVal.value = (amount / 1000).toPrecision(3);
+ }
+ else if(amount < 1000 * 60 * 60)
+ {
+ returnVal.units = "min";
+ returnVal.value = (amount / (1000 * 60)).toPrecision(3);
+ }
+ else if(amount < 1000 * 60 * 60 * 24)
+ {
+ returnVal.units = "hr";
+ returnVal.value = (amount / (1000 * 60 * 60)).toPrecision(3);
+ }
+ else if(amount < 1000 * 60 * 60 * 24 * 7)
+ {
+ returnVal.units = "d";
+ returnVal.value = (amount / (1000 * 60 * 60 * 24)).toPrecision(3);
+ }
+ else if(amount < 1000 * 60 * 60 * 24 * 365)
+ {
+ returnVal.units = "wk";
+ returnVal.value = (amount / (1000 * 60 * 60 * 24 * 7)).toPrecision(3);
+ }
+ else
+ {
+ returnVal.units = "yr";
+ returnVal.value = (amount / (1000 * 60 * 60 * 24 * 365)).toPrecision(3);
+ }
+
+ return returnVal;
+ }
+ };
+}); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/properties.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/properties.js
new file mode 100644
index 0000000000..8d85345b74
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/properties.js
@@ -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.
+ *
+ */
+define(["dojo/has", "dojo/_base/sniff", "dojo/domReady!"],
+ function (has) {
+ var properties = {};
+ properties.useSyncGet = (has("ie") <= 8);
+ return properties;
+ }); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/updater.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/updater.js
new file mode 100644
index 0000000000..86bbaa46ba
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/updater.js
@@ -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.
+ *
+ */
+define(function () {
+ var updateList = new Array();
+
+ setInterval(function() {
+ for(var i = 0; i < updateList.length; i++) {
+ var obj = updateList[i];
+ obj.update();
+ }
+ }, 5000); // TODO: Should make this configurable
+
+ return {
+ add: function(obj) {
+ updateList.push(obj);
+ },
+
+ remove: function(obj) {
+ for(var i = 0; i < updateList.length; i++) {
+ if(updateList[i] === obj) {
+ updateList.splice(i,1);
+ return;
+ }
+ }
+ }
+ };
+}); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/util.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/util.js
new file mode 100644
index 0000000000..d7917b640e
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/common/util.js
@@ -0,0 +1,56 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+define([],
+ function () {
+ var util = {};
+ if (Array.isArray) {
+ util.isArray = function (object) {
+ return Array.isArray(object);
+ };
+ } else {
+ util.isArray = function (object) {
+ return object instanceof Array;
+ };
+ }
+
+ util.flattenStatistics = function (data) {
+ var attrName, stats, propName, theList;
+ for(attrName in data) {
+ if(data.hasOwnProperty(attrName)) {
+ if(attrName == "statistics") {
+ stats = data.statistics;
+ for(propName in stats) {
+ if(stats.hasOwnProperty( propName )) {
+ data[ propName ] = stats[ propName ];
+ }
+ }
+ } else if(data[ attrName ] instanceof Array) {
+ theList = data[ attrName ];
+
+ for(var i=0; i < theList.length; i++) {
+ util.flattenStatistics( theList[i] );
+ }
+ }
+ }
+ }
+ };
+ return util;
+ }); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/AuthenticationProvider.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/AuthenticationProvider.js
new file mode 100644
index 0000000000..7613fd5d71
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/AuthenticationProvider.js
@@ -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.
+ *
+ */
+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 AuthenticationProvider(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "authenticationprovider", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+ AuthenticationProvider.prototype.getTitle = function() {
+ return "AuthenticationProvider";
+ };
+
+ AuthenticationProvider.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showAuthProvider.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.authProviderAdapter = new AuthProviderUpdater(contentPane.containerNode, that.modelObj, that.controller);
+
+ updater.add( that.authProviderAdapter );
+
+ that.authProviderAdapter.update();
+
+ }});
+ };
+
+ AuthenticationProvider.prototype.close = function() {
+ updater.remove( this.authProviderAdapter );
+ };
+
+ function AuthProviderUpdater(node, authProviderObj, controller)
+ {
+ this.controller = controller;
+ this.name = query(".name", node)[0];
+ /*this.state = dom.byId("state");
+ this.durable = dom.byId("durable");
+ this.lifetimePolicy = dom.byId("lifetimePolicy");
+ */
+ this.query = "rest/authenticationprovider/"+encodeURIComponent(authProviderObj.name);
+
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data)
+ {
+ that.authProviderData = data[0];
+
+ util.flattenStatistics( that.authProviderData );
+
+ that.updateHeader();
+
+ require(["qpid/management/authenticationprovider/"+that.authProviderData.type],
+ function(SpecificProvider) {
+ that.details = new SpecificProvider(node, authProviderObj, controller);
+ that.details.update();
+ });
+
+ });
+
+ }
+
+ AuthProviderUpdater.prototype.updateHeader = function()
+ {
+ this.name.innerHTML = this.authProviderData[ "name" ];
+ /* this.state.innerHTML = this.brokerData[ "state" ];
+ this.durable.innerHTML = this.brokerData[ "durable" ];
+ this.lifetimePolicy.innerHTML = this.brokerData[ "lifetimePolicy" ];
+*/
+ };
+
+ AuthProviderUpdater.prototype.update = function()
+ {
+
+ var that = this;
+
+
+ };
+
+
+
+ return AuthenticationProvider;
+ });
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Broker.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Broker.js
new file mode 100644
index 0000000000..dcf6711073
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Broker.js
@@ -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.
+ *
+ */
+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 Broker(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "broker", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+ Broker.prototype.getTitle = function()
+ {
+ return "Broker";
+ };
+
+ Broker.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showBroker.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.brokerUpdater = new BrokerUpdater(contentPane.containerNode, that.modelObj, that.controller);
+
+ updater.add( that.brokerUpdater );
+
+ that.brokerUpdater.update();
+
+ }});
+ };
+
+ Broker.prototype.close = function() {
+ updater.remove( this.brokerUpdater );
+ };
+
+ function BrokerUpdater(node, brokerObj, controller)
+ {
+ this.controller = controller;
+ this.name = query(".broker-name", node)[0];
+ /*this.state = dom.byId("state");
+ this.durable = dom.byId("durable");
+ this.lifetimePolicy = dom.byId("lifetimePolicy");
+ */
+ this.query = "rest/broker";
+
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data)
+ {
+ that.brokerData= data[0];
+
+ util.flattenStatistics( that.brokerData);
+
+ that.updateHeader();
+ that.vhostsGrid =
+ new UpdatableStore(that.brokerData.vhosts, query(".broker-virtualhosts")[0],
+ [ { name: "Virtual Host", field: "name", width: "120px"},
+ { name: "Connections", field: "connectionCount", width: "80px"},
+ { name: "Queues", field: "queueCount", width: "80px"},
+ { name: "Exchanges", field: "exchangeCount", width: "100%"}
+ ], function(obj) {
+ connect.connect(obj.grid, "onRowDblClick", obj.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var name = obj.dataStore.getValue(theItem,"name");
+ that.controller.show("virtualhost", name, brokerObj);
+ });
+ });
+
+ that.portsGrid =
+ new UpdatableStore(that.brokerData.ports, query(".broker-ports")[0],
+ [ { name: "Address", field: "bindingAddress", width: "70px"},
+ { name: "Port", field: "port", width: "70px"},
+ { name: "Transports", field: "transports", width: "150px"},
+ { name: "Protocols", field: "protocols", width: "100%"}
+ ], function(obj) {
+ connect.connect(obj.grid, "onRowDblClick", obj.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var name = obj.dataStore.getValue(theItem,"name");
+ that.controller.show("port", name, brokerObj);
+ });
+ });
+
+ });
+
+ xhr.get({url: "rest/logrecords", sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data)
+ {
+ that.logData = data;
+
+ var gridProperties = {
+ height: 400,
+ plugins: {
+ pagination: {
+ pageSizes: ["10", "25", "50", "100"],
+ description: true,
+ sizeSwitch: true,
+ pageStepper: true,
+ gotoButton: true,
+ maxPageStep: 4,
+ position: "bottom"
+ }
+ }};
+
+
+ that.logfileGrid =
+ new UpdatableStore(that.logData, query(".broker-logfile")[0],
+ [ { name: "Timestamp", field: "timestamp", width: "200px",
+ formatter: function(val) {
+ var d = new Date(0);
+ d.setUTCSeconds(val/1000);
+
+ return d.toLocaleString();
+ }},
+ { name: "Level", field: "level", width: "60px"},
+ { name: "Logger", field: "logger", width: "280px"},
+ { name: "Thread", field: "thread", width: "120px"},
+ { name: "Log Message", field: "message", width: "100%"}
+
+ ], null, gridProperties, EnhancedGrid);
+ });
+ }
+
+ BrokerUpdater.prototype.updateHeader = function()
+ {
+ this.name.innerHTML = this.brokerData[ "name" ];
+ /* this.state.innerHTML = this.brokerData[ "state" ];
+ this.durable.innerHTML = this.brokerData[ "durable" ];
+ this.lifetimePolicy.innerHTML = this.brokerData[ "lifetimePolicy" ];
+*/
+ };
+
+ BrokerUpdater.prototype.update = function()
+ {
+
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ that.brokerData = data[0];
+ util.flattenStatistics( that.brokerData );
+
+ that.updateHeader();
+
+ that.vhostsGrid.update(that.brokerData.virtualhosts);
+
+ that.portsGrid.update(that.brokerData.ports);
+
+
+ });
+
+
+ xhr.get({url: "rest/logrecords", sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data)
+ {
+ that.logData = data;
+ that.logfileGrid.update(that.logData);
+ });
+
+ };
+
+
+
+ return Broker;
+ });
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Connection.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Connection.js
new file mode 100644
index 0000000000..01f9a325c5
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Connection.js
@@ -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.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojo/parser",
+ "dojo/query",
+ "dojo/_base/connect",
+ "qpid/common/properties",
+ "qpid/common/updater",
+ "qpid/common/util",
+ "qpid/common/formatter",
+ "qpid/common/UpdatableStore",
+ "dojo/domReady!"],
+ function (xhr, parser, query, connect, properties, updater, util, formatter, UpdatableStore) {
+
+ function Connection(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "exchange", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+ Connection.prototype.getTitle = function()
+ {
+ return "Connection: " + this.name;
+ };
+
+ Connection.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showConnection.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.connectionUpdater = new ConnectionUpdater(contentPane.containerNode, that.modelObj, that.controller);
+
+ updater.add( that.connectionUpdater );
+
+ that.connectionUpdater.update();
+
+ }});
+ };
+
+ Connection.prototype.close = function() {
+ updater.remove( this.connectionUpdater );
+ };
+
+ function ConnectionUpdater(containerNode, connectionObj, 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",
+ "msgInRate",
+ "bytesInRate",
+ "bytesInRateUnits",
+ "msgOutRate",
+ "bytesOutRate",
+ "bytesOutRateUnits"]);
+
+
+
+ this.query = "rest/connection/"+ encodeURIComponent(connectionObj.parent.virtualhost.name) + "/" + encodeURIComponent(connectionObj.name);
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ that.connectionData = data[0];
+
+ util.flattenStatistics( that.connectionData );
+
+ that.updateHeader();
+ that.sessionsGrid = new UpdatableStore(that.connectionData.sessions, findNode("sessions"),
+ [ { name: "Name", field: "name", width: "70px"},
+ { name: "Mode", field: "distributionMode", width: "70px"},
+ { name: "Msgs Rate", field: "msgRate",
+ width: "150px"},
+ { name: "Bytes Rate", field: "bytesRate",
+ width: "100%"}
+ ]);
+
+
+ });
+
+ }
+
+ ConnectionUpdater.prototype.updateHeader = function()
+ {
+ this.name.innerHTML = this.connectionData[ "name" ];
+ this.state.innerHTML = this.connectionData[ "state" ];
+ this.durable.innerHTML = this.connectionData[ "durable" ];
+ this.lifetimePolicy.innerHTML = this.connectionData[ "lifetimePolicy" ];
+
+ };
+
+ ConnectionUpdater.prototype.update = function()
+ {
+
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ that.connectionData = data[0];
+
+ util.flattenStatistics( that.connectionData );
+
+ var sessions = that.connectionData[ "sessions" ];
+
+ that.updateHeader();
+
+ var sampleTime = new Date();
+ var messageIn = that.connectionData["messagesIn"];
+ var bytesIn = that.connectionData["bytesIn"];
+ var messageOut = that.connectionData["messagesOut"];
+ var bytesOut = that.connectionData["bytesOut"];
+
+ if(that.sampleTime)
+ {
+ var samplePeriod = sampleTime.getTime() - that.sampleTime.getTime();
+
+ var msgInRate = (1000 * (messageIn - that.messageIn)) / samplePeriod;
+ var msgOutRate = (1000 * (messageOut - that.messageOut)) / samplePeriod;
+ var bytesInRate = (1000 * (bytesIn - that.bytesIn)) / samplePeriod;
+ var bytesOutRate = (1000 * (bytesOut - that.bytesOut)) / samplePeriod;
+
+ that.msgInRate.innerHTML = msgInRate.toFixed(0);
+ var bytesInFormat = formatter.formatBytes( bytesInRate );
+ that.bytesInRate.innerHTML = "(" + bytesInFormat.value;
+ that.bytesInRateUnits.innerHTML = bytesInFormat.units + "/s)";
+
+ that.msgOutRate.innerHTML = msgOutRate.toFixed(0);
+ var bytesOutFormat = formatter.formatBytes( bytesOutRate );
+ that.bytesOutRate.innerHTML = "(" + bytesOutFormat.value;
+ that.bytesOutRateUnits.innerHTML = bytesOutFormat.units + "/s)";
+
+ if(sessions && that.sessions)
+ {
+ for(var i=0; i < sessions.length; i++)
+ {
+ var session = sessions[i];
+ for(var j = 0; j < that.sessions.length; j++)
+ {
+ var oldSession = that.sessions[j];
+ if(oldSession.id == session.id)
+ {
+ var msgRate = (1000 * (session.messagesOut - oldSession.messagesOut)) /
+ samplePeriod;
+ session.msgRate = msgRate.toFixed(0) + "msg/s";
+
+ var bytesRate = (1000 * (session.bytesOut - oldSession.bytesOut)) /
+ samplePeriod;
+ var bytesRateFormat = formatter.formatBytes( bytesRate );
+ session.bytesRate = bytesRateFormat.value + bytesRateFormat.units + "/s";
+ }
+
+
+ }
+
+ }
+ }
+
+ }
+
+ that.sampleTime = sampleTime;
+ that.messageIn = messageIn;
+ that.bytesIn = bytesIn;
+ that.messageOut = messageOut;
+ that.bytesOut = bytesOut;
+ that.sessions = sessions;
+
+
+ // update sessions
+ that.sessionsGrid.update(that.connectionData.sessions)
+ });
+ };
+
+
+ return Connection;
+ }); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Exchange.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Exchange.js
new file mode 100644
index 0000000000..0450ef53ac
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Exchange.js
@@ -0,0 +1,229 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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",
+ "dijit/registry",
+ "qpid/common/properties",
+ "qpid/common/updater",
+ "qpid/common/util",
+ "qpid/common/formatter",
+ "qpid/common/UpdatableStore",
+ "qpid/management/addBinding",
+ "dojo/domReady!"],
+ function (xhr, parser, query, connect, registry, properties, updater, util, formatter, UpdatableStore, addBinding) {
+
+ function Exchange(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "exchange", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+
+ Exchange.prototype.getExchangeName = function()
+ {
+ return this.name;
+ };
+
+
+ Exchange.prototype.getVirtualHostName = function()
+ {
+ return this.modelObj.parent.virtualhost.name;
+ };
+
+ Exchange.prototype.getTitle = function()
+ {
+ return "Exchange: " + this.name;
+ };
+
+ Exchange.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showExchange.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.exchangeUpdater = new ExchangeUpdater(contentPane.containerNode, that.modelObj, that.controller);
+
+ updater.add( that.exchangeUpdater );
+
+ that.exchangeUpdater.update();
+
+
+ var addBindingButton = query(".addBindingButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(addBindingButton), "onClick",
+ function(evt){
+ addBinding.show({ virtualhost: that.getVirtualHostName(),
+ exchange: that.getExchangeName()});
+ });
+
+ }});
+ };
+
+ Exchange.prototype.close = function() {
+ updater.remove( this.exchangeUpdater );
+ };
+
+ function ExchangeUpdater(containerNode, exchangeObj, 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",
+ "alertRepeatGap",
+ "alertRepeatGapUnits",
+ "alertThresholdMessageAge",
+ "alertThresholdMessageAgeUnits",
+ "alertThresholdMessageSize",
+ "alertThresholdMessageSizeUnits",
+ "alertThresholdQueueDepthBytes",
+ "alertThresholdQueueDepthBytesUnits",
+ "alertThresholdQueueDepthMessages",
+ "msgInRate",
+ "bytesInRate",
+ "bytesInRateUnits",
+ "msgDropRate",
+ "bytesDropRate",
+ "bytesDropRateUnits"]);
+
+
+
+ this.query = "rest/exchange/"+ encodeURIComponent(exchangeObj.parent.virtualhost.name) + "/" + encodeURIComponent(exchangeObj.name);
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ that.exchangeData = data[0];
+ util.flattenStatistics( that.exchangeData );
+
+ that.updateHeader();
+ that.bindingsGrid = new UpdatableStore(that.exchangeData.bindings, findNode("bindings"),
+ [ { name: "Queue", field: "queue", width: "90px"},
+ { name: "Binding Key", field: "name", width: "120px"},
+ { name: "Arguments", field: "argumentString", width: "100%"}
+ ]);
+
+ });
+
+ }
+
+ ExchangeUpdater.prototype.updateHeader = function()
+ {
+ this.name.innerHTML = this.exchangeData[ "name" ];
+ this.state.innerHTML = this.exchangeData[ "state" ];
+ this.durable.innerHTML = this.exchangeData[ "durable" ];
+ this.lifetimePolicy.innerHTML = this.exchangeData[ "lifetimePolicy" ];
+
+ };
+
+ ExchangeUpdater.prototype.update = function()
+ {
+
+ var thisObj = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ thisObj.exchangeData = data[0];
+
+ util.flattenStatistics( thisObj.exchangeData );
+
+ var bindings = thisObj.exchangeData[ "bindings" ];
+
+ if(bindings)
+ {
+ for(var i=0; i < bindings.length; i++)
+ {
+ if(bindings[i].arguments)
+ {
+ bindings[i].argumentString = dojo.toJson(bindings[i].arguments);
+ }
+ else
+ {
+ bindings[i].argumentString = "";
+ }
+ }
+ }
+
+
+ var sampleTime = new Date();
+
+ thisObj.updateHeader();
+
+ var messageIn = thisObj.exchangeData["messagesIn"];
+ var bytesIn = thisObj.exchangeData["bytesIn"];
+ var messageDrop = thisObj.exchangeData["messagesDropped"];
+ var bytesDrop = thisObj.exchangeData["bytesDropped"];
+
+ if(thisObj.sampleTime)
+ {
+ var samplePeriod = sampleTime.getTime() - thisObj.sampleTime.getTime();
+
+ var msgInRate = (1000 * (messageIn - thisObj.messageIn)) / samplePeriod;
+ var msgDropRate = (1000 * (messageDrop - thisObj.messageDrop)) / samplePeriod;
+ var bytesInRate = (1000 * (bytesIn - thisObj.bytesIn)) / samplePeriod;
+ var bytesDropRate = (1000 * (bytesDrop - thisObj.bytesDrop)) / samplePeriod;
+
+ thisObj.msgInRate.innerHTML = msgInRate.toFixed(0);
+ var bytesInFormat = formatter.formatBytes( bytesInRate );
+ thisObj.bytesInRate.innerHTML = "(" + bytesInFormat.value;
+ thisObj.bytesInRateUnits.innerHTML = bytesInFormat.units + "/s)";
+
+ thisObj.msgDropRate.innerHTML = msgDropRate.toFixed(0);
+ var bytesDropFormat = formatter.formatBytes( bytesDropRate );
+ thisObj.bytesDropRate.innerHTML = "(" + bytesDropFormat.value;
+ thisObj.bytesDropRateUnits.innerHTML = bytesDropFormat.units + "/s)"
+
+ }
+
+ thisObj.sampleTime = sampleTime;
+ thisObj.messageIn = messageIn;
+ thisObj.bytesIn = bytesIn;
+ thisObj.messageDrop = messageDrop;
+ thisObj.bytesDrop = bytesDrop;
+
+ // update bindings
+ thisObj.bindingsGrid.update(thisObj.exchangeData.bindings)
+
+ });
+ };
+
+
+ return Exchange;
+ });
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Queue.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Queue.js
new file mode 100644
index 0000000000..1eb0bfdd79
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Queue.js
@@ -0,0 +1,438 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+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",
+ "qpid/management/addBinding",
+ "qpid/management/moveCopyMessages",
+ "qpid/management/showMessage",
+ "dojo/store/JsonRest",
+ "dojox/grid/EnhancedGrid",
+ "dojo/data/ObjectStore",
+ "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, addBinding, moveMessages, showMessage, JsonRest, EnhancedGrid, ObjectStore) {
+
+ function Queue(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "queue", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+ Queue.prototype.getQueueName = function()
+ {
+ return this.name;
+ };
+
+
+ Queue.prototype.getVirtualHostName = function()
+ {
+ return this.modelObj.parent.virtualhost.name;
+ };
+
+ Queue.prototype.getTitle = function()
+ {
+ return "Queue: " + this.name;
+ };
+
+ Queue.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showQueue.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.queueUpdater = new QueueUpdater(contentPane.containerNode, that, that.controller);
+
+ updater.add( that.queueUpdater );
+
+ that.queueUpdater.update();
+
+ var myStore = new JsonRest({target:"rest/message/"+ encodeURIComponent(that.getVirtualHostName()) +
+ "/" + encodeURIComponent(that.getQueueName())});
+ var messageGridDiv = query(".messages",contentPane.containerNode)[0];
+ that.dataStore = new ObjectStore({objectStore: myStore});
+ that.grid = new EnhancedGrid({
+ store: that.dataStore,
+ autoHeight: 10,
+ keepSelection: true,
+ structure: [
+ {name:"Size", field:"size", width: "60px"},
+ {name:"State", field:"state", width: "120px"},
+
+ {name:"Arrival", field:"arrivalTime", width: "100%",
+ formatter: function(val) {
+ var d = new Date(0);
+ d.setUTCSeconds(val/1000);
+
+ return d.toLocaleString();
+ } }
+ ],
+ plugins: {
+ pagination: {
+ pageSizes: ["10", "25", "50", "100"],
+ description: true,
+ sizeSwitch: true,
+ pageStepper: true,
+ gotoButton: true,
+ maxPageStep: 4,
+ position: "bottom"
+ },
+ indirectSelection: true
+ }
+ }, messageGridDiv);
+
+ connect.connect(that.grid, "onRowDblClick", that.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var id = that.dataStore.getValue(theItem,"id");
+ showMessage.show({ messageNumber: id,
+ queue: that.getQueueName(),
+ virtualhost: that.getVirtualHostName() });
+ });
+
+ var deleteMessagesButton = query(".deleteMessagesButton", contentPane.containerNode)[0];
+ var deleteWidget = registry.byNode(deleteMessagesButton);
+ connect.connect(deleteWidget, "onClick",
+ function(evt){
+ event.stop(evt);
+ that.deleteMessages();
+ });
+ var moveMessagesButton = query(".moveMessagesButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(moveMessagesButton), "onClick",
+ function(evt){
+ event.stop(evt);
+ that.moveOrCopyMessages({move: true});
+ });
+
+
+ var copyMessagesButton = query(".copyMessagesButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(copyMessagesButton), "onClick",
+ function(evt){
+ event.stop(evt);
+ that.moveOrCopyMessages({move: false});
+ });
+
+ var addBindingButton = query(".addBindingButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(addBindingButton), "onClick",
+ function(evt){
+ event.stop(evt);
+ addBinding.show({ virtualhost: that.getVirtualHostName(),
+ queue: that.getQueueName()});
+ });
+
+ }});
+
+
+
+ };
+
+ Queue.prototype.deleteMessages = function() {
+ var data = this.grid.selection.getSelected();
+ if(data.length) {
+ var that = this;
+ if(confirm("Delete " + data.length + " messages?")) {
+ var i, queryParam;
+ for(i = 0; i<data.length; i++) {
+ if(queryParam) {
+ queryParam += "&";
+ } else {
+ queryParam = "?";
+ }
+
+ queryParam += "id=" + data[i].id;
+ }
+ var query = "rest/message/"+ encodeURIComponent(that.getVirtualHostName())
+ + "/" + encodeURIComponent(that.getQueueName()) + queryParam;
+ that.success = true
+ xhr.del({url: query, sync: true, handleAs: "json"}).then(
+ function(data) {
+ that.grid.setQuery({id: "*"});
+ that.grid.selection.deselectAll();
+ that.queueUpdater.update();
+ },
+ function(error) {that.success = false; that.failureReason = error;});
+ if(!that.success ) {
+ alert("Error:" + this.failureReason);
+ }
+ }
+ }
+ };
+
+ Queue.prototype.moveOrCopyMessages = function(obj) {
+ var that = this;
+ var move = obj.move;
+ var data = this.grid.selection.getSelected();
+ if(data.length) {
+ var that = this;
+ var i, putData = { messages:[] };
+ if(move) {
+ putData.move = true;
+ }
+ for(i = 0; i<data.length; i++) {
+ putData.messages.push(data[i].id);
+ }
+ moveMessages.show({ virtualhost: this.getVirtualHostName(),
+ queue: this.getQueueName(),
+ data: putData}, function() {
+ if(move)
+ {
+ that.grid.setQuery({id: "*"});
+ that.grid.selection.deselectAll();
+ }
+ });
+
+ }
+
+
+
+ };
+
+ Queue.prototype.startup = function() {
+ this.grid.startup();
+ };
+
+ Queue.prototype.close = function() {
+ updater.remove( this.queueUpdater );
+ };
+
+ function QueueUpdater(containerNode, queueObj, 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",
+ "alertRepeatGap",
+ "alertRepeatGapUnits",
+ "alertThresholdMessageAge",
+ "alertThresholdMessageAgeUnits",
+ "alertThresholdMessageSize",
+ "alertThresholdMessageSizeUnits",
+ "alertThresholdQueueDepthBytes",
+ "alertThresholdQueueDepthBytesUnits",
+ "alertThresholdQueueDepthMessages",
+ "queueDepthMessages",
+ "queueDepthBytes",
+ "queueDepthBytesUnits",
+ "unacknowledgedMessages",
+ "unacknowledgedBytes",
+ "unacknowledgedBytesUnits",
+ "msgInRate",
+ "bytesInRate",
+ "bytesInRateUnits",
+ "msgOutRate",
+ "bytesOutRate",
+ "bytesOutRateUnits"]);
+
+
+
+ this.query = "rest/queue/"+ encodeURIComponent(queueObj.getVirtualHostName()) + "/" + encodeURIComponent(queueObj.getQueueName());
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ that.queueData = data[0];
+
+ util.flattenStatistics( that.queueData );
+
+ that.updateHeader();
+ that.bindingsGrid = new UpdatableStore(that.queueData.bindings, findNode("bindings"),
+ [ { name: "Exchange", field: "exchange", width: "90px"},
+ { name: "Binding Key", field: "name", width: "120px"},
+ { name: "Arguments", field: "argumentString", width: "100%"}
+ ]);
+
+ that.consumersGrid = new UpdatableStore(that.queueData.consumers, findNode("consumers"),
+ [ { name: "Name", field: "name", width: "70px"},
+ { name: "Mode", field: "distributionMode", width: "70px"},
+ { name: "Msgs Rate", field: "msgRate",
+ width: "150px"},
+ { name: "Bytes Rate", field: "bytesRate",
+ width: "100%"}
+ ]);
+
+
+
+
+ });
+
+ }
+
+ QueueUpdater.prototype.updateHeader = function()
+ {
+
+ var bytesDepth;
+ this.name.innerHTML = this.queueData[ "name" ];
+ this.state.innerHTML = this.queueData[ "state" ];
+ this.durable.innerHTML = this.queueData[ "durable" ];
+ this.lifetimePolicy.innerHTML = this.queueData[ "lifetimePolicy" ];
+
+ this.queueDepthMessages.innerHTML = this.queueData["queueDepthMessages"];
+ bytesDepth = formatter.formatBytes( this.queueData["queueDepthBytes"] );
+ this.queueDepthBytes.innerHTML = "(" + bytesDepth.value;
+ this.queueDepthBytesUnits.innerHTML = bytesDepth.units + ")";
+
+ this.unacknowledgedMessages.innerHTML = this.queueData["unacknowledgedMessages"];
+ bytesDepth = formatter.formatBytes( this.queueData["unacknowledgedBytes"] );
+ this.unacknowledgedBytes.innerHTML = "(" + bytesDepth.value;
+ this.unacknowledgedBytesUnits.innerHTML = bytesDepth.units + ")"
+
+
+ };
+
+ QueueUpdater.prototype.update = function()
+ {
+
+ var thisObj = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data) {
+ var i,j;
+ thisObj.queueData = data[0];
+ util.flattenStatistics( thisObj.queueData );
+
+ var bindings = thisObj.queueData[ "bindings" ];
+ var consumers = thisObj.queueData[ "consumers" ];
+
+ for(i=0; i < bindings.length; i++) {
+ bindings[i].argumentString = json.stringify(bindings[i].arguments);
+ }
+
+ thisObj.updateHeader();
+
+
+ // update alerting info
+ var alertRepeatGap = formatter.formatTime( thisObj.queueData["alertRepeatGap"] );
+
+ thisObj.alertRepeatGap.innerHTML = alertRepeatGap.value;
+ thisObj.alertRepeatGapUnits.innerHTML = alertRepeatGap.units;
+
+
+ var alertMsgAge = formatter.formatTime( thisObj.queueData["alertThresholdMessageAge"] );
+
+ thisObj.alertThresholdMessageAge.innerHTML = alertMsgAge.value;
+ thisObj.alertThresholdMessageAgeUnits.innerHTML = alertMsgAge.units;
+
+ var alertMsgSize = formatter.formatBytes( thisObj.queueData["alertThresholdMessageSize"] );
+
+ thisObj.alertThresholdMessageSize.innerHTML = alertMsgSize.value;
+ thisObj.alertThresholdMessageSizeUnits.innerHTML = alertMsgSize.units;
+
+ var alertQueueDepth = formatter.formatBytes( thisObj.queueData["alertThresholdQueueDepthBytes"] );
+
+ thisObj.alertThresholdQueueDepthBytes.innerHTML = alertQueueDepth.value;
+ thisObj.alertThresholdQueueDepthBytesUnits.innerHTML = alertQueueDepth.units;
+
+ thisObj.alertThresholdQueueDepthMessages.innerHTML = thisObj.queueData["alertThresholdQueueDepthMessages"];
+
+ var sampleTime = new Date();
+ var messageIn = thisObj.queueData["totalEnqueuedMessages"];
+ var bytesIn = thisObj.queueData["totalEnqueuedBytes"];
+ var messageOut = thisObj.queueData["totalDequeuedMessages"];
+ var bytesOut = thisObj.queueData["totalDequeuedBytes"];
+
+ if(thisObj.sampleTime) {
+ var samplePeriod = sampleTime.getTime() - thisObj.sampleTime.getTime();
+
+ var msgInRate = (1000 * (messageIn - thisObj.messageIn)) / samplePeriod;
+ var msgOutRate = (1000 * (messageOut - thisObj.messageOut)) / samplePeriod;
+ var bytesInRate = (1000 * (bytesIn - thisObj.bytesIn)) / samplePeriod;
+ var bytesOutRate = (1000 * (bytesOut - thisObj.bytesOut)) / samplePeriod;
+
+ thisObj.msgInRate.innerHTML = msgInRate.toFixed(0);
+ var bytesInFormat = formatter.formatBytes( bytesInRate );
+ thisObj.bytesInRate.innerHTML = "(" + bytesInFormat.value;
+ thisObj.bytesInRateUnits.innerHTML = bytesInFormat.units + "/s)";
+
+ thisObj.msgOutRate.innerHTML = msgOutRate.toFixed(0);
+ var bytesOutFormat = formatter.formatBytes( bytesOutRate );
+ thisObj.bytesOutRate.innerHTML = "(" + bytesOutFormat.value;
+ thisObj.bytesOutRateUnits.innerHTML = bytesOutFormat.units + "/s)";
+
+ if(consumers && thisObj.consumers) {
+ for(i=0; i < consumers.length; i++) {
+ var consumer = consumers[i];
+ for(j = 0; j < thisObj.consumers.length; j++) {
+ var oldConsumer = thisObj.consumers[j];
+ if(oldConsumer.id == consumer.id) {
+ var msgRate = (1000 * (consumer.messagesOut - oldConsumer.messagesOut)) /
+ samplePeriod;
+ consumer.msgRate = msgRate.toFixed(0) + "msg/s";
+
+ var bytesRate = (1000 * (consumer.bytesOut - oldConsumer.bytesOut)) /
+ samplePeriod;
+ var bytesRateFormat = formatter.formatBytes( bytesRate );
+ consumer.bytesRate = bytesRateFormat.value + bytesRateFormat.units + "/s";
+ }
+ }
+ }
+ }
+
+ }
+
+ thisObj.sampleTime = sampleTime;
+ thisObj.messageIn = messageIn;
+ thisObj.bytesIn = bytesIn;
+ thisObj.messageOut = messageOut;
+ thisObj.bytesOut = bytesOut;
+ thisObj.consumers = consumers;
+
+ // update bindings
+ thisObj.bindingsGrid.update(thisObj.queueData.bindings);
+
+ // update consumers
+ thisObj.consumersGrid.update(thisObj.queueData.consumers)
+
+ });
+ };
+
+
+ return Queue;
+ });
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/VirtualHost.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/VirtualHost.js
new file mode 100644
index 0000000000..ce24145930
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/VirtualHost.js
@@ -0,0 +1,327 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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",
+ "dijit/registry",
+ "qpid/common/properties",
+ "qpid/common/updater",
+ "qpid/common/util",
+ "qpid/common/formatter",
+ "qpid/common/UpdatableStore",
+ "qpid/management/addQueue",
+ "qpid/management/addExchange",
+ "dojo/domReady!"],
+ function (xhr, parser, query, connect, registry, properties, updater, util, formatter, UpdatableStore, addQueue, addExchange) {
+
+ function VirtualHost(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "virtualhost", name: name};
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+ VirtualHost.prototype.getTitle = function()
+ {
+ return "VirtualHost: " + this.name;
+ };
+
+ VirtualHost.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showVirtualHost.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.vhostUpdater = new Updater(contentPane.containerNode, that.modelObj, that.controller);
+
+ updater.add( that.vhostUpdater );
+
+ that.vhostUpdater.update();
+
+ var addQueueButton = query(".addQueueButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(addQueueButton), "onClick", function(evt){ addQueue.show(that.name) });
+
+ var addExchangeButton = query(".addExchangeButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(addExchangeButton), "onClick", function(evt){ addExchange.show(that.name) });
+ }});
+
+ };
+
+ VirtualHost.prototype.close = function() {
+ updater.remove( this.vhostUpdater );
+ };
+
+
+ function Updater(node, vhost, controller)
+ {
+
+ var that = this;
+
+ function findNode(name) {
+ return query("." + name, node)[0];
+ }
+
+ function storeNodes(names)
+ {
+ for(var i = 0; i < names.length; i++) {
+ that[names[i]] = findNode(names[i]);
+ }
+ }
+
+ storeNodes(["name",
+ "state",
+ "durable",
+ "lifetimePolicy",
+ "alertRepeatGap",
+ "alertRepeatGapUnits",
+ "alertThresholdMessageAge",
+ "alertThresholdMessageAgeUnits",
+ "alertThresholdMessageSize",
+ "alertThresholdMessageSizeUnits",
+ "alertThresholdQueueDepthBytes",
+ "alertThresholdQueueDepthBytesUnits",
+ "alertThresholdQueueDepthMessages",
+ "msgInRate",
+ "bytesInRate",
+ "bytesInRateUnits",
+ "msgOutRate",
+ "bytesOutRate",
+ "bytesOutRateUnits"]);
+
+ this.query = "rest/virtualhost/"+ encodeURIComponent(vhost.name);
+
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data) {
+ that.vhostData = data[0];
+
+ // flatten statistics into attributes
+ util.flattenStatistics( that.vhostData );
+
+ that.updateHeader();
+ that.queuesGrid = new UpdatableStore(that.vhostData.queues, findNode("queues"),
+ [ { name: "Name", field: "name", width: "90px"},
+ { name: "Messages", field: "queueDepthMessages", width: "90px"},
+ { name: "Arguments", field: "arguments", width: "100%"}
+ ],
+ function(obj)
+ {
+ connect.connect(obj.grid, "onRowDblClick", obj.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var queueName = obj.dataStore.getValue(theItem,"name");
+ controller.show("queue", queueName, vhost);
+ });
+ } );
+
+ that.exchangesGrid = new UpdatableStore(that.vhostData.exchanges, findNode("exchanges"),
+ [ { name: "Name", field: "name", width: "120px"},
+ { name: "Type", field: "type", width: "120px"},
+ { name: "Binding Count", field: "bindingCount",
+ width: "100%"}
+ ],
+ function(obj)
+ {
+ connect.connect(obj.grid, "onRowDblClick", obj.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var exchangeName = obj.dataStore.getValue(theItem,"name");
+ controller.show("exchange", exchangeName, vhost);
+ });
+ } );
+
+
+ that.connectionsGrid = new UpdatableStore(that.vhostData.connections,
+ findNode("connections"),
+ [ { name: "Name", field: "name", width: "150px"},
+ { name: "Sessions", field: "sessionCount", width: "70px"},
+ { name: "Msgs In", field: "msgInRate",
+ width: "80px"},
+ { name: "Bytes In", field: "bytesInRate",
+ width: "80px"},
+ { name: "Msgs Out", field: "msgOutRate",
+ width: "80px"},
+ { name: "Bytes Out", field: "bytesOutRate",
+ width: "100%"}
+ ],
+ function(obj)
+ {
+ connect.connect(obj.grid, "onRowDblClick", obj.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var connectionName = obj.dataStore.getValue(theItem,"name");
+ controller.show("connection", connectionName, vhost);
+ });
+ } );
+
+
+
+ });
+
+ }
+
+ Updater.prototype.updateHeader = function()
+ {
+ this.name.innerHTML = this.vhostData[ "name" ];
+ this.state.innerHTML = this.vhostData[ "state" ];
+ this.durable.innerHTML = this.vhostData[ "durable" ];
+ this.lifetimePolicy.innerHTML = this.vhostData[ "lifetimePolicy" ];
+
+
+ };
+
+ Updater.prototype.update = function()
+ {
+
+ var thisObj = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data) {
+ thisObj.vhostData = data[0];
+ util.flattenStatistics( thisObj.vhostData );
+ var connections = thisObj.vhostData[ "connections" ];
+ var queues = thisObj.vhostData[ "queues" ];
+ var exchanges = thisObj.vhostData[ "exchanges" ];
+
+ thisObj.updateHeader();
+
+
+ // update alerting info
+ var alertRepeatGap = formatter.formatTime( thisObj.vhostData["alertRepeatGap"] );
+
+ thisObj.alertRepeatGap.innerHTML = alertRepeatGap.value;
+ thisObj.alertRepeatGapUnits.innerHTML = alertRepeatGap.units;
+
+
+ var alertMsgAge = formatter.formatTime( thisObj.vhostData["alertThresholdMessageAge"] );
+
+ thisObj.alertThresholdMessageAge.innerHTML = alertMsgAge.value;
+ thisObj.alertThresholdMessageAgeUnits.innerHTML = alertMsgAge.units;
+
+ var alertMsgSize = formatter.formatBytes( thisObj.vhostData["alertThresholdMessageSize"] );
+
+ thisObj.alertThresholdMessageSize.innerHTML = alertMsgSize.value;
+ thisObj.alertThresholdMessageSizeUnits.innerHTML = alertMsgSize.units;
+
+ var alertQueueDepth = formatter.formatBytes( thisObj.vhostData["alertThresholdQueueDepthBytes"] );
+
+ thisObj.alertThresholdQueueDepthBytes.innerHTML = alertQueueDepth.value;
+ thisObj.alertThresholdQueueDepthBytesUnits.innerHTML = alertQueueDepth.units;
+
+ thisObj.alertThresholdQueueDepthMessages.innerHTML = thisObj.vhostData["alertThresholdQueueDepthMessages"];
+
+ var stats = thisObj.vhostData[ "statistics" ];
+
+ var sampleTime = new Date();
+ var messageIn = stats["messagesIn"];
+ var bytesIn = stats["bytesIn"];
+ var messageOut = stats["messagesOut"];
+ var bytesOut = stats["bytesOut"];
+
+ if(thisObj.sampleTime)
+ {
+ var samplePeriod = sampleTime.getTime() - thisObj.sampleTime.getTime();
+
+ var msgInRate = (1000 * (messageIn - thisObj.messageIn)) / samplePeriod;
+ var msgOutRate = (1000 * (messageOut - thisObj.messageOut)) / samplePeriod;
+ var bytesInRate = (1000 * (bytesIn - thisObj.bytesIn)) / samplePeriod;
+ var bytesOutRate = (1000 * (bytesOut - thisObj.bytesOut)) / samplePeriod;
+
+ thisObj.msgInRate.innerHTML = msgInRate.toFixed(0);
+ var bytesInFormat = formatter.formatBytes( bytesInRate );
+ thisObj.bytesInRate.innerHTML = "(" + bytesInFormat.value;
+ thisObj.bytesInRateUnits.innerHTML = bytesInFormat.units + "/s)";
+
+ thisObj.msgOutRate.innerHTML = msgOutRate.toFixed(0);
+ var bytesOutFormat = formatter.formatBytes( bytesOutRate );
+ thisObj.bytesOutRate.innerHTML = "(" + bytesOutFormat.value;
+ thisObj.bytesOutRateUnits.innerHTML = bytesOutFormat.units + "/s)";
+
+ if(connections && thisObj.connections)
+ {
+ for(var i=0; i < connections.length; i++)
+ {
+ var connection = connections[i];
+ for(var j = 0; j < thisObj.connections.length; j++)
+ {
+ var oldConnection = thisObj.connections[j];
+ if(oldConnection.id == connection.id)
+ {
+ msgOutRate = (1000 * (connection.messagesOut - oldConnection.messagesOut)) /
+ samplePeriod;
+ connection.msgOutRate = msgOutRate.toFixed(0) + "msg/s";
+
+ bytesOutRate = (1000 * (connection.bytesOut - oldConnection.bytesOut)) /
+ samplePeriod;
+ var bytesOutRateFormat = formatter.formatBytes( bytesOutRate );
+ connection.bytesOutRate = bytesOutRateFormat.value + bytesOutRateFormat.units + "/s";
+
+
+ msgInRate = (1000 * (connection.messagesIn - oldConnection.messagesIn)) /
+ samplePeriod;
+ connection.msgInRate = msgInRate.toFixed(0) + "msg/s";
+
+ bytesInRate = (1000 * (connection.bytesIn - oldConnection.bytesIn)) /
+ samplePeriod;
+ var bytesInRateFormat = formatter.formatBytes( bytesInRate );
+ connection.bytesInRate = bytesInRateFormat.value + bytesInRateFormat.units + "/s";
+ }
+
+
+ }
+
+ }
+ }
+ }
+
+ thisObj.sampleTime = sampleTime;
+ thisObj.messageIn = messageIn;
+ thisObj.bytesIn = bytesIn;
+ thisObj.messageOut = messageOut;
+ thisObj.bytesOut = bytesOut;
+ thisObj.connections = connections;
+
+ // update queues
+ thisObj.queuesGrid.update(thisObj.vhostData.queues);
+
+ // update exchanges
+ thisObj.exchangesGrid.update(thisObj.vhostData.exchanges);
+
+ // update connections
+ thisObj.connectionsGrid.update(thisObj.vhostData.connections)
+
+
+ });
+ };
+
+
+ return VirtualHost;
+ }); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/addBinding.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/addBinding.js
new file mode 100644
index 0000000000..83e724d0e9
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/addBinding.js
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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',
+ "dojo/store/Memory",
+ "dijit/form/FilteringSelect",
+ "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, Memory, FilteringSelect) {
+
+ var addBinding = {};
+
+ var node = construct.create("div", null, win.body(), "last");
+
+ var convertToBinding = function convertToBinding(formValues)
+ {
+ var newBinding = {};
+
+ newBinding.name = formValues.name;
+ for(var propName in formValues)
+ {
+ if(formValues.hasOwnProperty(propName))
+ {
+ if(propName === "durable")
+ {
+ if (formValues.durable[0] && formValues.durable[0] == "durable") {
+ newBinding.durable = true;
+ }
+ } else {
+ if(formValues[ propName ] !== "") {
+ newBinding[ propName ] = formValues[propName];
+ }
+ }
+
+ }
+ }
+ if(addBinding.queue) {
+ newBinding.queue = addBinding.queue;
+ }
+ if(addBinding.exchange) {
+ newBinding.exchange = addBinding.exchange;
+ }
+ return newBinding;
+ };
+
+
+ xhr.get({url: "addBinding.html",
+ sync: true,
+ load: function(data) {
+ var theForm;
+ node.innerHTML = data;
+ addBinding.dialogNode = dom.byId("addBinding");
+ parser.instantiate([addBinding.dialogNode]);
+
+ theForm = registry.byId("formAddBinding");
+ array.forEach(theForm.getDescendants(), function(widget)
+ {
+ if(widget.name === "type") {
+ widget.on("change", function(isChecked) {
+
+ var obj = registry.byId(widget.id + ":fields");
+ if(obj) {
+ if(isChecked) {
+ obj.domNode.style.display = "block";
+ obj.resize();
+ } else {
+ obj.domNode.style.display = "none";
+ obj.resize();
+ }
+ }
+ })
+ }
+
+ });
+
+ theForm.on("submit", function(e) {
+
+ event.stop(e);
+ if(theForm.validate()){
+
+ var newBinding = convertToBinding(theForm.getValues());
+ var that = this;
+
+ xhr.put({url: "rest/binding/"+encodeURIComponent(addBinding.vhost)
+ +"/"+encodeURIComponent(newBinding.exchange)
+ +"/"+encodeURIComponent(newBinding.queue)
+ +"/"+encodeURIComponent(newBinding.name),
+ sync: true, handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.toJson(newBinding),
+ load: function(x) {that.success = true; },
+ error: function(error) {that.success = false; that.failureReason = error;}});
+
+ if(this.success === true)
+ {
+ registry.byId("addBinding").hide();
+ }
+ else
+ {
+ alert("Error:" + this.failureReason);
+ }
+
+ return false;
+
+
+ }else{
+ alert('Form contains invalid data. Please correct first');
+ return false;
+ }
+
+ });
+ }});
+
+ addBinding.show = function(obj) {
+ var that = this;
+
+ addBinding.vhost = obj.virtualhost;
+ addBinding.queue = obj.queue;
+ addBinding.exchange = obj.exchange;
+ registry.byId("formAddBinding").reset();
+
+
+
+ xhr.get({url: "rest/queue/" + encodeURIComponent(obj.virtualhost) + "?depth=0",
+ handleAs: "json"}).then(
+ function(data) {
+ var queues = [];
+ for(var i=0; i < data.length; i++) {
+ queues[i] = {id: data[i].name, name: data[i].name};
+ }
+ var queueStore = new Memory({ data: queues });
+
+
+ if(that.queueChooser) {
+ that.queueChooser.destroy( false );
+ }
+ var queueDiv = dom.byId("addBinding.selectQueueDiv");
+ var input = construct.create("input", {id: "addBindingSelectQueue"}, queueDiv);
+
+ that.queueChooser = new FilteringSelect({ id: "addBindingSelectQueue",
+ name: "queue",
+ store: queueStore,
+ searchAttr: "name"}, input);
+
+ if(obj.queue)
+ {
+ that.queueChooser.set("value", obj.queue);
+ that.queueChooser.set("disabled", true);
+ }
+
+ xhr.get({url: "rest/exchange/" + encodeURIComponent(obj.virtualhost) + "?depth=0",
+ handleAs: "json"}).then(
+ function(data) {
+
+ var exchanges = [];
+ for(var i=0; i < data.length; i++) {
+ exchanges[i] = {id: data[i].name, name: data[i].name};
+ }
+ var exchangeStore = new Memory({ data: exchanges });
+
+
+ if(that.exchangeChooser) {
+ that.exchangeChooser.destroy( false );
+ }
+ var exchangeDiv = dom.byId("addBinding.selectExchangeDiv");
+ var input = construct.create("input", {id: "addBindingSelectExchange"}, exchangeDiv);
+
+ that.exchangeChooser = new FilteringSelect({ id: "addBindingSelectExchange",
+ name: "exchange",
+ store: exchangeStore,
+ searchAttr: "name"}, input);
+
+ if(obj.exchange)
+ {
+ that.exchangeChooser.set("value", obj.exchange);
+ that.exchangeChooser.set("disabled", true);
+ }
+
+
+ registry.byId("addBinding").show();
+ });
+
+
+ });
+
+
+ };
+
+ return addBinding;
+ });
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/addExchange.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/addExchange.js
new file mode 100644
index 0000000000..f88daa54bb
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/addExchange.js
@@ -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.
+ *
+ */
+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 addExchange = {};
+
+ var node = construct.create("div", null, win.body(), "last");
+
+ var convertToExchange = function convertToExchange(formValues)
+ {
+ var newExchange = {};
+ newExchange.name = formValues.name;
+ for(var propName in formValues)
+ {
+ if(formValues.hasOwnProperty(propName))
+ {
+ if(propName === "durable")
+ {
+ if (formValues.durable[0] && formValues.durable[0] == "durable") {
+ newExchange.durable = true;
+ }
+ } else {
+ if(formValues[ propName ] !== "") {
+ newExchange[ propName ] = formValues[propName];
+ }
+ }
+
+ }
+ }
+
+ return newExchange;
+ };
+
+
+ xhr.get({url: "addExchange.html",
+ sync: true,
+ load: function(data) {
+ var theForm;
+ node.innerHTML = data;
+ addExchange.dialogNode = dom.byId("addExchange");
+ parser.instantiate([addExchange.dialogNode]);
+
+ theForm = registry.byId("formAddExchange");
+ array.forEach(theForm.getDescendants(), function(widget)
+ {
+ if(widget.name === "type") {
+ widget.on("change", function(isChecked) {
+
+ var obj = registry.byId(widget.id + ":fields");
+ if(obj) {
+ if(isChecked) {
+ obj.domNode.style.display = "block";
+ obj.resize();
+ } else {
+ obj.domNode.style.display = "none";
+ obj.resize();
+ }
+ }
+ })
+ }
+
+ });
+
+ theForm.on("submit", function(e) {
+
+ event.stop(e);
+ if(theForm.validate()){
+
+ var newExchange = convertToExchange(theForm.getValues());
+ var that = this;
+
+ xhr.put({url: "rest/exchange/"+encodeURIComponent(addExchange.vhost) +
+ "/"+encodeURIComponent(newExchange.name), sync: true, handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.toJson(newExchange),
+ load: function(x) {that.success = true; },
+ error: function(error) {that.success = false; that.failureReason = error;}});
+
+ if(this.success === true)
+ {
+ registry.byId("addExchange").hide();
+ }
+ else
+ {
+ alert("Error:" + this.failureReason);
+ }
+
+ return false;
+
+
+ }else{
+ alert('Form contains invalid data. Please correct first');
+ return false;
+ }
+
+ });
+ }});
+
+ addExchange.show = function(vhost) {
+ addExchange.vhost = vhost;
+ registry.byId("formAddExchange").reset();
+ registry.byId("addExchange").show();
+ };
+
+ return addExchange;
+ }); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/addQueue.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/addQueue.js
new file mode 100644
index 0000000000..4a2dccde5f
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/addQueue.js
@@ -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.
+ *
+ */
+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 addQueue = {};
+
+ var node = construct.create("div", null, win.body(), "last");
+
+ var typeSpecificFields = {
+ numPriorities: "priority",
+ lvqKey: "lvq",
+ sortKey: "sorted"
+ };
+
+
+ var convertToQueue = function convertToQueue(formValues)
+ {
+ var newQueue = {};
+ newQueue.name = formValues.name;
+ for(var propName in formValues)
+ {
+ if(formValues.hasOwnProperty(propName))
+ {
+ if(propName === "durable")
+ {
+ if (formValues.durable[0] && formValues.durable[0] == "durable") {
+ newQueue.durable = true;
+ }
+ } else if (!typeSpecificFields.hasOwnProperty(propName) ||
+ formValues.type === typeSpecificFields[ propName ]) {
+ if(formValues[ propName ] !== "") {
+ newQueue[ propName ] = formValues[propName];
+ }
+ }
+
+ }
+ }
+
+ return newQueue;
+ };
+
+
+ xhr.get({url: "addQueue.html",
+ sync: true,
+ load: function(data) {
+ var theForm;
+ node.innerHTML = data;
+ addQueue.dialogNode = dom.byId("addQueue");
+ parser.instantiate([addQueue.dialogNode]);
+
+ // for children which have name type, add a function to make all the associated rows
+ // visible / invisible as the radio button is checked / unchecked
+
+ theForm = registry.byId("formAddQueue");
+ array.forEach(theForm.getDescendants(), function(widget)
+ {
+ if(widget.name === "type") {
+ widget.on("change", function(isChecked) {
+
+ var obj = registry.byId(widget.id + ":fields");
+ if(obj) {
+ if(isChecked) {
+ obj.domNode.style.display = "block";
+ obj.resize();
+ } else {
+ obj.domNode.style.display = "none";
+ obj.resize();
+ }
+ }
+ })
+ }
+
+ });
+
+ theForm.on("submit", function(e) {
+
+ event.stop(e);
+ if(theForm.validate()){
+
+ var newQueue = convertToQueue(theForm.getValues());
+ var that = this;
+
+ xhr.put({url: "rest/queue/"+encodeURIComponent(addQueue.vhost)
+ +"/"+encodeURIComponent(newQueue.name), sync: true, handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.toJson(newQueue),
+ load: function(x) {that.success = true; },
+ error: function(error) {that.success = false; that.failureReason = error;}});
+
+ if(this.success === true)
+ {
+ registry.byId("addQueue").hide();
+ }
+ else
+ {
+ alert("Error:" + this.failureReason);
+ }
+
+ return false;
+
+
+ }else{
+ alert('Form contains invalid data. Please correct first');
+ return false;
+ }
+
+ });
+ }});
+
+ addQueue.show = function(vhost) {
+ addQueue.vhost = vhost;
+ registry.byId("formAddQueue").reset();
+ registry.byId("addQueue").show();
+ };
+
+ return addQueue;
+ }); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js
new file mode 100644
index 0000000000..ffebc98af7
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js
@@ -0,0 +1,327 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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 DatabaseAuthManager(containerNode, authProviderObj, controller) {
+ var node = construct.create("div", null, containerNode, "last");
+ var that = this;
+ this.name = authProviderObj.name;
+ xhr.get({url: "authenticationprovider/showPrincipalDatabaseAuthenticationManager.html",
+ sync: true,
+ load: function(data) {
+ node.innerHTML = data;
+ parser.parse(node);
+
+
+ that.authDatabaseUpdater= new AuthProviderUpdater(node, authProviderObj, controller);
+
+ updater.add( that.authDatabaseUpdater);
+
+ that.authDatabaseUpdater.update();
+
+
+ }});
+ }
+
+ DatabaseAuthManager.prototype.update = function() {
+ this.authDatabaseUpdater.update();
+ };
+
+ DatabaseAuthManager.prototype.close = function() {
+ updater.remove( this.authDatabaseUpdater );
+ };
+
+ function AuthProviderUpdater(node, authProviderObj, controller)
+ {
+ this.controller = controller;
+ this.query = "rest/authenticationprovider/"+encodeURIComponent(authProviderObj.name);
+ this.name = authProviderObj.name;
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data) {
+ that.authProviderData = data[0];
+
+ util.flattenStatistics( that.authProviderData );
+
+ var userDiv = query(".users")[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.usersGrid =
+ new UpdatableStore(that.authProviderData.users, userDiv,
+ [ { name: "User Name", field: "name", width: "100%" }
+ ], function(obj) {
+ connect.connect(obj.grid, "onRowDblClick", obj.grid,
+ function(evt){
+ var idx = evt.rowIndex,
+ theItem = this.getItem(idx);
+ var name = obj.dataStore.getValue(theItem,"name");
+ var id = obj.dataStore.getValue(theItem,"id");
+ setPassword.show(authProviderObj.name, {name: name, id: id});
+ });
+ }, gridProperties, EnhancedGrid);
+
+
+ var addUserButton = query(".addUserButton", node)[0];
+ connect.connect(registry.byNode(addUserButton), "onClick", function(evt){ addUser.show(authProviderObj.name) });
+
+ var deleteMessagesButton = query(".deleteUserButton", node)[0];
+ var deleteWidget = registry.byNode(deleteMessagesButton);
+ connect.connect(deleteWidget, "onClick",
+ function(evt){
+ event.stop(evt);
+ that.deleteUsers();
+ });
+ });
+ }
+
+ AuthProviderUpdater.prototype.deleteUsers = function()
+ {
+ var grid = this.usersGrid.grid;
+ var data = grid.selection.getSelected();
+ if(data.length) {
+ var that = this;
+ if(confirm("Delete " + data.length + " users?")) {
+ var i, queryParam;
+ for(i = 0; i<data.length; i++) {
+ if(queryParam) {
+ queryParam += "&";
+ } else {
+ queryParam = "?";
+ }
+
+ queryParam += "id=" + data[i].id;
+ }
+ var query = "rest/user/"+ encodeURIComponent(that.name)
+ + queryParam;
+ that.success = true
+ xhr.del({url: query, sync: true, handleAs: "json"}).then(
+ function(data) {
+ grid.setQuery({id: "*"});
+ grid.selection.deselectAll();
+ that.update();
+ },
+ function(error) {that.success = false; that.failureReason = error;});
+ if(!that.success ) {
+ alert("Error:" + this.failureReason);
+ }
+ }
+}
+ };
+
+ AuthProviderUpdater.prototype.update = function()
+ {
+
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data) {
+ that.authProviderData = data[0];
+ util.flattenStatistics( that.authProviderData );
+
+ that.usersGrid.update(that.authProviderData.users);
+
+ });
+
+
+ };
+
+ var addUser = {};
+
+ var node = construct.create("div", null, win.body(), "last");
+
+ var convertToUser = function convertToUser(formValues) {
+ var newUser = {};
+ newUser.name = formValues.name;
+ for(var propName in formValues)
+ {
+ if(formValues.hasOwnProperty(propName)) {
+ if(formValues[ propName ] !== "") {
+ newUser[ propName ] = formValues[propName];
+ }
+ }
+ }
+
+ return newUser;
+ };
+
+
+ xhr.get({url: "authenticationprovider/addUser.html",
+ sync: true,
+ load: function(data) {
+ var theForm;
+ node.innerHTML = data;
+ addUser.dialogNode = dom.byId("addUser");
+ parser.instantiate([addUser.dialogNode]);
+
+ var that = this;
+
+ theForm = registry.byId("formAddUser");
+ theForm.on("submit", function(e) {
+
+ event.stop(e);
+ if(theForm.validate()){
+
+ var newUser = convertToUser(theForm.getValues());
+
+
+ var url = "rest/user/"+encodeURIComponent(addUser.authProvider) +
+ "/"+encodeURIComponent(newUser.name);
+
+ xhr.put({url: url, sync: true, handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.toJson(newUser),
+ load: function(x) {that.success = true; },
+ error: function(error) {that.success = false; that.failureReason = error;}});
+
+ if(this.success === true) {
+ registry.byId("addUser").hide();
+ } else {
+ alert("Error:" + this.failureReason);
+ }
+
+ return false;
+
+
+ }else{
+ alert('Form contains invalid data. Please correct first');
+ return false;
+ }
+
+ });
+ }});
+
+ addUser.show = function(authProvider) {
+ addUser.authProvider = authProvider;
+ registry.byId("formAddUser").reset();
+ registry.byId("addUser").show();
+ };
+
+
+ var setPassword = {};
+
+ var setPasswordNode = construct.create("div", null, win.body(), "last");
+
+ xhr.get({url: "authenticationprovider/setPassword.html",
+ sync: true,
+ load: function(data) {
+ var theForm;
+ setPasswordNode.innerHTML = data;
+ setPassword.dialogNode = dom.byId("setPassword");
+ parser.instantiate([setPassword.dialogNode]);
+
+ var that = this;
+
+ theForm = registry.byId("formSetPassword");
+ theForm.on("submit", function(e) {
+
+ event.stop(e);
+ if(theForm.validate()){
+
+ var newUser = convertToUser(theForm.getValues());
+ newUser.name = setPassword.name;
+ newUser.id = setPassword.id;
+
+ var url = "rest/user/"+encodeURIComponent(setPassword.authProvider) +
+ "/"+encodeURIComponent(newUser.name);
+
+ xhr.put({url: url, sync: true, handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.toJson(newUser),
+ load: function(x) {that.success = true; },
+ error: function(error) {that.success = false; that.failureReason = error;}});
+
+ if(that.success === true) {
+ registry.byId("setPassword").hide();
+ } else {
+ alert("Error:" + that.failureReason);
+ }
+
+ return false;
+
+
+ }else{
+ alert('Form contains invalid data. Please correct first');
+ return false;
+ }
+
+ });
+ }});
+
+ setPassword.show = function(authProvider, user) {
+ setPassword.authProvider = authProvider;
+ setPassword.name = user.name;
+ setPassword.id = user.id;
+ registry.byId("formSetPassword").reset();
+
+ var namebox = registry.byId("formSetPassword.name");
+ namebox.set("value", user.name);
+ namebox.set("disabled", true);
+
+ registry.byId("setPassword").show();
+
+ };
+
+
+
+ return DatabaseAuthManager;
+ });
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/controller.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/controller.js
new file mode 100644
index 0000000000..1aa05a5a3c
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/controller.js
@@ -0,0 +1,104 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+define(["dojo/dom",
+ "dijit/registry",
+ "dijit/layout/ContentPane",
+ "qpid/management/Broker",
+ "qpid/management/VirtualHost",
+ "qpid/management/Exchange",
+ "qpid/management/Queue",
+ "qpid/management/Connection",
+ "qpid/management/AuthenticationProvider",
+ "dojo/ready",
+ "dojo/domReady!"],
+ function (dom, registry, ContentPane, Broker, VirtualHost, Exchange, Queue, Connection, AuthProvider, ready) {
+ var controller = {};
+
+ var constructors = { broker: Broker, virtualhost: VirtualHost, exchange: Exchange,
+ queue: Queue, connection: Connection, authenticationprovider: AuthProvider };
+
+ var tabDiv = dom.byId("managedViews");
+
+ ready(function() {
+ controller.tabContainer = registry.byId("managedViews");
+ });
+
+
+ controller.viewedObjects = {};
+
+ controller.show = function(objType, name, parent) {
+
+ function generateName(obj)
+ {
+ if(obj) {
+ var name = "";
+ if(obj.parent)
+ {
+ for(var prop in obj.parent) {
+ if(obj.parent.hasOwnProperty(prop)) {
+ name = name + generateName( obj.parent[ prop ]);
+ }
+ }
+
+ }
+ return name + parent.type +":" + parent.name + "/"
+ }
+ }
+
+ var that = this;
+ var objId = generateName(parent) + objType+":"+name;
+ if( this.viewedObjects[ objId ] ) {
+ this.tabContainer.selectChild(this.viewedObjects[ objId ].contentPane);
+ } else {
+ var Constructor = constructors[ objType ];
+ if(Constructor) {
+ var obj = new Constructor(name, parent, this);
+ this.viewedObjects[ objId ] = obj;
+
+ var contentPane = new ContentPane({ region: "center" ,
+ title: obj.getTitle(),
+ closable: true,
+ onClose: function() {
+ obj.close();
+ delete that.viewedObjects[ objId ];
+ return true;
+ }
+ });
+ this.tabContainer.addChild( contentPane );
+ obj.open(contentPane);
+ contentPane.startup();
+ if(obj.startup) {
+ obj.startup();
+ }
+ this.tabContainer.selectChild( contentPane );
+ }
+
+ }
+
+ };
+
+ ready(function() {
+ controller.show("broker","");
+ });
+
+
+ return controller;
+ }); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/moveCopyMessages.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/moveCopyMessages.js
new file mode 100644
index 0000000000..8cc488324f
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/moveCopyMessages.js
@@ -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.
+ */
+
+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',
+ "dojo/store/Memory",
+ "dijit/form/FilteringSelect",
+ "dojo/query",
+ "dojo/_base/connect",
+ "dojo/domReady!"],
+ function (xhr, dom, construct, win, registry, parser, array, event, json, Memory, FilteringSelect, query, connect) {
+
+ var moveMessages = {};
+
+ var node = construct.create("div", null, win.body(), "last");
+
+ xhr.get({url: "moveCopyMessages.html",
+ sync: true,
+ load: function(data) {
+ var theForm;
+ node.innerHTML = data;
+ moveMessages.dialogNode = dom.byId("moveMessages");
+ parser.instantiate([moveMessages.dialogNode]);
+
+ theForm = registry.byId("formMoveMessages");
+
+
+ var cancelButton = query(".moveMessageCancel")[0];
+ connect.connect(registry.byNode(cancelButton), "onClick",
+ function(evt){
+ event.stop(evt);
+ registry.byId("moveMessages").hide();
+ });
+
+
+ theForm.on("submit", function(e) {
+
+ event.stop(e);
+ if(theForm.validate()){
+
+ moveMessages.data.destinationQueue = theForm.getValues()["queue"];
+ var that = this;
+
+ xhr.post({url: "rest/message/"+encodeURIComponent(moveMessages.vhost)
+ +"/"+encodeURIComponent(moveMessages.queue),
+ sync: true, handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ postData: json.toJson(moveMessages.data),
+ load: function(x) {that.success = true; },
+ error: function(error) {that.success = false; that.failureReason = error;}});
+
+ if(this.success === true) {
+ registry.byId("moveMessages").hide();
+ if(moveMessages.next) {
+ moveMessages.next();
+ }
+ } else {
+ alert("Error:" + this.failureReason);
+ }
+
+ return false;
+
+
+ }else{
+ alert('Form contains invalid data. Please correct first');
+ return false;
+ }
+
+ });
+
+ }});
+
+ moveMessages.show = function(obj, next) {
+ var that = this;
+
+ moveMessages.vhost = obj.virtualhost;
+ moveMessages.queue = obj.queue;
+ moveMessages.data = obj.data;
+ moveMessages.next = next;
+ registry.byId("formMoveMessages").reset();
+
+
+
+ xhr.get({url: "rest/queue/" + encodeURIComponent(obj.virtualhost) + "?depth=0",
+ handleAs: "json"}).then(
+ function(data) {
+ var queues = [];
+ for(var i=0; i < data.length; i++) {
+ queues[i] = {id: data[i].name, name: data[i].name};
+ }
+ var queueStore = new Memory({ data: queues });
+
+
+ if(that.queueChooser) {
+ that.queueChooser.destroy( false );
+ }
+ var queueDiv = dom.byId("moveMessages.selectQueueDiv");
+ var input = construct.create("input", {id: "moveMessagesSelectQueue"}, queueDiv);
+
+ that.queueChooser = new FilteringSelect({ id: "moveMessagesSelectQueue",
+ name: "queue",
+ store: queueStore,
+ searchAttr: "name"}, input);
+
+
+
+ registry.byId("moveMessages").show();
+
+
+ });
+
+
+ };
+
+ return moveMessages;
+ });
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/showMessage.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/showMessage.js
new file mode 100644
index 0000000000..b1ccc0ca07
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/showMessage.js
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+define(["dojo/_base/xhr",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dojo/dom-class",
+ "dojo/_base/window",
+ "dijit/registry",
+ "dojo/parser",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ 'dojo/_base/json',
+ "dojo/query",
+ "dojo/_base/connect",
+ "qpid/common/properties",
+ "dojox/html/entities",
+ "dojo/domReady!"],
+ function (xhr, dom, construct, domClass, win, registry, parser, array, event, json, query, connect, properties, entities) {
+
+
+ function encode(val){
+ return typeof val === 'string' ? entities.encode(val) : val;
+ }
+
+ var showMessage = {};
+
+ showMessage.hide = function () {
+ if(this.populatedFields) {
+ for(var i = 0 ; i < this.populatedFields.length; i++) {
+ this.populatedFields[i].innerHTML = "";
+ }
+ this.populatedFields = [];
+ }
+ registry.byId("showMessage").hide();
+ };
+
+ showMessage.loadViewMessage = function(data) {
+ var that = this;
+ node.innerHTML = data;
+ showMessage.dialogNode = dom.byId("showMessage");
+ parser.instantiate([showMessage.dialogNode]);
+
+ var closeButton = query(".closeViewMessage")[0];
+ connect.connect(closeButton, "onclick",
+ function (evt) {
+ event.stop(evt);
+ showMessage.hide();
+ });
+ };
+
+ showMessage.populateShowMessage = function(data) {
+
+ this.populatedFields = [];
+
+ for(var attrName in data) {
+ if(data.hasOwnProperty(attrName)) {
+ var fields = query(".message-"+attrName, this.dialogNode);
+ if(fields && fields.length != 0) {
+ var field = fields[0];
+ this.populatedFields.push(field);
+ var val = data[attrName];
+ if(val) {
+ if(domClass.contains(field,"map")) {
+ var tableStr = "<table style='border: 1pt'><tr><th style='width: 6em; font-weight: bold'>Header</th><th style='font-weight: bold'>Value</th></tr>";
+ for(var name in val) {
+ if(val.hasOwnProperty(name)) {
+
+ tableStr += "<tr><td>"+encode(name)+"</td>";
+ tableStr += "<td>"+encode(val[ name ])+"</td></tr>";
+ }
+ field.innerHTML = tableStr;
+ }
+ tableStr += "</table>";
+ } else if(domClass.contains(field,"datetime")) {
+ var d = new Date(0);
+ d.setUTCSeconds(val/1000);
+ field.innerHTML = d.toLocaleString();
+ } else {
+ field.innerHTML = encode(val);
+ }
+ }
+ }
+ }
+ }
+ var contentField = query(".message-content", this.dialogNode)[0];
+
+ if(data.mimeType && data.mimeType.match(/text\/.*/)) {
+ xhr.get({url: "rest/message-content/" + encodeURIComponent(showMessage.virtualhost)
+ + "/" + encodeURIComponent(showMessage.queue)
+ + "/" + encodeURIComponent(showMessage.messageNumber),
+ sync: true
+
+ }).then(function(obj) { contentField.innerHTML = encode(obj) });
+ } else {
+ contentField.innerHTML = "<a href=\"" + "rest/message-content/" + encodeURIComponent(showMessage.virtualhost)
+ + "/" + encodeURIComponent(showMessage.queue)
+ + "/" + encodeURIComponent(showMessage.messageNumber)
+ + "\" target=\"_blank\">Download</a>";
+ }
+ this.populatedFields.push(contentField);
+
+ registry.byId("showMessage").show();
+ };
+
+ showMessage.show = function(obj) {
+ showMessage.virtualhost = obj.virtualhost;
+ showMessage.queue = obj.queue;
+ showMessage.messageNumber = obj.messageNumber;
+
+ xhr.get({url: "rest/message/" + encodeURIComponent(obj.virtualhost)
+ + "/" + encodeURIComponent(obj.queue)
+ + "/" + encodeURIComponent(obj.messageNumber),
+ sync: properties.useSyncGet,
+ handleAs: "json",
+ load: this.populateShowMessage
+ });
+ };
+
+ var node = construct.create("div", null, win.body(), "last");
+
+ xhr.get({url: "showMessage.html",
+ sync: true,
+ load: showMessage.loadViewMessage
+ });
+
+ return showMessage;
+ });
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/treeView.js b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/treeView.js
new file mode 100644
index 0000000000..b1d4abf8c1
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/js/qpid/management/treeView.js
@@ -0,0 +1,313 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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/query",
+ "dojo/io-query",
+ "dijit/Tree",
+ "qpid/common/util",
+ "qpid/common/updater",
+ "qpid/management/controller",
+ "dojo/domReady!"],
+ function (xhr, query, ioQuery, Tree, util, updater, controller) {
+
+ function TreeViewModel(queryString) {
+ this.query = queryString;
+
+ this.onChildrenChange = function (parent, children) {
+ // fired when the set of children for an object change
+ };
+
+ this.onChange = function (object) {
+ // fired when the properties of an object change
+ };
+
+ this.onDelete = function (object) {
+ // fired when an object is deleted
+ };
+
+ }
+
+
+ TreeViewModel.prototype.buildModel = function (data) {
+ this.model = data;
+
+ };
+
+ TreeViewModel.prototype.updateModel = function (data) {
+ var that = this;
+
+ function checkForChanges(oldData, data) {
+ var propName;
+ if (oldData.name != data.name) {
+ that.onChange(data);
+ }
+
+ var childChanges = false;
+ // Iterate over old childTypes, check all are in new
+ for (propName in oldData) {
+ if (oldData.hasOwnProperty(propName)) {
+ var oldChildren = oldData[ propName ];
+ if (util.isArray(oldChildren)) {
+
+ var newChildren = data[ propName ];
+
+ if (!(newChildren && util.isArray(newChildren))) {
+ childChanges = true;
+ } else {
+ var subChanges = false;
+ // iterate over elements in array, make sure in both, in which case recurse
+ for (var i = 0; i < oldChildren.length; i++) {
+ var matched = false;
+ for (var j = 0; j < newChildren.length; j++) {
+ if (oldChildren[i].id == newChildren[j].id) {
+ checkForChanges(oldChildren[i], newChildren[j]);
+ matched = true;
+ break;
+ }
+ }
+ if (!matched) {
+ subChanges = true;
+ }
+ }
+ if (subChanges == true || oldChildren.length != newChildren.length) {
+ that.onChildrenChange({ id:data.id + propName, _dummyChild:propName, data:data },
+ newChildren);
+ }
+ }
+ }
+ }
+ }
+
+ for (propName in data) {
+ if (data.hasOwnProperty(propName)) {
+ var prop = data[ propName ];
+ if (util.isArray(prop)) {
+ if (!(oldData[ propName ] && util.isArray(oldData[propName]))) {
+ childChanges = true;
+ }
+ }
+ }
+ }
+
+ if (childChanges) {
+ var children = [];
+ that.getChildren(data, function (theChildren) {
+ children = theChildren
+ });
+ that.onChildrenChange(data, children);
+ }
+ }
+
+ var oldData = this.model;
+ this.model = data;
+
+ checkForChanges(oldData, data);
+ };
+
+
+ TreeViewModel.prototype.fetchItemByIdentity = function (id) {
+
+ function fetchItem(id, data) {
+ var propName;
+
+ if (data.id == id) {
+ return data;
+ } else if (id.indexOf(data.id) == 0) {
+ return { id:id, _dummyChild:id.substring(id.length), data:data };
+ } else {
+ for (propName in data) {
+ if (data.hasOwnProperty(propName)) {
+ var prop = data[ propName ];
+ if (util.isArray(prop)) {
+ for (var i = 0; i < prop.length; i++) {
+ var theItem = fetchItem(id, prop[i]);
+ if (theItem) {
+ return theItem;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+ }
+
+ return fetchItem(id, this.model);
+ };
+
+ TreeViewModel.prototype.getChildren = function (parentItem, onComplete) {
+
+ if (parentItem) {
+ if (parentItem._dummyChild) {
+ onComplete(parentItem.data[ parentItem._dummyChild ]);
+ } else {
+ var children = [];
+ for (var propName in parentItem) {
+ if (parentItem.hasOwnProperty(propName)) {
+ var prop = parentItem[ propName ];
+
+ if (util.isArray(prop)) {
+ children.push({ id:parentItem.id
+ + propName, _dummyChild:propName, data:parentItem });
+ }
+ }
+ }
+ onComplete(children);
+ }
+ } else {
+ onComplete([]);
+ }
+ };
+
+ TreeViewModel.prototype.getIdentity = function (theItem) {
+ if (theItem) {
+ return theItem.id;
+ }
+
+ };
+
+ TreeViewModel.prototype.getLabel = function (theItem) {
+ if (theItem) {
+ if (theItem._dummyChild) {
+ return theItem._dummyChild;
+ } else {
+ return theItem.name;
+ }
+ } else {
+ return "";
+ }
+ };
+
+ TreeViewModel.prototype.getRoot = function (onItem) {
+ onItem(this.model);
+ };
+
+ TreeViewModel.prototype.mayHaveChildren = function (theItem) {
+ if (theItem) {
+ if (theItem._dummyChild) {
+ return true;
+ } else {
+ for (var propName in theItem) {
+ if (theItem.hasOwnProperty(propName)) {
+ var prop = theItem[ propName ];
+ if (util.isArray(prop)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ } else {
+ return false;
+ }
+ };
+
+ TreeViewModel.prototype.relocate = function (theItem) {
+
+ function findItemDetails(theItem, details, type, object) {
+ if (theItem.id == object.id) {
+ details.type = type;
+ details[ type ] = object.name;
+ } else {
+ details[ type ] = object.name;
+
+ // iterate over children
+ for (var propName in object) {
+ if (object.hasOwnProperty(propName)) {
+ var prop = object[ propName ];
+ if (util.isArray(prop)) {
+ for (var i = 0; i < prop.length; i++) {
+ findItemDetails(theItem, details, propName.substring(0, propName.length - 1),
+ prop[i]);
+
+ if (details.type) {
+ break;
+ }
+ }
+ }
+ if (details.type) {
+ break;
+ }
+ }
+ }
+
+ if (!details.type) {
+ details[ type ] = null;
+ }
+ }
+ }
+
+ var details = new Object();
+
+ findItemDetails(theItem, details, "broker", this.model);
+
+ if (details.type == "broker") {
+ controller.show("broker", "");
+ } else if (details.type == "virtualhost") {
+ controller.show("virtualhost", details.virtualhost, {type:"broker", name:""});
+ } else if (details.type == "exchange") {
+ controller.show("exchange", details.exchange, { type: "virtualhost", name: details.virtualhost, parent: {broker: {type:"broker", name:""}}});
+ } else if (details.type == "queue") {
+ controller.show("queue", details.queue, { type: "virtualhost", name: details.virtualhost, parent: {broker: {type:"broker", name:""}}});
+ } else if (details.type == "connection") {
+ controller.show("connection", details.connection, { type: "virtualhost", name: details.virtualhost, parent: {broker: {type:"broker", name:""}}});
+ } else if (details.type == 'port') {
+ controller.show("port", details.port, { type: "virtualhost", name: details.virtualhost, parent: {broker: {type:"broker", name:""}}});
+ } else if (details.type == 'authenticationprovider') {
+ controller.show("authenticationprovider", details.authenticationprovider, {broker: {type:"broker", name:""}});
+ }
+
+
+
+ };
+
+ TreeViewModel.prototype.update = function () {
+ var thisObj = this;
+
+ xhr.get({url:this.query, sync: true, handleAs:"json"})
+ .then(function (data) {
+ if (thisObj.model) {
+ thisObj.updateModel(data);
+ }
+ else {
+ thisObj.buildModel(data);
+ }
+ });
+
+ };
+
+ query('div[qpid-type="treeView"]').forEach(function(node, index, arr) {
+ var treeModel = new TreeViewModel("rest/structure");
+ treeModel.update();
+ var tree = new Tree({ model: treeModel }, node);
+ tree.on("dblclick",
+ function (object) {
+ if (object && !object._dummyChild) {
+ treeModel.relocate(object);
+ }
+
+ }, true);
+ tree.startup();
+ updater.add( treeModel );
+ });
+
+ return TreeViewModel;
+ }); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/management.html b/qpid/java/broker-plugins/management/src/main/java/resources/management.html
new file mode 100644
index 0000000000..a8345a8503
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/management.html
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Qpid Management</title>
+ <link rel="stylesheet" href="dojo/dojo/resources/dojo.css">
+ <link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css">
+ <link rel="stylesheet" href="dojo/dojox/grid/resources/claroGrid.css">
+ <link rel="stylesheet" href="dojo/dojox/grid/enhanced/resources/claro/EnhancedGrid.css">
+ <link rel="stylesheet" href="dojo/dojox/grid/enhanced/resources/EnhancedGrid_rtl.css">
+ <link rel="stylesheet" href="css/common.css" media="screen">
+ <script>
+ function getContextPath()
+ {
+ var contextPath = "/";
+ var documentURL = document.URL;
+ var managementPageStart = documentURL.lastIndexOf("/");
+ var firstSlashPos = documentURL.indexOf("/", documentURL.indexOf("//") + 2);
+ if (managementPageStart > firstSlashPos)
+ {
+ contextPath = documentURL.substring(firstSlashPos, managementPageStart);
+ }
+ return contextPath;
+ }
+
+ var dojoConfig = {
+ tlmSiblingOfDojo:false,
+ parseOnLoad:true,
+ async:true,
+ baseUrl: getContextPath(),
+ packages:[
+ { name:"dojo", location:"dojo/dojo" },
+ { name:"dijit", location:"dojo/dijit" },
+ { name:"dojox", location:"dojo/dojox" },
+ { name:"qpid", location:"js/qpid" }
+ ]
+ };
+
+ </script>
+ <script src="dojo/dojo/dojo.js">
+ </script>
+
+ <script>
+ require(["dijit/layout/BorderContainer",
+ "dijit/layout/TabContainer",
+ "dijit/layout/ContentPane",
+ "dijit/TitlePane",
+ "dojo/parser",
+ "qpid/management/treeView",
+ "qpid/management/controller",
+ "qpid/common/footer",
+ "qpid/authorization/sasl"]);
+ </script>
+
+</head>
+<body class="claro">
+
+<div id="pageLayout" data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design: 'headline', gutters: false">
+ <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'top'">
+ <div id="header" class="header"></div>
+ </div>
+ <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'top'">
+ <div id="login"></div>
+ </div>
+ <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'leading', splitter: true">
+ <div qpid-type="treeView" qpid-props="query: 'rest/structure'" ></div>
+ </div>
+ <div id="managedViews" data-dojo-type="dijit.layout.TabContainer" data-dojo-props="region:'center', tabPosition: 'top'">
+ </div>
+ <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'bottom'">
+ <div qpid-type="footer"></div>
+ </div>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/moveCopyMessages.html b/qpid/java/broker-plugins/management/src/main/java/resources/moveCopyMessages.html
new file mode 100644
index 0000000000..f188c3001c
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/moveCopyMessages.html
@@ -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.
+ -->
+
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Move/Copy Messages'" id="moveMessages">
+ <form id="formMoveMessages" method="post" dojoType="dijit.form.Form">
+ <table cellpadding="0" cellspacing="2">
+ <tr>
+ <td valign="top"><strong>Queue: </strong></td>
+ <td><div id="moveMessages.selectQueueDiv"></div></td>
+ </tr>
+ </table>
+ <br/>
+
+ <!-- submit buttons -->
+
+ <input type="button" value="Cancel" label="Cancel" dojoType="dijit.form.Button" class="moveMessageCancel"/>
+ <input type="submit" value="Move Messages" label="Move Messages" dojoType="dijit.form.Button" />
+
+ </form>
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/showAuthProvider.html b/qpid/java/broker-plugins/management/src/main/java/resources/showAuthProvider.html
new file mode 100644
index 0000000000..c5d4e48a75
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/showAuthProvider.html
@@ -0,0 +1,25 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<div class="authorizationProvider">
+ <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span>
+ <br/>
+ <span style="">Type:</span><span class="type" style="position:absolute; left:6em"></span>
+</div> \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/showBroker.html b/qpid/java/broker-plugins/management/src/main/java/resources/showBroker.html
new file mode 100644
index 0000000000..cb2f4a4b9a
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/showBroker.html
@@ -0,0 +1,25 @@
+<div class="broker">
+ <span>Broker:</span><span class="broker-name" style="position:absolute; left:6em"></span>
+ <br/>
+<!-- <span>State:</span><span class="broker-state" style="position:absolute; left:6em"></span>
+ <br/>
+ <span>Durable:</span><span class="broker-durable" style="position:absolute; left:6em"></span>
+ <br/>
+ <span>Lifespan:</span><span class="broker-lifetimePolicy" style="position:absolute; left:6em" ></span>
+ <br/> -->
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Virtual Hosts'">
+ <div class="broker-virtualhosts"></div>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Ports'">
+ <div class="broker-ports"></div>
+ </div>
+ <br/>
+
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Log File', open: false">
+ <div class="broker-logfile"></div>
+ </div>
+ <br/>
+</div>
+
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/showConnection.html b/qpid/java/broker-plugins/management/src/main/java/resources/showConnection.html
new file mode 100644
index 0000000000..84854daf47
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/showConnection.html
@@ -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.
+ -
+ -->
+<div class="connection">
+ <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span>
+ <br/>
+ <span style="">State:</span><span class="state" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Pre-fetched:</span>
+ <br/>
+ <span style="">Durable:</span><span class="durable" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Inbound:</span>
+ <span class="msgInRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesInRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesInRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <span style="">Lifespan:</span><span style="position:absolute; left:6em" class="lifetimePolicy"></span>
+ <span style="position:absolute; left:26em">Outbound:</span>
+ <span class="msgOutRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesOutRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesOutRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Sessions'">
+ <div class="sessions"></div>
+ </div>
+ <br/>
+
+</div>
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/showExchange.html b/qpid/java/broker-plugins/management/src/main/java/resources/showExchange.html
new file mode 100644
index 0000000000..64f351d218
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/showExchange.html
@@ -0,0 +1,46 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<div class="exchange">
+ <span style="">Exchange:</span><span class="name" style="position:absolute; left:6em"></span>
+ <br/>
+ <span style="">State:</span><span class="state" style="position:absolute; left:6em"></span>
+ <br/>
+ <span style="">Durable:</span><span class="durable" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Inbound:</span>
+ <span class="msgInRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesInRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesInRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <span style="">Lifespan:</span><span style="position:absolute; left:6em" class="lifetimePolicy"></span>
+ <span style="position:absolute; left:26em">Dropped:</span>
+ <span class="msgDropRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesDropRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesDropRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Bindings'">
+ <div class="bindings"></div>
+ <button data-dojo-type="dijit.form.Button" class="addBindingButton">Add Binding</button>
+ </div>
+ <br/>
+</div>
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/showMessage.html b/qpid/java/broker-plugins/management/src/main/java/resources/showMessage.html
new file mode 100644
index 0000000000..0dea508c60
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/showMessage.html
@@ -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.
+ -->
+
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'View Message'" id="showMessage">
+
+ <table style="border: 0;">
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Message Number:</span></td>
+ <td><span class="message-id"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Message Id:</span></td>
+ <td><span class="message-messageId"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">State:</span></td>
+ <td><span class="message-state"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Persistent:</span></td>
+ <td><span class="message-persistent boolean"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Priority:</span></td>
+ <td><span class="message-priority"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Arrival Time:</span>
+ </td><td><span class="message-arrivalTime datetime"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Expiration:</span></td>
+ <td><span class="message-expiration datetime"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">MIME Type:</span></td>
+ <td><span class="message-mimeType"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">User:</span></td>
+ <td><span class="message-userId"></span></td>
+ </tr>
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Headers:</span></td>
+ <td><div class="message-headers map"></div></td>
+ </tr>
+
+ <tr style="margin-bottom: 4pt">
+ <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Content:</span></td>
+ <td><div class="message-content"></div></td>
+ </tr>
+ </table>
+ <br/>
+ <input type="button" value="Close" label="Close" dojoType="dijit.form.Button" class="closeViewMessage"/>
+
+ </div>
+</div>
+
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/showQueue.html b/qpid/java/broker-plugins/management/src/main/java/resources/showQueue.html
new file mode 100644
index 0000000000..c87a462760
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/showQueue.html
@@ -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.
+ -
+ -->
+<div class="queue">
+ <span style="">Queue:</span><span class="name" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Size:</span>
+ <span class="queueDepthMessages" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msgs</span>
+ <span class="queueDepthBytes" style="position:absolute; right: 3.3em">(</span>
+ <span class="queueDepthBytesUnits" style="position:absolute; right: 0em; width: 3em">)</span>
+ <br/>
+ <span style="">State:</span><span class="state" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Pre-fetched:</span>
+ <span class="unacknowledgedMessages" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msgs</span>
+ <span class="unacknowledgedBytes" style="position:absolute; right: 3.3em"></span>
+ <span class="unacknowledgedBytesUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <span style="">Durable:</span><span class="durable" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Inbound:</span>
+ <span class="msgInRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesInRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesInRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <span style="">Lifespan:</span><span style="position:absolute; left:6em" class="lifetimePolicy"></span>
+ <span style="position:absolute; left:26em">Outbound:</span>
+ <span class="msgOutRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesOutRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesOutRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Bindings'">
+ <div class="bindings"></div>
+ <button data-dojo-type="dijit.form.Button" class="addBindingButton" type="button">Add Binding</button>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Consumers'">
+ <div class="consumers"></div>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Messages'">
+ <div class="messages"></div>
+ <button data-dojo-type="dijit.form.Button" class="deleteMessagesButton" type="button">Delete Messages</button>
+ <button data-dojo-type="dijit.form.Button" class="moveMessagesButton" type="button">Move Messages</button>
+ <button data-dojo-type="dijit.form.Button" class="copyMessagesButton" type="button">Copy Messages</button>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Alerting Thresholds', open: false">
+ <span style="">Max. Queue Size:</span>
+ <span class="alertThresholdQueueDepthMessages"
+ style="position:absolute; left:8em; width:8em; text-align:right"></span>
+ <span style="position:absolute; left:16.2em">msgs</span>
+
+ <span class="alertThresholdQueueDepthBytes"
+ style="position:absolute; left:20em; width:8em; text-align:right"></span>
+ <span class="alertThresholdQueueDepthBytesUnits" style="position:absolute; left:28.2em"></span>
+ <br>
+ <span style="">Max. Message Age:</span>
+ <span class="alertThresholdMessageAge"
+ style="position:absolute; left:8em; width:8em; text-align:right"></span>
+ <span class="alertThresholdMessageAgeUnits" style="position:absolute; left:16.2em"></span>
+
+ <span style="position:absolute; left:21em">Size: </span>
+ <span class="alertThresholdMessageSize"
+ style="position:absolute; left:23em; width:5em; text-align:right"></span>
+ <span class="alertThresholdMessageSizeUnits" style="position:absolute; left:28.2em"></span>
+ <br/>
+ <br/>
+ <span style="">Alert frequency:</span>
+ <span class="alertRepeatGap"
+ style="position:absolute; left:8em; width:8em; text-align:right"></span>
+ <span class="alertRepeatGapUnits" style="position:absolute; left:16.2em"></span>
+
+
+
+ </div>
+</div>
+
diff --git a/qpid/java/broker-plugins/management/src/main/java/resources/showVirtualHost.html b/qpid/java/broker-plugins/management/src/main/java/resources/showVirtualHost.html
new file mode 100644
index 0000000000..9d16d523d6
--- /dev/null
+++ b/qpid/java/broker-plugins/management/src/main/java/resources/showVirtualHost.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+
+<div class="virtualhost">
+ <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span>
+ <br/>
+ <span style="">State:</span><span class="state" style="position:absolute; left:6em"></span>
+ <br/>
+ <span style="">Durable:</span><span class="durable" style="position:absolute; left:6em"></span>
+ <span style="position:absolute; left:26em">Inbound:</span>
+ <span class="msgInRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesInRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesInRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <span style="">Lifespan:</span><span style="position:absolute; left:6em" class="lifetimePolicy"></span>
+ <span style="position:absolute; left:26em">Outbound:</span>
+ <span class="msgOutRate" style="position:absolute; right:9.5em"></span>
+ <span style="position:absolute; right: 5em; width: 4em"> msg/s</span>
+ <span class="bytesOutRate" style="position:absolute; right: 3.3em"></span>
+ <span class="bytesOutRateUnits" style="position:absolute; right: 0em; width: 3em"></span>
+ <br/>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Exchanges'">
+ <div class="exchanges"></div>
+ <button data-dojo-type="dijit.form.Button" class="addExchangeButton">Add Exchange</button>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Queues'">
+ <div class="queues"></div>
+ <button data-dojo-type="dijit.form.Button" class="addQueueButton">Add Queue</button>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Connections'">
+ <div class="connections"></div>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Alerting Thresholds', open: false">
+ <span style="">Max. Queue Size:</span>
+ <span class="alertThresholdQueueDepthMessages"
+ style="position:absolute; left:8em; width:8em; text-align:right"></span>
+ <span style="position:absolute; left:16.2em">msgs</span>
+
+ <span class="alertThresholdQueueDepthBytes"
+ style="position:absolute; left:20em; width:8em; text-align:right"></span>
+ <span class="alertThresholdQueueDepthBytesUnits" style="position:absolute; left:28.2em"></span>
+ <br>
+ <span style="">Max. Message Age:</span>
+ <span class="alertThresholdMessageAge"
+ style="position:absolute; left:8em; width:8em; text-align:right"></span>
+ <span class="alertThresholdMessageAgeUnits" style="position:absolute; left:16.2em"></span>
+
+ <span style="position:absolute; left:21em">Size: </span>
+ <span class="alertThresholdMessageSize"
+ style="position:absolute; left:23em; width:5em; text-align:right"></span>
+ <span class="alertThresholdMessageSizeUnits" style="position:absolute; left:28.2em"></span>
+ <br/>
+ <br/>
+ <span style="">Alert frequency:</span>
+ <span class="alertRepeatGap"
+ style="position:absolute; left:8em; width:8em; text-align:right"></span>
+ <span class="alertRepeatGapUnits" style="position:absolute; left:16.2em"></span>
+ </div>
+</div>
+
diff --git a/qpid/java/broker-web/build.xml b/qpid/java/broker-web/build.xml
new file mode 100644
index 0000000000..fb747f50e3
--- /dev/null
+++ b/qpid/java/broker-web/build.xml
@@ -0,0 +1,107 @@
+<!--
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -->
+<project name="broker-web" xmlns:ivy="antlib:org.apache.ivy.ant" default="build">
+
+ <condition property="bdbstore" value="bdbstore" else="">
+ <contains string="${modules.opt}" substring="bdbstore"/>
+ </condition>
+
+ <import file="../common.xml"/>
+ <findSubProjects name="broker-plugins" dir="../broker-plugins"/>
+ <property name="module.depends" value="common management/common amqp-1-0-common broker ${bdbstore} ${broker-plugins}" />
+ <property name="module.test.depends" value="test client common/test broker/test management/common systests" />
+ <property name="module.genpom" value="true"/>
+
+ <import file="../module.xml"/>
+
+ <scriptdef name="string-replace" language="javascript">
+ <attribute name="string" />
+ <attribute name="token" />
+ <attribute name="value" />
+ <attribute name="property" />
+ <![CDATA[
+ var string = attributes.get("string");
+ var token = attributes.get("token");
+ var value = attributes.get("value");
+ project.setProperty(attributes.get("property"), string.replace(token, value));
+ ]]>
+ </scriptdef>
+
+ <!-- war is built as part of build task and stored in module release folder -->
+ <target name="postbuild" description="Create war" >
+
+ <property name="war.dir" value="../build/war"/>
+ <mkdir dir="${war.dir}/WEB-INF/lib"/>
+
+ <!-- copy third-party dependencies into WEB-INF/lib -->
+ <copy todir="${war.dir}/WEB-INF/lib" flatten="true">
+ <fileset dir="${project.root}" includes="${module.depends.libs}"
+ excludes="**/jetty-* **/*servlet*"/>
+ </copy>
+
+ <!-- copy qpid dependencies into WEB-INF/lib -->
+ <foreach property="dependency" list="${module.depends}">
+ <string-replace string="qpid-${dependency}" token="/" value="-" property="dependency.path"/>
+ <copy todir="${war.dir}/WEB-INF/lib">
+ <fileset dir="${project.root}/build/lib" includes="**/${dependency.path}*.jar"
+ excludes="*-tests-*.jar *-sources.jar *.osgi.jar"/>
+ </copy>
+ </foreach>
+
+ <!-- copy management jar into WEB-INF/lib in order to use servlets from it-->
+ <copy todir="${war.dir}/WEB-INF/lib">
+ <fileset dir="${project.root}/build/lib/plugins" includes="qpid-broker-plugins-management*.jar"/>
+ </copy>
+
+ <mkdir dir="${war.dir}/WEB-INF/etc"/>
+ <mkdir dir="${war.dir}/WEB-INF/work/log"/>
+
+ <!-- copy default broker configuration into /WEB-INF/etc-->
+ <copy todir="${war.dir}/WEB-INF/etc">
+ <fileset dir="${project.root}/broker/etc" excludes="config.xml virtualhosts.xml"/>
+ </copy>
+
+ <copy todir="${war.dir}/WEB-INF/etc">
+ <fileset dir="src/main/resources/WEB-INF/etc/"/>
+ </copy>
+
+ <!-- copy management.html into index.html -->
+ <copy tofile="${war.dir}/index.html"
+ file="../broker-plugins/management/src/main/java/resources/management.html"/>
+
+ <!-- extract dojo -->
+ <unwar src="${project.root}/${dojo}" dest="${war.dir}/dojo">
+ <patternset>
+ <exclude name="META-INF/**"/>
+ <exclude name="WEB-INF/**"/>
+ <exclude name="**/*.uncompressed.js"/>
+ </patternset>
+ </unwar>
+
+ <!-- build war -->
+ <war destfile="release/qpid.war" webxml="src/main/resources/WEB-INF/web.xml">
+ <lib file="${module.jar}"/>
+ <fileset dir="../broker-plugins/management/src/main/java/resources"/>
+ <fileset dir="${war.dir}"/>
+ </war>
+
+ <copy file="release/qpid.war" tofile="release/qpid-${project.version}.war"/>
+ </target>
+
+</project>
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/Managable.java b/qpid/java/broker-web/src/main/java/org/apache/qpid/web/listener/BrokerOptionsBuilder.java
index 166a2a376d..3d929826f2 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/Managable.java
+++ b/qpid/java/broker-web/src/main/java/org/apache/qpid/web/listener/BrokerOptionsBuilder.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,17 +18,19 @@
* under the License.
*
*/
-package org.apache.qpid.server.management;
+package org.apache.qpid.web.listener;
+
+import javax.servlet.ServletContext;
+
+import org.apache.qpid.server.BrokerOptions;
/**
- * Any object that can return a related MBean should implement this interface.
- *
- * This enables other classes to get the managed object, which in turn is useful when
- * constructing relationships between managed objects without having to maintain
- * separate data structures containing MBeans.
- *
+ * Defines operations to build {@link BrokerOptions} from {@link ServletContext}.
*/
-public interface Managable
+public interface BrokerOptionsBuilder
{
- ManagedObject getManagedObject();
+ /**
+ * Builds {@link BrokerOptions} from {@link ServletContext}.
+ */
+ BrokerOptions buildBrokerOptions(ServletContext context);
}
diff --git a/qpid/java/broker-web/src/main/java/org/apache/qpid/web/listener/InitParametersOptionsBuilder.java b/qpid/java/broker-web/src/main/java/org/apache/qpid/web/listener/InitParametersOptionsBuilder.java
new file mode 100644
index 0000000000..61c7b09b26
--- /dev/null
+++ b/qpid/java/broker-web/src/main/java/org/apache/qpid/web/listener/InitParametersOptionsBuilder.java
@@ -0,0 +1,314 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.web.listener;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import javax.servlet.ServletContext;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+
+import org.apache.qpid.server.BrokerOptions;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSOutput;
+import org.w3c.dom.ls.LSSerializer;
+
+/**
+ * Builder to build {@link BrokerOptions} from initialization parameters of servlet context.
+ * <p>
+ * The following init parameters are supported:
+ * <ul>
+ * <li>home, QPID_HOME setting
+ * <li>work, QPID_WORK setting
+ * <li>config, path to Qpid configuration file
+ * <li>logconfig, path to Qpid log configuration file
+ * <li>port, Qpid AMQP port
+ * <li>sslport, SSL port for AMQP
+ * <li>jmxregistryport, RMI port
+ * <li>jmxconnectorport, JMX connector port
+ * <li>bind, bind address
+ * <li>logwatch, log watch frequency
+ * </ul>
+ * <p>
+ * If parameters are not set then default configuration in WEB-INF/etc is used
+ * to start the broker
+ * <p>
+ * Examples of init configuration for web.xml
+ * <code>
+ * &lt;context-param&gt;
+ * &lt;param-name&gt;config&lt;/param-name&gt;
+ * &lt;param-value&gt;/home/user/qpid/etc/config.xml&lt;/param-value&gt;
+ * &lt;/context-param&gt;
+ *
+ * &lt;context-param&gt;
+ * &lt;param-name&gt;work&lt;/param-name&gt;
+ * &lt;param-value&gt;/home/user/qpid/work&lt;/param-value&gt;
+ * &lt;/context-param&gt;
+ *
+ * &lt;context-param&gt;
+ * &lt;param-name&gt;home&lt;/param-name&gt;
+ * &lt;param-value&gt;/home/user/qpid&lt;/param-value&gt;
+ * &lt;/context-param&gt;
+ *
+ * &lt;context-param&gt;
+ * &lt;param-name&gt;port&lt;/param-name&gt;
+ * &lt;param-value&gt;5671&lt;/param-value&gt;
+ * &lt;/context-param&gt;
+ * &lt;context-param&gt;
+ * &lt;param-name&gt;jmxregistryport&lt;/param-name&gt;
+ * &lt;param-value&gt;8998&lt;/param-value&gt;
+ * &lt;/context-param&gt;
+ * &lt;context-param&gt;
+ * &lt;param-name&gt;jmxconnectorport&lt;/param-name&gt;
+ * &lt;param-value&gt;9098&lt;/param-value&gt;
+ * &lt;/context-param&gt;
+ * </code>
+ */
+public class InitParametersOptionsBuilder implements BrokerOptionsBuilder
+{
+ private static final String INIT_PARAM_HOME_FOLDER = "home";
+
+ private static final String INIT_PARAM_WORK_FOLDER = "work";
+
+ private static final String INIT_PARAM_CONFIG_FILE = "config";
+
+ private static final String INIT_PARAM_LOG_CONFIG_FILE = "logconfig";
+
+ private static final String INIT_PARAM_PORT = "port";
+
+ private static final String INIT_PARAM_SSL_PORT = "sslport";
+
+ private static final String INIT_PARAM_JMX_PORT_REGISTRY_SERVER = "jmxregistryport";
+
+ private static final String INIT_PARAM_JMX_PORT_CONNECTOR_SERVER = "jmxconnectorport";
+
+ private static final String INIT_PARAM_BIND = "bind";
+
+ private static final String INIT_PARAM_LOG_WATCH = "logwatch";
+
+ @Override
+ public BrokerOptions buildBrokerOptions(ServletContext context)
+ {
+ BrokerOptions options = new BrokerOptions();
+
+ String homeFolder = context.getInitParameter(INIT_PARAM_HOME_FOLDER);
+ if (homeFolder == null)
+ {
+ homeFolder = context.getRealPath("/WEB-INF");
+ }
+ options.setQpidHome(homeFolder);
+
+ String workFolder = context.getInitParameter(INIT_PARAM_WORK_FOLDER);
+ if (workFolder == null)
+ {
+ workFolder = context.getRealPath("/WEB-INF/work");
+ }
+ options.setQpidWork(workFolder);
+
+ String configFile = context.getInitParameter(INIT_PARAM_CONFIG_FILE);
+ if (configFile == null)
+ {
+ configFile = context.getRealPath("/WEB-INF/" + BrokerOptions.DEFAULT_CONFIG_FILE);
+ }
+ options.setConfigFile(configFile);
+
+ String logConfig = context.getInitParameter(INIT_PARAM_LOG_CONFIG_FILE);
+ if (logConfig == null)
+ {
+ logConfig = createLogConfigurationFromTemplate(context);
+ }
+ options.setLogConfigFile(logConfig);
+
+ String port = context.getInitParameter(INIT_PARAM_PORT);
+ if (port != null)
+ {
+ int p = 0;
+ try
+ {
+ p = Integer.parseInt(port);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Cannot parse broker port. Please specify correct value for a port!");
+ }
+ options.addPort(p);
+ }
+ String sslport = context.getInitParameter(INIT_PARAM_SSL_PORT);
+ if (sslport != null)
+ {
+ int p = 0;
+ try
+ {
+ p = Integer.parseInt(sslport);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Cannot parse broker ssl port. Please specify correct value for ssl port!");
+ }
+ options.addSSLPort(p);
+ }
+ String jmxRegistryPort = context.getInitParameter(INIT_PARAM_JMX_PORT_REGISTRY_SERVER);
+ if (jmxRegistryPort != null)
+ {
+ int p = 0;
+ try
+ {
+ p = Integer.parseInt(jmxRegistryPort);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Cannot parse broker RMI port. Please specify correct value for RMI port!");
+ }
+ options.setJmxPortRegistryServer(p);
+ }
+ String jmxConnectorPort = context.getInitParameter(INIT_PARAM_JMX_PORT_CONNECTOR_SERVER);
+ if (jmxConnectorPort != null)
+ {
+ int p = 0;
+ try
+ {
+ p = Integer.parseInt(jmxConnectorPort);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Cannot parse broker JMX connector port."
+ + " Please specify correct value for JMX connector port!");
+ }
+ options.setJmxPortConnectorServer(p);
+ }
+ String logwatch = context.getInitParameter(INIT_PARAM_LOG_WATCH);
+ if (logwatch != null)
+ {
+ int logWatchFrequency = 0;
+ try
+ {
+ logWatchFrequency = Integer.parseInt(logwatch);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Cannot parse broker log watch frequency."
+ + " Please specify correct value for log watch frequency!");
+ }
+ options.setLogWatchFrequency(logWatchFrequency);
+ }
+ String bind = context.getInitParameter(INIT_PARAM_BIND);
+ if (bind != null)
+ {
+ options.setBind(bind);
+ }
+ return options;
+ }
+
+
+ /**
+ * Opens /WEB-INF/etc/log4j.xml, changes the location of the log file to
+ * "/WEB-INF/work/log/qpid.log" and stores log configuration in
+ * "/WEB-INF/work/log4j.xml"
+ */
+ private String createLogConfigurationFromTemplate(ServletContext context)
+ {
+ String webInfPath = context.getRealPath("/WEB-INF");
+ String template = webInfPath + "/" + BrokerOptions.DEFAULT_LOG_CONFIG_FILE;
+ String targetLogConfig = webInfPath + "/work/log4j.xml";
+ String logFile = webInfPath + "/work/log/${logprefix}qpid${logsuffix}.log";
+ transformLog(template, targetLogConfig, logFile);
+ return targetLogConfig;
+ }
+
+ private void transformLog(String template, String targetLogConfig, String logFile)
+ throws TransformerFactoryConfigurationError
+ {
+ Document document = null;
+ try
+ {
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ documentBuilderFactory.setAttribute("http://xml.org/sax/features/namespaces", true);
+ documentBuilderFactory.setAttribute("http://xml.org/sax/features/validation", false);
+ documentBuilderFactory.setAttribute("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
+ documentBuilderFactory.setAttribute("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+ documentBuilderFactory.setNamespaceAware(true);
+ documentBuilderFactory.setIgnoringElementContentWhitespace(false);
+ documentBuilderFactory.setIgnoringComments(false);
+ documentBuilderFactory.setValidating(false);
+
+ DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
+ document = builder.parse(new File(template));
+ NodeList parameters = document.getDocumentElement().getElementsByTagName("param");
+ for (int i = 0, l = parameters.getLength(); i < l; i++)
+ {
+ Node node = parameters.item(i);
+ if (node instanceof Element)
+ {
+ Element element = (Element) node;
+ String nameAttribute = element.getAttribute("name");
+ if (nameAttribute != null && nameAttribute.equalsIgnoreCase("file"))
+ {
+
+ element.setAttribute("value", logFile);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Cannot open log4j configuration at " + template, e);
+ }
+ FileWriter fileWriter = null;
+ try
+ {
+ fileWriter = new FileWriter(targetLogConfig);
+ DOMImplementationLS ls = (DOMImplementationLS) DOMImplementationRegistry.newInstance()
+ .getDOMImplementation("LS");
+ LSOutput lsout = ls.createLSOutput();
+ lsout.setCharacterStream(fileWriter);
+ lsout.setEncoding(document.getXmlEncoding());
+ LSSerializer serializer = ls.createLSSerializer();
+ serializer.write(document, lsout);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Cannot save log4j configuration at " + targetLogConfig, e);
+ }
+ finally
+ {
+ if (fileWriter != null)
+ {
+ try
+ {
+ fileWriter.close();
+ }
+ catch (IOException e)
+ {
+ // ignore this
+ }
+ }
+ }
+
+ }
+}
diff --git a/qpid/java/broker-web/src/main/java/org/apache/qpid/web/listener/QpidServletContextListener.java b/qpid/java/broker-web/src/main/java/org/apache/qpid/web/listener/QpidServletContextListener.java
new file mode 100644
index 0000000000..a8aa272c10
--- /dev/null
+++ b/qpid/java/broker-web/src/main/java/org/apache/qpid/web/listener/QpidServletContextListener.java
@@ -0,0 +1,162 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.web.listener;
+
+import java.util.Enumeration;
+import java.util.Properties;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.apache.commons.configuration.interpol.ConfigurationInterpolator;
+import org.apache.commons.lang.text.StrLookup;
+import org.apache.qpid.server.Broker;
+import org.apache.qpid.server.BrokerOptions;
+
+/**
+ * An implementation of {@link ServletContextListener} allowing to start Qpid
+ * broker in web container.
+ * <p>
+ * The listener instantiate {@link BrokerOptionsBuilder} specified in
+ * initialization parameter "broker-options-builder" and uses this builder to
+ * create {@link BrokerOptions} instance to start broker.
+ */
+public class QpidServletContextListener implements ServletContextListener
+{
+ private static final String INIT_PARAM_BROKER_OPTIONS_BUILDER = "broker-options-builder";
+
+ private Broker _broker;
+
+ @Override
+ public void contextDestroyed(ServletContextEvent event)
+ {
+ if (_broker != null)
+ {
+ _broker.shutdown();
+ }
+ }
+
+ @Override
+ public void contextInitialized(ServletContextEvent event)
+ {
+ ServletContext context = event.getServletContext();
+ BrokerOptions options = createBrokerOptions(context);
+ setConfigurationVariables(options, context);
+ startBroker(options);
+ }
+
+ /**
+ * Starts broker with given {@link BrokerOptions}.
+ */
+ private void startBroker(BrokerOptions options)
+ {
+ _broker = new Broker();
+ try
+ {
+ _broker.startup(options);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Broker cannot be started", e);
+ }
+ }
+
+ /**
+ * Sets resolver for QPID_HOME and QPID_WORK configuration variables and all
+ * context initialization parameters, so, they can be used in default
+ * configuration files.
+ */
+ private void setConfigurationVariables(BrokerOptions options, ServletContext context)
+ {
+ Properties properties = new Properties();
+ @SuppressWarnings("unchecked")
+ Enumeration<String> parameterNames = context.getInitParameterNames();
+ while (parameterNames.hasMoreElements())
+ {
+ String name = parameterNames.nextElement();
+ properties.put(name, context.getInitParameter(name));
+ }
+ properties.put(BrokerOptions.QPID_HOME, options.getQpidHome());
+ properties.put(BrokerOptions.QPID_WORK, options.getQpidWork());
+ PropertiesLookup lookup = new PropertiesLookup(properties);
+ ConfigurationInterpolator.registerGlobalLookup("web", lookup);
+ }
+
+ /**
+ * Creates {@link BrokerOptions} using initialization parameters of servlet
+ * context.
+ */
+ private BrokerOptions createBrokerOptions(final ServletContext context)
+ {
+ BrokerOptionsBuilder builder = null;
+ String builderClassName = context.getInitParameter(INIT_PARAM_BROKER_OPTIONS_BUILDER);
+ if (builderClassName != null)
+ {
+ Class<?> builderClass = null;
+ try
+ {
+ builderClass = Class.forName(builderClassName);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new RuntimeException("Invalid options builder class " + builderClassName + " is specified", e);
+ }
+ try
+ {
+ builder = (BrokerOptionsBuilder) builderClass.newInstance();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Cannot instantiate options builder", e);
+ }
+ }
+ else
+ {
+ builder = new InitParametersOptionsBuilder();
+ }
+ return builder.buildBrokerOptions(context);
+ }
+
+ /**
+ * A variable resolver to resolve variables set in given {@link Properties}.
+ * <p>
+ * It is used to resolve "QPID_HOME" and "QPID_WORK" and servlet context
+ * init parameters.
+ */
+ private static class PropertiesLookup extends StrLookup
+ {
+ private Properties _properties;
+
+ private PropertiesLookup(Properties properties)
+ {
+ _properties = properties;
+ }
+
+ @Override
+ public String lookup(String varName)
+ {
+ return _properties.getProperty(varName);
+ }
+
+ }
+
+}
diff --git a/qpid/java/broker-web/src/main/resources/WEB-INF/etc/config.xml b/qpid/java/broker-web/src/main/resources/WEB-INF/etc/config.xml
new file mode 100644
index 0000000000..3cd0b44f4f
--- /dev/null
+++ b/qpid/java/broker-web/src/main/resources/WEB-INF/etc/config.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<broker>
+ <prefix>${web:QPID_HOME}</prefix>
+ <work>${web:QPID_WORK}</work>
+ <conf>${prefix}/etc</conf>
+
+ <plugin-directory>${web:QPID_HOME}/lib/plugins</plugin-directory>
+ <cache-directory>${web:QPID_WORK}/cache</cache-directory>
+
+ <connector>
+ <!-- To enable SSL edit the keystorePath and keystorePassword
+ and set enabled to true.
+ To disable Non-SSL port set sslOnly to true -->
+ <ssl>
+ <enabled>false</enabled>
+ <port>5671</port>
+ <sslOnly>false</sslOnly>
+ <keyStorePath>/path/to/keystore.ks</keyStorePath>
+ <keyStorePassword>keystorepass</keyStorePassword>
+ </ssl>
+ <port>5672</port>
+ <socketReceiveBuffer>262144</socketReceiveBuffer>
+ <socketSendBuffer>262144</socketSendBuffer>
+ </connector>
+ <management>
+ <enabled>false</enabled>
+ <platform-mbeanserver>false</platform-mbeanserver>
+ <http>
+ <enabled>false</enabled>
+ </http>
+ <jmxport>
+ <registryServer>8999</registryServer>
+ <!--
+ If unspecified, connectorServer defaults to 100 + registryServer port.
+ <connectorServer>9099</connectionServer>
+ -->
+ </jmxport>
+ <ssl>
+ <enabled>false</enabled>
+ <!-- Update below path to your keystore location. -->
+ <keyStorePath>${conf}/qpid.keystore</keyStorePath>
+ <keyStorePassword>password</keyStorePassword>
+ </ssl>
+ </management>
+ <advanced>
+ <framesize>65535</framesize>
+ <locale>en_US</locale>
+ </advanced>
+
+ <security>
+ <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>
+
+ <!-- By default, all authenticated users have permissions to perform all actions -->
+
+ <!-- ACL Example
+ This example illustrates securing the both Management (JMX) and Messaging.
+ <acl>${conf}/broker_example.acl</acl>
+ -->
+
+ <msg-auth>false</msg-auth>
+ </security>
+
+ <virtualhosts>${conf}/virtualhosts.xml</virtualhosts>
+
+ <heartbeat>
+ <delay>0</delay>
+ <timeoutFactor>2.0</timeoutFactor>
+ </heartbeat>
+ <queue>
+ <auto_register>true</auto_register>
+ </queue>
+
+ <status-updates>ON</status-updates>
+
+</broker>
+
+
diff --git a/qpid/java/broker-web/src/main/resources/WEB-INF/etc/virtualhosts.xml b/qpid/java/broker-web/src/main/resources/WEB-INF/etc/virtualhosts.xml
new file mode 100644
index 0000000000..44d9154f03
--- /dev/null
+++ b/qpid/java/broker-web/src/main/resources/WEB-INF/etc/virtualhosts.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<virtualhosts>
+ <default>test</default>
+ <virtualhost>
+ <name>localhost</name>
+ <localhost>
+ <store>
+ <class>org.apache.qpid.server.store.derby.DerbyMessageStore</class>
+ <environment-path>${web:QPID_WORK}/derbystore</environment-path>
+ </store>
+
+ <housekeeping>
+ <threadCount>2</threadCount>
+ <checkPeriod>20000</checkPeriod>
+ </housekeeping>
+
+ <exchanges>
+ <exchange>
+ <type>direct</type>
+ <name>test.direct</name>
+ <durable>true</durable>
+ </exchange>
+ <exchange>
+ <type>topic</type>
+ <name>test.topic</name>
+ </exchange>
+ </exchanges>
+ <queues>
+ <exchange>amq.direct</exchange>
+ <maximumQueueDepth>4235264</maximumQueueDepth>
+ <!-- 4Mb -->
+ <maximumMessageSize>2117632</maximumMessageSize>
+ <!-- 2Mb -->
+ <maximumMessageAge>600000</maximumMessageAge>
+ <!-- 10 mins -->
+ <maximumMessageCount>50</maximumMessageCount>
+ <!-- 50 messages -->
+
+ <queue>
+ <name>queue</name>
+ </queue>
+ <queue>
+ <name>ping</name>
+ </queue>
+ <queue>
+ <name>test-queue</name>
+ <test-queue>
+ <exchange>test.direct</exchange>
+ <durable>true</durable>
+ </test-queue>
+ </queue>
+ <queue>
+ <name>test-ping</name>
+ <test-ping>
+ <exchange>test.direct</exchange>
+ </test-ping>
+ </queue>
+
+ </queues>
+ </localhost>
+ </virtualhost>
+
+
+ <virtualhost>
+ <name>development</name>
+ <development>
+ <store>
+ <class>org.apache.qpid.server.store.derby.DerbyMessageStore</class>
+ <environment-path>${web:QPID_WORK}/derbystore</environment-path>
+ </store>
+
+ <queues>
+ <minimumAlertRepeatGap>30000</minimumAlertRepeatGap>
+ <maximumMessageCount>50</maximumMessageCount>
+ <queue>
+ <name>queue</name>
+ <queue>
+ <exchange>amq.direct</exchange>
+ <maximumQueueDepth>4235264</maximumQueueDepth>
+ <!-- 4Mb -->
+ <maximumMessageSize>2117632</maximumMessageSize>
+ <!-- 2Mb -->
+ <maximumMessageAge>600000</maximumMessageAge>
+ <!-- 10 mins -->
+ </queue>
+ </queue>
+ <queue>
+ <name>ping</name>
+ <ping>
+ <exchange>amq.direct</exchange>
+ <maximumQueueDepth>4235264</maximumQueueDepth>
+ <!-- 4Mb -->
+ <maximumMessageSize>2117632</maximumMessageSize>
+ <!-- 2Mb -->
+ <maximumMessageAge>600000</maximumMessageAge>
+ <!-- 10 mins -->
+ </ping>
+ </queue>
+ </queues>
+ </development>
+ </virtualhost>
+ <virtualhost>
+ <name>test</name>
+ <test>
+ <store>
+ <class>org.apache.qpid.server.store.derby.DerbyMessageStore</class>
+ <environment-path>${web:QPID_WORK}/derbystore</environment-path>
+ </store>
+
+ <queues>
+ <minimumAlertRepeatGap>30000</minimumAlertRepeatGap>
+ <maximumMessageCount>50</maximumMessageCount>
+ <queue>
+ <name>queue</name>
+ <queue>
+ <exchange>amq.direct</exchange>
+ <maximumQueueDepth>4235264</maximumQueueDepth>
+ <!-- 4Mb -->
+ <maximumMessageSize>2117632</maximumMessageSize>
+ <!-- 2Mb -->
+ <maximumMessageAge>600000</maximumMessageAge>
+ <!-- 10 mins -->
+ </queue>
+ </queue>
+ <queue>
+ <name>ping</name>
+ <ping>
+ <exchange>amq.direct</exchange>
+ <maximumQueueDepth>4235264</maximumQueueDepth>
+ <!-- 4Mb -->
+ <maximumMessageSize>2117632</maximumMessageSize>
+ <!-- 2Mb -->
+ <maximumMessageAge>600000</maximumMessageAge>
+ <!-- 10 mins -->
+ </ping>
+ </queue>
+ </queues>
+ </test>
+ </virtualhost>
+</virtualhosts>
+
+
diff --git a/qpid/java/broker-web/src/main/resources/WEB-INF/web.xml b/qpid/java/broker-web/src/main/resources/WEB-INF/web.xml
new file mode 100644
index 0000000000..42322ceaa3
--- /dev/null
+++ b/qpid/java/broker-web/src/main/resources/WEB-INF/web.xml
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -->
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+ <session-config><!-- 10 minutes -->
+ <session-timeout>10</session-timeout>
+ </session-config>
+
+ <servlet>
+ <display-name>VhostsServlet</display-name>
+ <servlet-name>VhostsServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.api.VhostsServlet</servlet-class>
+ </servlet>
+
+ <servlet>
+ <display-name>ExchangesServlet</display-name>
+ <servlet-name>ExchangesServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.api.ExchangesServlet</servlet-class>
+ </servlet>
+
+ <servlet>
+ <display-name>BrokerRestServlet</display-name>
+ <servlet-name>BrokerRestServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.RestServlet</servlet-class>
+ </servlet>
+
+ <servlet>
+ <display-name>VirtualHostRestServlet</display-name>
+ <servlet-name>VirtualHostRestServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.RestServlet</servlet-class>
+ <init-param>
+ <param-name>hierarchy</param-name>
+ <param-value>VirtualHost</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <display-name>AuthenticationProviderRestServlet</display-name>
+ <servlet-name>AuthenticationProviderRestServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.RestServlet</servlet-class>
+ <init-param>
+ <param-name>hierarchy</param-name>
+ <param-value>AuthenticationProvider</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <display-name>UserRestServlet</display-name>
+ <servlet-name>UserRestServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.RestServlet</servlet-class>
+ <init-param>
+ <param-name>hierarchy</param-name>
+ <param-value>AuthenticationProvider,User</param-value>
+ </init-param>
+ </servlet>
+
+
+ <servlet>
+ <display-name>ExchangeRestServlet</display-name>
+ <servlet-name>ExchangeRestServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.RestServlet</servlet-class>
+ <init-param>
+ <param-name>hierarchy</param-name>
+ <param-value>VirtualHost,Exchange</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <display-name>QueueRestServlet</display-name>
+ <servlet-name>QueueRestServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.RestServlet</servlet-class>
+ <init-param>
+ <param-name>hierarchy</param-name>
+ <param-value>VirtualHost,Queue</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <display-name>ConnectionRestServlet</display-name>
+ <servlet-name>ConnectionRestServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.RestServlet</servlet-class>
+ <init-param>
+ <param-name>hierarchy</param-name>
+ <param-value>VirtualHost,Connection</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <display-name>BindingRestServlet</display-name>
+ <servlet-name>BindingRestServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.RestServlet</servlet-class>
+ <init-param>
+ <param-name>hierarchy</param-name>
+ <param-value>VirtualHost,Exchange,Queue,Binding</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <display-name>PortRestServlet</display-name>
+ <servlet-name>PortRestServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.RestServlet</servlet-class>
+ <init-param>
+ <param-name>hierarchy</param-name>
+ <param-value>Port</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <display-name>SessionRestServlet</display-name>
+ <servlet-name>SessionRestServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.RestServlet</servlet-class>
+ <init-param>
+ <param-name>hierarchy</param-name>
+ <param-value>VirtualHost,Connection,Session</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <display-name>StructureServlet</display-name>
+ <servlet-name>StructureServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.StructureServlet</servlet-class>
+ </servlet>
+
+ <servlet>
+ <display-name>MessageServlet</display-name>
+ <servlet-name>MessageServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.MessageServlet</servlet-class>
+ </servlet>
+
+ <servlet>
+ <display-name>MessageContentServlet</display-name>
+ <servlet-name>MessageContentServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.MessageContentServlet</servlet-class>
+ </servlet>
+
+ <servlet>
+ <display-name>LogRecordsServlet</display-name>
+ <servlet-name>LogRecordsServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.LogRecordsServlet</servlet-class>
+ </servlet>
+
+ <servlet>
+ <display-name>SaslServlet</display-name>
+ <servlet-name>SaslServlet</servlet-name>
+ <servlet-class>org.apache.qpid.server.management.plugin.servlet.rest.SaslServlet</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>VhostsServlet</servlet-name>
+ <url-pattern>/api/vhosts/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>ExchangesServlet</servlet-name>
+ <url-pattern>/api/exchanges/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>BrokerRestServlet</servlet-name>
+ <url-pattern>/rest/broker/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>VirtualHostRestServlet</servlet-name>
+ <url-pattern>/rest/virtualhost/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>AuthenticationProviderRestServlet</servlet-name>
+ <url-pattern>/rest/authenticationprovider/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>UserRestServlet</servlet-name>
+ <url-pattern>/rest/user/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>ExchangeRestServlet</servlet-name>
+ <url-pattern>/rest/exchange/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>QueueRestServlet</servlet-name>
+ <url-pattern>/rest/queue/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>ConnectionRestServlet</servlet-name>
+ <url-pattern>/rest/connection/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>BindingRestServlet</servlet-name>
+ <url-pattern>/rest/binding/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>PortRestServlet</servlet-name>
+ <url-pattern>/rest/port/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>SessionRestServlet</servlet-name>
+ <url-pattern>/rest/session/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>StructureServlet</servlet-name>
+ <url-pattern>/rest/structure</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>MessageServlet</servlet-name>
+ <url-pattern>/rest/message/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>MessageContentServlet</servlet-name>
+ <url-pattern>/rest/message-content/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>LogRecordsServlet</servlet-name>
+ <url-pattern>/rest/logrecords</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>SaslServlet</servlet-name>
+ <url-pattern>/rest/sasl</url-pattern>
+ </servlet-mapping>
+
+ <listener>
+ <listener-class>org.apache.qpid.web.listener.QpidServletContextListener</listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ <welcome-file>management.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/qpid/java/broker/etc/broker_example.acl b/qpid/java/broker/etc/broker_example.acl
index aae4ee3162..1f32f8463e 100644
--- a/qpid/java/broker/etc/broker_example.acl
+++ b/qpid/java/broker/etc/broker_example.acl
@@ -24,6 +24,8 @@
#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
### MANAGEMENT ####
@@ -74,6 +76,23 @@ 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
diff --git a/qpid/java/broker/etc/config.xml b/qpid/java/broker/etc/config.xml
index e1aacd43b5..3bf8e1afa3 100644
--- a/qpid/java/broker/etc/config.xml
+++ b/qpid/java/broker/etc/config.xml
@@ -43,7 +43,7 @@
<socketSendBuffer>262144</socketSendBuffer>
</connector>
<management>
- <enabled>true</enabled>
+ <enabled>false</enabled>
<jmxport>
<registryServer>8999</registryServer>
<!--
diff --git a/qpid/java/broker/etc/log4j.xml b/qpid/java/broker/etc/log4j.xml
index 7dbb1bc87d..b881539a52 100644
--- a/qpid/java/broker/etc/log4j.xml
+++ b/qpid/java/broker/etc/log4j.xml
@@ -87,10 +87,6 @@
</layout>
</appender>
- <category additivity="true" name="org.apache.qpid.server.queue.AMQQueueMBean">
- <priority value="info"/>
- </category>
-
<!-- Provide warnings to standard output -->
<category additivity="true" name="org.apache.qpid">
<priority value="warn"/>
@@ -101,8 +97,6 @@
<level value="info"/>
</logger>
-
-
<!-- Examples of additional logging settings -->
<!-- Used to generate extra debug. See debug.log4j.xml -->
diff --git a/qpid/java/broker/etc/passwd b/qpid/java/broker/etc/passwd
index 99f0f05c6a..f0dcb80f25 100644
--- a/qpid/java/broker/etc/passwd
+++ b/qpid/java/broker/etc/passwd
@@ -21,3 +21,5 @@ client:guest
server:guest
admin:admin
+webadmin:webadmin
+
diff --git a/qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java b/qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java
index dca62f34b4..79bedb2a7e 100644
--- a/qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java
+++ b/qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java
@@ -26,8 +26,6 @@ import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
-import org.apache.qpid.server.logging.management.LoggingManagementMBean;
-
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -65,7 +63,6 @@ public class QpidLog4JConfigurator
LOCK.lock();
parseXMLConfigFile(filename);
- checkLoggerLevels(filename);
DOMConfigurator.configure(filename);
@@ -84,7 +81,6 @@ public class QpidLog4JConfigurator
SAXException, IllegalLoggerLevelException
{
parseXMLConfigFile(filename);
- checkLoggerLevels(filename);
QpidLog4JXMLWatchdog watchdog = new QpidLog4JXMLWatchdog(filename);
watchdog.setDelay(delay);
@@ -200,23 +196,6 @@ public class QpidLog4JConfigurator
return;
}
- try
- {
- checkLoggerLevels(filename);
- }
- catch (Exception e)
- {
- //logger will be instantiated following first configuration success, which has been pre-validated
- //and so the null check should never actually be required.
- if(_logger != null)
- {
- _logger.warn("Errors were found when validating the logger level values in the " +
- "log4j XML configuration file. The new configuration was not applied. " +
- "Correct the issues to prompt another update attempt: " + e.getMessage());
- }
- return;
- }
-
//everything checked was ok, let the normal update process proceed
super.doOnChange();
@@ -235,60 +214,7 @@ public class QpidLog4JConfigurator
}
}
-
- protected static void checkLoggerLevels(String filename) throws IllegalLoggerLevelException, IOException
- {
- //check that the logger levels specified in the XML are actually valid
- try
- {
- LOCK.lock();
-
- //get the Logger levels to check
- Map<String, String> loggersLevels;
- loggersLevels = LoggingManagementMBean.retrieveConfigFileLoggersLevels(filename);
- //add the RootLogger to the list too
- String rootLoggerlevelString = LoggingManagementMBean.retrieveConfigFileRootLoggerLevel(filename);
- loggersLevels.put("Root", rootLoggerlevelString);
-
-
- for (Map.Entry<String, String> entry : loggersLevels.entrySet())
- {
- String loggerName = entry.getKey();
- String levelString = entry.getValue();
-
- //let log4j replace any properties in the string
- String log4jConfiguredString = domConfig.subst(levelString);
-
- if(log4jConfiguredString.equals("") && ! log4jConfiguredString.equals(levelString))
- {
- //log4j has returned an empty string but this isnt what we gave it.
- //There may have been an undefined property. Unlike an incorrect
- //literal value, we will allow this case to proceed, but warn users.
-
- if(_logger != null)
- {
- _logger.warn("Unable to detect Level value from '" + levelString
- +"' for logger '" + loggerName + "', Log4J will default this to DEBUG");
- }
- else
- {
- System.err.println("Unable to detect Level value from '" + levelString
- +"' for logger " + loggerName + ", Log4J will default this to DEBUG");
- }
-
- continue;
- }
-
- checkLevel(loggerName,log4jConfiguredString);
- }
- }
- finally
- {
- LOCK.unlock();
- }
- }
-
private static void checkLevel(String loggerName, String levelString) throws IllegalLoggerLevelException
{
if("null".equalsIgnoreCase(levelString) || "inherited".equalsIgnoreCase(levelString))
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java
index 034a4ae53c..0d48aec562 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java
@@ -540,6 +540,11 @@ public class ManagementExchange implements Exchange, QMFService.Listener
return getMsgReceives();
}
+ public long getMsgDrops()
+ {
+ return 0l;
+ }
+
public long getByteReceives()
{
return _bytesReceived.get();
@@ -550,6 +555,11 @@ public class ManagementExchange implements Exchange, QMFService.Listener
return getByteReceives();
}
+ public long getByteDrops()
+ {
+ return 0l;
+ }
+
public long getCreateTime()
{
return _createTime;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java
index 787cede2b7..1b173c7e11 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java
@@ -21,6 +21,8 @@
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;
@@ -111,6 +113,16 @@ public class QMFMessage implements ServerMessage, InboundMessage, AMQMessageHead
return 0;
}
+ public String getUserId()
+ {
+ return null;
+ }
+
+ public String getAppId()
+ {
+ return null;
+ }
+
public String getMessageId()
{
return null;
@@ -166,6 +178,12 @@ public class QMFMessage implements ServerMessage, InboundMessage, AMQMessageHead
return false;
}
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ return Collections.EMPTY_SET;
+ }
+
public boolean containsHeader(String name)
{
return false;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
deleted file mode 100644
index 0f32b98aa8..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.qpid.server;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-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.exchange.ExchangeType;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.ManagementActor;
-import org.apache.qpid.server.management.AMQManagedObject;
-import org.apache.qpid.server.management.ManagedObject;
-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.queue.AMQQueueMBean;
-import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.virtualhost.VirtualHostImpl;
-
-import javax.management.JMException;
-import javax.management.MBeanException;
-import javax.management.MalformedObjectNameException;
-import javax.management.ObjectName;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-/**
- * This MBean implements the broker management interface and exposes the
- * Broker level management features like creating and deleting exchanges and queue.
- */
-@MBeanDescription("This MBean exposes the broker level management features")
-public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBroker
-{
- private final QueueRegistry _queueRegistry;
- private final ExchangeRegistry _exchangeRegistry;
- private final ExchangeFactory _exchangeFactory;
-
- private final VirtualHostImpl.VirtualHostMBean _virtualHostMBean;
-
- @MBeanConstructor("Creates the Broker Manager MBean")
- public AMQBrokerManagerMBean(VirtualHostImpl.VirtualHostMBean virtualHostMBean) throws JMException
- {
- super(ManagedBroker.class, ManagedBroker.TYPE);
-
- _virtualHostMBean = virtualHostMBean;
- VirtualHost virtualHost = virtualHostMBean.getVirtualHost();
-
- _queueRegistry = virtualHost.getQueueRegistry();
- _exchangeRegistry = virtualHost.getExchangeRegistry();
- _exchangeFactory = virtualHost.getExchangeFactory();
- }
-
- public String getObjectInstanceName()
- {
- return _virtualHostMBean.getVirtualHost().getName();
- }
-
- /**
- * Returns an array of the exchange types available for creation.
- * @since Qpid JMX API 1.3
- * @throws IOException
- */
- public String[] getExchangeTypes() throws IOException
- {
- ArrayList<String> exchangeTypes = new ArrayList<String>();
- for(ExchangeType<? extends Exchange> ex : _exchangeFactory.getPublicCreatableTypes())
- {
- exchangeTypes.add(ex.getName().toString());
- }
-
- return exchangeTypes.toArray(new String[0]);
- }
-
- /**
- * Returns a list containing the names of the attributes available for the Queue mbeans.
- * @since Qpid JMX API 1.3
- * @throws IOException
- */
- public List<String> retrieveQueueAttributeNames() throws IOException
- {
- return ManagedQueue.QUEUE_ATTRIBUTES;
- }
-
- /**
- * Returns a List of Object Lists containing the requested attribute values (in the same sequence requested) for each queue in the virtualhost.
- * If a particular attribute cant be found or raises an mbean/reflection exception whilst being gathered its value is substituted with the String "-".
- * @since Qpid JMX API 1.3
- * @throws IOException
- */
- public List<List<Object>> retrieveQueueAttributeValues(String[] attributes) throws IOException
- {
- if(_queueRegistry.getQueues().size() == 0)
- {
- return new ArrayList<List<Object>>();
- }
-
- List<List<Object>> queueAttributesList = new ArrayList<List<Object>>(_queueRegistry.getQueues().size());
-
- int attributesLength = attributes.length;
-
- for(AMQQueue queue : _queueRegistry.getQueues())
- {
- AMQQueueMBean mbean = (AMQQueueMBean) queue.getManagedObject();
-
- if(mbean == null)
- {
- continue;
- }
-
- List<Object> attributeValues = new ArrayList<Object>(attributesLength);
-
- for(int i=0; i < attributesLength; i++)
- {
- try
- {
- attributeValues.add(mbean.getAttribute(attributes[i]));
- }
- catch (Exception e)
- {
- attributeValues.add("-");
- }
- }
-
- queueAttributesList.add(attributeValues);
- }
-
- return queueAttributesList;
- }
-
- /**
- * Creates new exchange and registers it with the registry.
- *
- * @param exchangeName
- * @param type
- * @param durable
- * @throws JMException
- * @throws MBeanException
- */
- public void createNewExchange(String exchangeName, String type, boolean durable) throws JMException, MBeanException
- {
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- synchronized (_exchangeRegistry)
- {
- Exchange exchange = _exchangeRegistry.getExchange(new AMQShortString(exchangeName));
- if (exchange == null)
- {
- exchange = _exchangeFactory.createExchange(new AMQShortString(exchangeName),
- new AMQShortString(type), durable, false, 0);
- _exchangeRegistry.registerExchange(exchange);
- if (durable)
- {
- getVirtualHost().getMessageStore().createExchange(exchange);
- }
- }
- else
- {
- throw new JMException("The exchange \"" + exchangeName + "\" already exists.");
- }
- }
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error in creating exchange " + exchangeName);
- }
- finally
- {
- CurrentActor.remove();
- }
- }
-
- /**
- * Unregisters the exchange from registry.
- *
- * @param exchangeName
- * @throws JMException
- * @throws MBeanException
- */
- public void unregisterExchange(String exchangeName) throws JMException, MBeanException
- {
- // TODO
- // Check if the exchange is in use.
-
- // Check if there are queue-bindings with the exchange and unregister
- // when there are no bindings.
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- _exchangeRegistry.unregisterExchange(new AMQShortString(exchangeName), false);
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error in unregistering exchange " + exchangeName);
- }
- finally
- {
- CurrentActor.remove();
- }
- }
-
- /**
- * Creates a new queue and registers it with the registry and puts it
- * in persistance storage if durable queue.
- *
- * @param queueName
- * @param durable
- * @param owner
- * @throws JMException
- * @throws MBeanException
- */
- public void createNewQueue(String queueName, String owner, boolean durable) throws JMException, MBeanException
- {
- createNewQueue(queueName, owner, durable, null);
- }
-
- public void createNewQueue(String queueName, String owner, boolean durable, Map<String,Object> arguments) throws JMException
- {
- final AMQShortString queueNameAsAMQShortString = new AMQShortString(queueName);
- synchronized (_queueRegistry)
- {
- AMQQueue queue = _queueRegistry.getQueue(queueNameAsAMQShortString);
- if (queue != null)
- {
- throw new JMException("The queue \"" + queueName + "\" already exists.");
- }
-
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- FieldTable args = null;
- if(arguments != null)
- {
- args = FieldTable.convertToFieldTable(arguments);
- }
- final VirtualHost virtualHost = getVirtualHost();
-
- queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateUUID(), queueName, durable, owner,
- false, false, getVirtualHost(), arguments);
- if (queue.isDurable() && !queue.isAutoDelete())
- {
- getVirtualHost().getMessageStore().createQueue(queue, args);
- }
-
- virtualHost.getBindingFactory().addBinding(queueName, queue, _exchangeRegistry.getDefaultExchange(), null);
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error in creating queue " + queueName);
- }
- finally
- {
- CurrentActor.remove();
- }
- }
- }
-
- private VirtualHost getVirtualHost()
- {
- return _virtualHostMBean.getVirtualHost();
- }
-
- /**
- * Deletes the queue from queue registry and persistant storage.
- *
- * @param queueName
- * @throws JMException
- * @throws MBeanException
- */
- public void deleteQueue(String queueName) throws JMException, MBeanException
- {
- AMQQueue queue = _queueRegistry.getQueue(new AMQShortString(queueName));
- if (queue == null)
- {
- throw new JMException("The Queue " + queueName + " is not a registered queue.");
- }
-
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- queue.delete();
- if (queue.isDurable())
- {
- getVirtualHost().getMessageStore().removeQueue(queue);
- }
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error in deleting queue " + queueName);
- }
- finally
- {
- CurrentActor.remove();
- }
- }
-
- @Override
- public ManagedObject getParentObject()
- {
- return _virtualHostMBean;
- }
-
- // This will have a single instance for a virtual host, so not having the name property in the ObjectName
- @Override
- public ObjectName getObjectName() throws MalformedObjectNameException
- {
- return getObjectNameForSingleInstanceMBean();
- }
-
- public void resetStatistics() throws Exception
- {
- getVirtualHost().resetStatistics();
- }
-
- public double getPeakMessageDeliveryRate()
- {
- return getVirtualHost().getMessageDeliveryStatistics().getPeak();
- }
-
- public double getPeakDataDeliveryRate()
- {
- return getVirtualHost().getDataDeliveryStatistics().getPeak();
- }
-
- public double getMessageDeliveryRate()
- {
- return getVirtualHost().getMessageDeliveryStatistics().getRate();
- }
-
- public double getDataDeliveryRate()
- {
- return getVirtualHost().getDataDeliveryStatistics().getRate();
- }
-
- public long getTotalMessagesDelivered()
- {
- return getVirtualHost().getMessageDeliveryStatistics().getTotal();
- }
-
- public long getTotalDataDelivered()
- {
- return getVirtualHost().getDataDeliveryStatistics().getTotal();
- }
-
- public double getPeakMessageReceiptRate()
- {
- return getVirtualHost().getMessageReceiptStatistics().getPeak();
- }
-
- public double getPeakDataReceiptRate()
- {
- return getVirtualHost().getDataReceiptStatistics().getPeak();
- }
-
- public double getMessageReceiptRate()
- {
- return getVirtualHost().getMessageReceiptStatistics().getRate();
- }
-
- public double getDataReceiptRate()
- {
- return getVirtualHost().getDataReceiptStatistics().getRate();
- }
-
- public long getTotalMessagesReceived()
- {
- return getVirtualHost().getMessageReceiptStatistics().getTotal();
- }
-
- public long getTotalDataReceived()
- {
- return getVirtualHost().getDataReceiptStatistics().getTotal();
- }
-
- public boolean isStatisticsEnabled()
- {
- return getVirtualHost().isStatisticsEnabled();
- }
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
index 4fd4e02220..819fe1f0e7 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
@@ -140,7 +140,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
private UnacknowledgedMessageMap _unacknowledgedMessageMap = new UnacknowledgedMessageMapImpl(DEFAULT_PREFETCH);
- // Set of messages being acknoweledged in the current transaction
+ // Set of messages being acknowledged in the current transaction
private SortedSet<QueueEntry> _acknowledgedMessages = new TreeSet<QueueEntry>();
private final AtomicBoolean _suspended = new AtomicBoolean(false);
@@ -263,6 +263,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
return _txnCount.get();
}
+ public Long getTxnStart()
+ {
+ return _txnStarts.get();
+ }
+
public int getChannelId()
{
return _channelId;
@@ -440,7 +445,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
* @param acks Are acks enabled for this subscriber
* @param filters Filters to apply to this subscriber
*
- * @param noLocal Flag stopping own messages being receivied.
+ * @param noLocal Flag stopping own messages being received.
* @param exclusive Flag requesting exclusive access to the queue
* @return the consumer tag. This is returned to the subscriber and used in subsequent unsubscribe requests
*
@@ -1417,6 +1422,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
return false;
}
+ public int getUnacknowledgedMessageCount()
+ {
+ return getUnacknowledgedMessageMap().size();
+ }
+
private void flow(boolean flow)
{
MethodRegistry methodRegistry = _session.getMethodRegistry();
@@ -1424,6 +1434,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
_session.writeFrame(responseBody.generateFrame(_channelId));
}
+ @Override
public boolean getBlocking()
{
return _blocking.get();
@@ -1587,7 +1598,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
_unfinishedCommandsQueue.add(new AsyncCommand(future, action));
}
- public void completeAsyncCommands()
+ public boolean completeAsyncCommands()
{
AsyncCommand cmd;
while((cmd = _unfinishedCommandsQueue.peek()) != null && cmd.isReadyForCompletion())
@@ -1601,6 +1612,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm
cmd.awaitReadyForCompletion();
cmd.complete();
}
+ return _unfinishedCommandsQueue.isEmpty();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java
index 90603777d1..c843ce6a23 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java
@@ -25,24 +25,17 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Properties;
-import java.util.Set;
+import java.util.*;
import javax.net.ssl.SSLContext;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.QpidLog4JConfigurator;
import org.apache.qpid.server.configuration.ServerConfiguration;
import org.apache.qpid.server.configuration.ServerNetworkTransportConfiguration;
-import org.apache.qpid.server.configuration.management.ConfigurationManagementMBean;
-import org.apache.qpid.server.information.management.ServerInformationMBean;
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.management.LoggingManagementMBean;
import org.apache.qpid.server.logging.messages.BrokerMessages;
import org.apache.qpid.server.protocol.AmqpProtocolVersion;
import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory;
@@ -118,6 +111,14 @@ public class Broker
ConfigurationFileApplicationRegistry config = new ConfigurationFileApplicationRegistry(configFile, options.getBundleContext());
ServerConfiguration serverConfig = config.getConfiguration();
+ if (options.getQpidWork() != null)
+ {
+ serverConfig.setQpidWork(options.getQpidWork());
+ }
+ if (options.getQpidHome() != null)
+ {
+ serverConfig.setQpidHome(options.getQpidHome());
+ }
updateManagementPorts(serverConfig, options.getJmxPortRegistryServer(), options.getJmxPortConnectorServer());
ApplicationRegistry.initialise(config);
@@ -135,14 +136,6 @@ public class Broker
try
{
- configureLoggingManagementMBean(logConfigFile, options.getLogWatchFrequency());
-
- ConfigurationManagementMBean configMBean = new ConfigurationManagementMBean();
- configMBean.register();
-
- ServerInformationMBean sysInfoMBean = new ServerInformationMBean(config);
- sysInfoMBean.register();
-
Set<Integer> ports = new HashSet<Integer>(options.getPorts());
if(ports.isEmpty())
{
@@ -258,7 +251,7 @@ public class Broker
transport.accept(settings, protocolEngineFactory, null);
ApplicationRegistry.getInstance().addAcceptor(inetSocketAddress,
- new QpidAcceptor(transport,"TCP"));
+ new QpidAcceptor(transport,QpidAcceptor.Transport.TCP, supported));
CurrentActor.get().message(BrokerMessages.LISTENING("TCP", port));
}
}
@@ -302,7 +295,7 @@ public class Broker
transport.accept(settings, protocolEngineFactory, sslContext);
ApplicationRegistry.getInstance().addAcceptor(inetSocketAddress,
- new QpidAcceptor(transport,"TCP"));
+ new QpidAcceptor(transport,QpidAcceptor.Transport.SSL, supported));
CurrentActor.get().message(BrokerMessages.LISTENING("TCP/SSL", sslPort));
}
}
@@ -495,12 +488,6 @@ public class Broker
}
}
- private void configureLoggingManagementMBean(File logConfigFile, int logWatchTime) throws Exception
- {
- LoggingManagementMBean blm = new LoggingManagementMBean(logConfigFile.getPath(),logWatchTime);
-
- blm.register();
- }
private void addShutdownHook()
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
index cec614881d..434d40d557 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
@@ -33,6 +33,7 @@ public class BrokerOptions
public static final String DEFAULT_CONFIG_FILE = "etc/config.xml";
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<Integer> _ports = new HashSet<Integer>();
private final Set<Integer> _sslPorts = new HashSet<Integer>();
@@ -47,6 +48,8 @@ public class BrokerOptions
private BundleContext _bundleContext;
private Integer _logWatchFrequency = 0;
+ private String _qpidWorkFolder;
+ private String _qpidHomeFolder;
public void addPort(final int port)
{
@@ -109,7 +112,7 @@ public class BrokerOptions
}
public String getQpidHome()
{
- return System.getProperty(QPID_HOME);
+ return _qpidHomeFolder == null? System.getProperty(QPID_HOME): _qpidHomeFolder;
}
public Set<Integer> getExcludedPorts(final ProtocolExclusion excludeProtocol)
@@ -179,4 +182,19 @@ public class BrokerOptions
Set<Integer> ports = _inclusionMap.get(includeProtocol);
ports.add(port);
}
+
+ public String getQpidWork()
+ {
+ return _qpidWorkFolder;
+ }
+
+ public void setQpidWork(String qpidWorkFolder)
+ {
+ _qpidWorkFolder = qpidWorkFolder;
+ }
+
+ public void setQpidHome(String qpidHomeFolder)
+ {
+ _qpidHomeFolder = qpidHomeFolder;
+ }
} \ No newline at end of file
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java
index 41c51d9684..6633d93adf 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java
@@ -49,7 +49,12 @@ public interface ExchangeConfig extends ConfiguredObject<ExchangeConfigType, Exc
long getMsgRoutes();
+ long getMsgDrops();
+
long getByteReceives();
long getByteRoutes();
+
+ long getByteDrops();
+
} \ No newline at end of file
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java
index 40bafb4275..8f03383777 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java
@@ -126,6 +126,11 @@ public class QueueConfiguration extends ConfigurationPlugin
return _name;
}
+ public String getDescription()
+ {
+ return getStringValue("description");
+ }
+
public int getMaximumMessageAge()
{
return getIntValue("maximumMessageAge", _vHostConfig.getMaximumMessageAge());
@@ -226,4 +231,5 @@ public class QueueConfiguration extends ConfigurationPlugin
}
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
index b48d8c5fdb..c23e58fdab 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
@@ -64,6 +64,7 @@ public class ServerConfiguration extends ConfigurationPlugin
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 String QPID_HOME = "QPID_HOME";
public static final String QPID_WORK = "QPID_WORK";
@@ -75,6 +76,8 @@ public class ServerConfiguration extends ConfigurationPlugin
private File _configFile;
private File _vhostsFile;
+ private String _qpidWork;
+ private String _qpidHome;
// Map of environment variables to config items
private static final Map<String, String> envVarMap = new HashMap<String, String>();
@@ -110,6 +113,8 @@ public class ServerConfiguration extends ConfigurationPlugin
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");
@@ -511,12 +516,26 @@ public class ServerConfiguration extends ConfigurationPlugin
public String getQpidWork()
{
- return System.getProperty(QPID_WORK, System.getProperty("java.io.tmpdir"));
+ if ( _qpidWork == null )
+ {
+ return System.getProperty(QPID_WORK, System.getProperty("java.io.tmpdir"));
+ }
+ else
+ {
+ return _qpidWork;
+ }
}
public String getQpidHome()
{
- return System.getProperty(QPID_HOME);
+ if ( _qpidHome == null )
+ {
+ return System.getProperty(QPID_HOME);
+ }
+ else
+ {
+ return _qpidHome;
+ }
}
public void setJMXPortRegistryServer(int registryServerPort)
@@ -554,6 +573,16 @@ public class ServerConfiguration extends ConfigurationPlugin
return getBooleanValue("management.platform-mbeanserver", true);
}
+ public boolean getHTTPManagementEnabled()
+ {
+ return getBooleanValue("management.http.enabled", true);
+ }
+
+ public int getHTTPManagementPort()
+ {
+ return getIntValue("management.http.port", 8080);
+ }
+
public String[] getVirtualHosts()
{
return _virtualHosts.keySet().toArray(new String[_virtualHosts.size()]);
@@ -622,7 +651,7 @@ public class ServerConfiguration extends ConfigurationPlugin
public boolean getManagementSSLEnabled()
{
- return getBooleanValue("management.ssl.enabled", true);
+ return getBooleanValue("management.ssl.enabled", false);
}
public String getManagementKeyStorePassword()
@@ -636,16 +665,11 @@ public class ServerConfiguration extends ConfigurationPlugin
return getBooleanValue("queue.auto_register", true);
}
- public boolean getManagementEnabled()
+ public boolean getJMXManagementEnabled()
{
return getBooleanValue("management.enabled", true);
}
- public void setManagementEnabled(boolean enabled)
- {
- getConfig().setProperty("management.enabled", enabled);
- }
-
public int getHeartBeatDelay()
{
return getIntValue("heartbeat.delay", 5);
@@ -981,4 +1005,14 @@ public class ServerConfiguration extends ConfigurationPlugin
return reply == null ? null : AmqpProtocolVersion.valueOf(reply);
}
+
+ public void setQpidWork(String path)
+ {
+ _qpidWork = path;
+ }
+
+ public void setQpidHome(String path)
+ {
+ _qpidHome = path;
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
index a539743081..451754e6d8 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
@@ -88,6 +88,13 @@ public class ConnectionRegistry implements IConnectionRegistry, Closeable
}
}
}
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.connectionRegistered(connnection);
+ }
+ }
}
public void deregisterConnection(AMQConnectionModel connnection)
@@ -104,6 +111,14 @@ public class ConnectionRegistry implements IConnectionRegistry, Closeable
}
}
}
+
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.connectionUnregistered(connnection);
+ }
+ }
}
public void addRegistryChangeListener(RegistryChangeListener listener)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index 9493f400f2..e633ddd341 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -30,15 +30,12 @@ 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.management.Managable;
-import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.message.InboundMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import javax.management.JMException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -50,10 +47,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
-public abstract class AbstractExchange implements Exchange, Managable
+public abstract class AbstractExchange implements Exchange
{
-
-
private AMQShortString _name;
private final AtomicBoolean _closed = new AtomicBoolean();
@@ -66,9 +61,6 @@ public abstract class AbstractExchange implements Exchange, Managable
private final List<Exchange.Task> _closeTaskList = new CopyOnWriteArrayList<Exchange.Task>();
-
- private AbstractExchangeMBean _exchangeMbean;
-
/**
* Whether the exchange is automatically deleted once all queues have detached from it
*/
@@ -86,6 +78,8 @@ public abstract class AbstractExchange implements Exchange, Managable
private final AtomicLong _receivedMessageSize = new AtomicLong();
private final AtomicLong _routedMessageCount = new AtomicLong();
private final AtomicLong _routedMessageSize = new AtomicLong();
+ private final AtomicLong _droppedMessageCount = new AtomicLong();
+ private final AtomicLong _droppedMessageSize = new AtomicLong();
private final CopyOnWriteArrayList<Exchange.BindingListener> _listeners = new CopyOnWriteArrayList<Exchange.BindingListener>();
@@ -107,13 +101,6 @@ public abstract class AbstractExchange implements Exchange, Managable
return _type.getName();
}
- /**
- * Concrete exchanges must implement this method in order to create the managed representation. This is
- * called during initialisation (template method pattern).
- * @return the MBean
- */
- protected abstract AbstractExchangeMBean createMBean() throws JMException;
-
public void initialise(UUID id, VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete)
throws AMQException
{
@@ -126,26 +113,12 @@ public abstract class AbstractExchange implements Exchange, Managable
_id = id;
getConfigStore().addConfiguredObject(this);
- createAndRegisterMBean();
_logSubject = new ExchangeLogSubject(this, this.getVirtualHost());
// Log Exchange creation
CurrentActor.get().message(ExchangeMessages.CREATED(String.valueOf(getTypeShortString()), String.valueOf(name), durable));
}
- private void createAndRegisterMBean()
- {
- try
- {
- _exchangeMbean = createMBean();
- _exchangeMbean.register();
- }
- catch (JMException e)
- {
- throw new RuntimeException("Failed to register mbean",e);
- }
- }
-
public ConfigStore getConfigStore()
{
return getVirtualHost().getConfigStore();
@@ -171,10 +144,6 @@ public abstract class AbstractExchange implements Exchange, Managable
if(_closed.compareAndSet(false,true))
{
- if (_exchangeMbean != null)
- {
- _exchangeMbean.unregister();
- }
getConfigStore().removeConfiguredObject(this);
if(_alternateExchange != null)
{
@@ -196,11 +165,6 @@ public abstract class AbstractExchange implements Exchange, Managable
return getClass().getSimpleName() + "[" + getNameShortString() +"]";
}
- public ManagedObject getManagedObject()
- {
- return _exchangeMbean;
- }
-
public VirtualHost getVirtualHost()
{
return _virtualHost;
@@ -359,6 +323,11 @@ public abstract class AbstractExchange implements Exchange, Managable
_routedMessageCount.incrementAndGet();
_routedMessageSize.addAndGet(message.getSize());
}
+ else
+ {
+ _droppedMessageCount.incrementAndGet();
+ _droppedMessageSize.addAndGet(message.getSize());
+ }
return queues;
}
@@ -374,6 +343,11 @@ public abstract class AbstractExchange implements Exchange, Managable
return _routedMessageCount.get();
}
+ public long getMsgDrops()
+ {
+ return _droppedMessageCount.get();
+ }
+
public long getByteReceives()
{
return _receivedMessageSize.get();
@@ -384,6 +358,11 @@ public abstract class AbstractExchange implements Exchange, Managable
return _routedMessageSize.get();
}
+ public long getByteDrops()
+ {
+ return _droppedMessageSize.get();
+ }
+
public long getCreateTime()
{
return _createTime;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java
deleted file mode 100644
index 034331abd9..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.exchange;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.management.common.mbeans.ManagedExchange;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.ManagementActor;
-import org.apache.qpid.server.management.AMQManagedObject;
-import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.management.ManagedObjectRegistry;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.management.JMException;
-import javax.management.MBeanException;
-import javax.management.MalformedObjectNameException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.ObjectName;
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularType;
-import java.util.Collections;
-
-
-/**
- * Abstract MBean class. This has some of the methods implemented from
- * management intrerface for exchanges. Any implementaion of an
- * Exchange MBean should extend this class.
- */
-public abstract class AbstractExchangeMBean<T extends AbstractExchange> extends AMQManagedObject implements ManagedExchange
-{
- // open mbean data types for representing exchange bindings
- private OpenType[] _bindingItemTypes;
- private CompositeType _bindingDataType;
- private TabularType _bindinglistDataType;
-
-
- private T _exchange;
-
- public AbstractExchangeMBean(final T abstractExchange) throws NotCompliantMBeanException
- {
- super(ManagedExchange.class, ManagedExchange.TYPE);
- _exchange = abstractExchange;
- }
-
- protected void init() throws OpenDataException
- {
- _bindingItemTypes = new OpenType[2];
- _bindingItemTypes[0] = SimpleType.STRING;
- _bindingItemTypes[1] = new ArrayType(1, SimpleType.STRING);
- _bindingDataType = new CompositeType("Exchange Binding", "Binding key and Queue names",
- COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]),
- COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]), _bindingItemTypes);
- _bindinglistDataType = new TabularType("Exchange Bindings", "Exchange Bindings for " + getName(),
- _bindingDataType, TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()]));
- }
-
- public ManagedObject getParentObject()
- {
- return _exchange.getVirtualHost().getManagedObject();
- }
-
- public T getExchange()
- {
- return _exchange;
- }
-
-
- public String getObjectInstanceName()
- {
- return ObjectName.quote(_exchange.getName());
- }
-
- public String getName()
- {
- return _exchange.getName();
- }
-
- public String getExchangeType()
- {
- return _exchange.getTypeShortString().toString();
- }
-
- public Integer getTicketNo()
- {
- return _exchange.getTicket();
- }
-
- public boolean isDurable()
- {
- return _exchange.isDurable();
- }
-
- public boolean isAutoDelete()
- {
- return _exchange.isAutoDelete();
- }
-
- // Added exchangetype in the object name lets maangement apps to do any customization required
- public ObjectName getObjectName() throws MalformedObjectNameException
- {
- String objNameString = super.getObjectName().toString();
- objNameString = objNameString + ",ExchangeType=" + getExchangeType();
- return new ObjectName(objNameString);
- }
-
- protected ManagedObjectRegistry getManagedObjectRegistry()
- {
- return ApplicationRegistry.getInstance().getManagedObjectRegistry();
- }
-
- public void createNewBinding(String queueName, String binding) throws JMException
- {
- VirtualHost vhost = getExchange().getVirtualHost();
- AMQQueue queue = vhost.getQueueRegistry().getQueue(new AMQShortString(queueName));
- if (queue == null)
- {
- throw new JMException("Queue \"" + queueName + "\" is not registered with the virtualhost.");
- }
-
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- vhost.getBindingFactory().addBinding(binding,queue,getExchange(),null);
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error creating new binding " + binding);
- }
- CurrentActor.remove();
- }
-
- /**
- * Removes a queue binding from the exchange.
- *
- * @see org.apache.qpid.server.binding.BindingFactory#removeBinding(String, AMQQueue, Exchange, java.util.Map)
- */
- public void removeBinding(String queueName, String binding) throws JMException
- {
- VirtualHost vhost = getExchange().getVirtualHost();
- AMQQueue queue = vhost.getQueueRegistry().getQueue(new AMQShortString(queueName));
- if (queue == null)
- {
- throw new JMException("Queue \"" + queueName + "\" is not registered with the virtualhost.");
- }
-
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- vhost.getBindingFactory().removeBinding(binding, queue, _exchange, Collections.<String, Object>emptyMap());
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error removing binding " + binding);
- }
- CurrentActor.remove();
- }
-
-
- protected OpenType[] getBindingItemTypes()
- {
- return _bindingItemTypes;
- }
-
- protected void setBindingItemTypes(OpenType[] bindingItemTypes)
- {
- _bindingItemTypes = bindingItemTypes;
- }
-
- protected CompositeType getBindingDataType()
- {
- return _bindingDataType;
- }
-
- protected void setBindingDataType(CompositeType bindingDataType)
- {
- _bindingDataType = bindingDataType;
- }
-
- protected TabularType getBindinglistDataType()
- {
- return _bindinglistDataType;
- }
-
- protected void setBindinglistDataType(TabularType bindinglistDataType)
- {
- _bindinglistDataType = bindinglistDataType;
- }
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
index bf4184bf0b..baf9cc3d09 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
@@ -29,7 +29,9 @@ import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -46,6 +48,8 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
private Exchange _defaultExchange;
private VirtualHost _host;
+ private final Collection<RegistryChangeListener> _listeners =
+ Collections.synchronizedCollection(new ArrayList<RegistryChangeListener>());
public DefaultExchangeRegistry(VirtualHost host)
{
@@ -68,6 +72,14 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
{
_exchangeMap.put(exchange.getNameShortString(), exchange);
_exchangeMapStr.put(exchange.getNameShortString().toString(), exchange);
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.exchangeRegistered(exchange);
+ }
+
+ }
}
public void setDefaultExchange(Exchange exchange)
@@ -114,6 +126,15 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
getDurableConfigurationStore().removeExchange(e);
}
e.close();
+
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.exchangeUnregistered(exchange);
+ }
+ }
+
}
else
{
@@ -126,6 +147,16 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
unregisterExchange(new AMQShortString(name), inUse);
}
+ public Collection<Exchange> getExchanges()
+ {
+ return new ArrayList<Exchange>(_exchangeMap.values());
+ }
+
+ public void addRegistryChangeListener(RegistryChangeListener listener)
+ {
+ _listeners.add(listener);
+ }
+
public Exchange getExchange(AMQShortString name)
{
if ((name == null) || name.length() == 0)
@@ -158,16 +189,14 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
{
final Exchange exchange = getExchange(exchangeName);
- if (exchange instanceof AbstractExchange)
+ //TODO: this is a bit of a hack, what if the listeners aren't aware
+ //that we are just unregistering the MBean because of HA, and aren't
+ //actually removing the exchange as such.
+ synchronized (_listeners)
{
- AbstractExchange abstractExchange = (AbstractExchange) exchange;
- try
- {
- abstractExchange.getManagedObject().unregister();
- }
- catch (AMQException e)
+ for(RegistryChangeListener listener : _listeners)
{
- LOGGER.warn("Failed to unregister mbean", e);
+ listener.exchangeUnregistered(exchange);
}
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
index af9322764a..92326412c1 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
@@ -127,11 +127,6 @@ public class DirectExchange extends AbstractExchange
super(TYPE);
}
- protected AbstractExchangeMBean createMBean() throws JMException
- {
- return new DirectExchangeMBean(this);
- }
-
public List<? extends BaseQueue> doRoute(InboundMessage payload)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java
deleted file mode 100644
index 0bfaf7035d..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.exchange;
-
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.binding.Binding;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * MBean class implementing the management interfaces.
- */
-@MBeanDescription("Management Bean for Direct Exchange")
-final class DirectExchangeMBean extends AbstractExchangeMBean<DirectExchange>
-{
- @MBeanConstructor("Creates an MBean for AMQ direct exchange")
- public DirectExchangeMBean(final DirectExchange exchange) throws JMException
- {
- super(exchange);
-
- init();
- }
-
- public TabularData bindings() throws OpenDataException
- {
- TabularDataSupport bindingList = new TabularDataSupport(getBindinglistDataType());
-
- Map<String, List<String>> bindingMap = new HashMap<String, List<String>>();
-
- for (Binding binding : getExchange().getBindings())
- {
- String key = binding.getBindingKey();
- List<String> queueList = bindingMap.get(key);
- if(queueList == null)
- {
- queueList = new ArrayList<String>();
- bindingMap.put(key, queueList);
- }
- queueList.add(binding.getQueue().getNameShortString().toString());
-
- }
-
- for(Map.Entry<String, List<String>> entry : bindingMap.entrySet())
- {
- Object[] bindingItemValues = {entry.getKey(), entry.getValue().toArray(new String[0])};
- CompositeData bindingData = new CompositeDataSupport(getBindingDataType(),
- COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]),
- bindingItemValues);
- bindingList.put(bindingData);
- }
-
- return bindingList;
- }
-
-
-
-}// End of MBean class
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java
index 795ae2e140..692a2b2b0d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.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
@@ -57,4 +57,14 @@ public interface ExchangeRegistry
void clearAndUnregisterMbeans();
Exchange getExchange(UUID exchangeId);
+
+ Collection<Exchange> getExchanges();
+
+ void addRegistryChangeListener(RegistryChangeListener listener);
+
+ interface RegistryChangeListener
+ {
+ void exchangeRegistered(Exchange exchange);
+ void exchangeUnregistered(Exchange exchange);
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
index 5ebcfd095f..5f4998f77f 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
@@ -48,11 +48,6 @@ public class FanoutExchange extends AbstractExchange
*/
private final ConcurrentHashMap<AMQQueue,Integer> _queues = new ConcurrentHashMap<AMQQueue,Integer>();
- protected AbstractExchangeMBean createMBean() throws JMException
- {
- return new FanoutExchangeMBean(this);
- }
-
public static final ExchangeType<FanoutExchange> TYPE = new ExchangeType<FanoutExchange>()
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java
deleted file mode 100644
index 61e23c896c..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.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.exchange;
-
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.binding.Binding;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.ArrayList;
-
-/**
- * MBean class implementing the management interfaces.
- */
-@MBeanDescription("Management Bean for Fanout Exchange")
-final class FanoutExchangeMBean extends AbstractExchangeMBean<FanoutExchange>
-{
- private static final String BINDING_KEY_SUBSTITUTE = "*";
-
- @MBeanConstructor("Creates an MBean for AMQ fanout exchange")
- public FanoutExchangeMBean(final FanoutExchange exchange) throws JMException
- {
- super(exchange);
- init();
- }
-
- public TabularData bindings() throws OpenDataException
- {
-
- TabularDataSupport bindingList = new TabularDataSupport(getBindinglistDataType());
-
-
- ArrayList<String> queueNames = new ArrayList<String>();
-
- for (Binding binding : getExchange().getBindings())
- {
- String queueName = binding.getQueue().getNameShortString().toString();
- queueNames.add(queueName);
- }
-
- Object[] bindingItemValues = {BINDING_KEY_SUBSTITUTE, queueNames.toArray(new String[0])};
- CompositeData bindingData = new CompositeDataSupport(getBindingDataType(),
- COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]),
- bindingItemValues);
- bindingList.put(bindingData);
-
- return bindingList;
- }
-
-
-} // End of MBean class
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
index 16ba3c0431..6bad59c2ae 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
@@ -227,11 +227,6 @@ public class HeadersExchange extends AbstractExchange
return !getBindings().isEmpty();
}
- protected AbstractExchangeMBean createMBean() throws JMException
- {
- return new HeadersExchangeMBean(this);
- }
-
protected void onBind(final Binding binding)
{
String bindingKey = binding.getBindingKey();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java
deleted file mode 100644
index 395c6c8a91..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.exchange;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.binding.Binding;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.ManagementActor;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.management.JMException;
-import javax.management.MBeanException;
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.TabularType;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * HeadersExchangeMBean class implements the management interface for the
- * Header Exchanges.
- */
-@MBeanDescription("Management Bean for Headers Exchange")
-final class HeadersExchangeMBean extends AbstractExchangeMBean<HeadersExchange>
-{
-
- @MBeanConstructor("Creates an MBean for AMQ Headers exchange")
- public HeadersExchangeMBean(final HeadersExchange headersExchange) throws JMException
- {
- super(headersExchange);
- init();
- }
-
- /**
- * initialises the OpenType objects.
- */
- protected void init() throws OpenDataException
- {
-
- setBindingItemTypes(new OpenType[3]);
- getBindingItemTypes()[0] = SimpleType.INTEGER;
- getBindingItemTypes()[1] = SimpleType.STRING;
- getBindingItemTypes()[2] = new ArrayType(1, SimpleType.STRING);
- setBindingDataType(new CompositeType("Exchange Binding", "Queue name and header bindings",
- HEADERS_COMPOSITE_ITEM_NAMES.toArray(new String[HEADERS_COMPOSITE_ITEM_NAMES.size()]),
- HEADERS_COMPOSITE_ITEM_DESC.toArray(new String[HEADERS_COMPOSITE_ITEM_DESC.size()]), getBindingItemTypes()));
- setBindinglistDataType(new TabularType("Exchange Bindings", "List of exchange bindings for " + getName(),
- getBindingDataType(), HEADERS_TABULAR_UNIQUE_INDEX.toArray(new String[HEADERS_TABULAR_UNIQUE_INDEX.size()])));
- }
-
- public TabularData bindings() throws OpenDataException
- {
- TabularDataSupport bindingList = new TabularDataSupport(getBindinglistDataType());
- int count = 1;
- for (Binding binding : getExchange().getBindings())
- {
-
- String queueName = binding.getQueue().getNameShortString().toString();
-
-
- Map<String,Object> headerMappings = binding.getArguments();
- final List<String> mappingList = new ArrayList<String>();
-
- if(headerMappings != null)
- {
- for(Map.Entry<String,Object> entry : headerMappings.entrySet())
- {
-
- mappingList.add(entry.getKey() + "=" + entry.getValue());
- }
- }
-
-
- Object[] bindingItemValues = {count++, queueName, mappingList.toArray(new String[0])};
- CompositeData bindingData = new CompositeDataSupport(getBindingDataType(),
- HEADERS_COMPOSITE_ITEM_NAMES.toArray(new String[HEADERS_COMPOSITE_ITEM_NAMES.size()]), bindingItemValues);
- bindingList.put(bindingData);
- }
-
- return bindingList;
- }
-
- @Override
- public void createNewBinding(String queueName, String binding) throws JMException
- {
- VirtualHost vhost = getExchange().getVirtualHost();
- AMQQueue queue = vhost.getQueueRegistry().getQueue(new AMQShortString(queueName));
- if (queue == null)
- {
- throw new JMException("Queue \"" + queueName + "\" is not registered with the virtualhost.");
- }
-
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
-
- final Map<String,Object> arguments = new HashMap<String, Object>();
- final String[] bindings = binding.split(",");
- for (int i = 0; i < bindings.length; i++)
- {
- final String[] keyAndValue = bindings[i].split("=");
- if (keyAndValue == null || keyAndValue.length == 0 || keyAndValue.length > 2 || keyAndValue[0].length() == 0)
- {
- throw new JMException("Format for headers binding should be \"<attribute1>=<value1>,<attribute2>=<value2>\" ");
- }
-
- if(keyAndValue.length == 1)
- {
- //no value was given, only a key. Use an empty value to signal match on key presence alone
- arguments.put(keyAndValue[0], "");
- }
- else
- {
- arguments.put(keyAndValue[0], keyAndValue[1]);
- }
- }
- try
- {
- vhost.getBindingFactory().addBinding(binding,queue,getExchange(),arguments);
- }
- catch (AMQException ex)
- {
- JMException jme = new JMException(ex.toString());
- throw new MBeanException(jme, "Error creating new binding " + binding);
- }
- CurrentActor.remove();
- }
-
-} // End of MBean class
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
index 7ea7a41826..480d4e4215 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
@@ -403,11 +403,6 @@ public class TopicExchange extends AbstractExchange
}
}
- protected AbstractExchangeMBean createMBean() throws JMException
- {
- return new TopicExchangeMBean(this);
- }
-
private Collection<AMQQueue> getMatchedQueues(InboundMessage message, AMQShortString routingKey)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java
deleted file mode 100644
index 481a377fc4..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.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.exchange;
-
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.binding.Binding;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/** TopicExchangeMBean class implements the management interface for the Topic exchanges. */
-@MBeanDescription("Management Bean for Topic Exchange")
-final class TopicExchangeMBean extends AbstractExchangeMBean<TopicExchange>
-{
- private TopicExchange _topicExchange;
-
- @MBeanConstructor("Creates an MBean for AMQ topic exchange")
- public TopicExchangeMBean(final TopicExchange topicExchange) throws JMException
- {
- super(topicExchange);
- init();
- }
-
- /** returns exchange bindings in tabular form */
- public TabularData bindings() throws OpenDataException
- {
- TabularDataSupport bindingList = new TabularDataSupport(getBindinglistDataType());
- Map<String, List<String>> bindingData = new HashMap<String, List<String>>();
- for (Binding binding : getExchange().getBindings())
- {
- String key = binding.getBindingKey();
- List<String> queueNames = bindingData.get(key);
- if(queueNames == null)
- {
- queueNames = new ArrayList<String>();
- bindingData.put(key, queueNames);
- }
- queueNames.add(binding.getQueue().getNameShortString().toString());
-
- }
- for(Map.Entry<String, List<String>> entry : bindingData.entrySet())
- {
- Object[] bindingItemValues = {entry.getKey(), entry.getValue().toArray(new String[entry.getValue().size()]) };
- CompositeData bindingCompositeData =
- new CompositeDataSupport(getBindingDataType(),
- COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]),
- bindingItemValues);
- bindingList.put(bindingCompositeData);
- }
-
- return bindingList;
- }
-
-} // End of MBean class
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java
deleted file mode 100644
index 4d395f625a..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.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.information.management;
-
-import org.apache.qpid.common.QpidProperties;
-import org.apache.qpid.management.common.mbeans.ServerInformation;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.management.AMQManagedObject;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-
-import javax.management.JMException;
-import java.io.IOException;
-
-/** MBean class for the ServerInformationMBean. */
-@MBeanDescription("Server Information Interface")
-public class ServerInformationMBean extends AMQManagedObject implements ServerInformation
-{
- private String buildVersion;
- private String productVersion;
- private ApplicationRegistry registry;
-
- public ServerInformationMBean(ApplicationRegistry applicationRegistry) throws JMException
- {
- super(ServerInformation.class, ServerInformation.TYPE);
-
- registry = applicationRegistry;
- buildVersion = QpidProperties.getBuildVersion();
- productVersion = QpidProperties.getReleaseVersion();
- }
-
- public String getObjectInstanceName()
- {
- return ServerInformation.TYPE;
- }
-
- public Integer getManagementApiMajorVersion() throws IOException
- {
- return QPID_JMX_API_MAJOR_VERSION;
- }
-
- public Integer getManagementApiMinorVersion() throws IOException
- {
- return QPID_JMX_API_MINOR_VERSION;
- }
-
- public String getBuildVersion() throws IOException
- {
- return buildVersion;
- }
-
- public String getProductVersion() throws IOException
- {
- return productVersion;
- }
-
-
- public void resetStatistics() throws Exception
- {
- registry.resetStatistics();
- }
-
- public double getPeakMessageDeliveryRate()
- {
- return registry.getMessageDeliveryStatistics().getPeak();
- }
-
- public double getPeakDataDeliveryRate()
- {
- return registry.getDataDeliveryStatistics().getPeak();
- }
-
- public double getMessageDeliveryRate()
- {
- return registry.getMessageDeliveryStatistics().getRate();
- }
-
- public double getDataDeliveryRate()
- {
- return registry.getDataDeliveryStatistics().getRate();
- }
-
- public long getTotalMessagesDelivered()
- {
- return registry.getMessageDeliveryStatistics().getTotal();
- }
-
- public long getTotalDataDelivered()
- {
- return registry.getDataDeliveryStatistics().getTotal();
- }
-
- public double getPeakMessageReceiptRate()
- {
- return registry.getMessageReceiptStatistics().getPeak();
- }
-
- public double getPeakDataReceiptRate()
- {
- return registry.getDataReceiptStatistics().getPeak();
- }
-
- public double getMessageReceiptRate()
- {
- return registry.getMessageReceiptStatistics().getRate();
- }
-
- public double getDataReceiptRate()
- {
- return registry.getDataReceiptStatistics().getRate();
- }
-
- public long getTotalMessagesReceived()
- {
- return registry.getMessageReceiptStatistics().getTotal();
- }
-
- public long getTotalDataReceived()
- {
- return registry.getDataReceiptStatistics().getTotal();
- }
-
- public boolean isStatisticsEnabled()
- {
- return registry.isStatisticsEnabled();
- }
-
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java
new file mode 100644
index 0000000000..a1065319d3
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.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.logging;
+
+import java.util.Iterator;
+import org.apache.log4j.Appender;
+import org.apache.log4j.Layout;
+import org.apache.log4j.Logger;
+import org.apache.log4j.spi.ErrorHandler;
+import org.apache.log4j.spi.Filter;
+import org.apache.log4j.spi.LoggingEvent;
+
+public class LogRecorder implements Appender, Iterable<LogRecorder.Record>
+{
+ private ErrorHandler _errorHandler;
+ private Filter _filter;
+ private String _name;
+ private long _recordId;
+
+ private final int _bufferSize = 4096;
+ private final int _mask = _bufferSize - 1;
+ private Record[] _records = new Record[_bufferSize];
+
+
+ public static class Record
+ {
+ private final long _id;
+ private final String _logger;
+ private final long _timestamp;
+ private final String _threadName;
+ private final String _level;
+ private final String _message;
+
+
+ public Record(long id, LoggingEvent event)
+ {
+ _id = id;
+ _logger = event.getLoggerName();
+ _timestamp = event.timeStamp;
+ _threadName = event.getThreadName();
+ _level = event.getLevel().toString();
+ _message = event.getRenderedMessage();
+ }
+
+ public long getId()
+ {
+ return _id;
+ }
+
+ public long getTimestamp()
+ {
+ return _timestamp;
+ }
+
+ public String getThreadName()
+ {
+ return _threadName;
+ }
+
+ public String getLevel()
+ {
+ return _level;
+ }
+
+ public String getMessage()
+ {
+ return _message;
+ }
+
+ public String getLogger()
+ {
+ return _logger;
+ }
+ }
+
+ public LogRecorder()
+ {
+
+ Logger.getRootLogger().addAppender(this);
+ }
+
+ @Override
+ public void addFilter(Filter filter)
+ {
+ _filter = filter;
+ }
+
+ @Override
+ public void clearFilters()
+ {
+ _filter = null;
+ }
+
+ @Override
+ public void close()
+ {
+ //TODO - Implement
+ }
+
+ @Override
+ public synchronized void doAppend(LoggingEvent loggingEvent)
+ {
+ _records[((int) (_recordId & _mask))] = new Record(_recordId, loggingEvent);
+ _recordId++;
+ }
+
+ @Override
+ public ErrorHandler getErrorHandler()
+ {
+ return _errorHandler;
+ }
+
+ @Override
+ public Filter getFilter()
+ {
+ return _filter;
+ }
+
+ @Override
+ public Layout getLayout()
+ {
+ return null;
+ }
+
+ @Override
+ public String getName()
+ {
+ return _name;
+ }
+
+ @Override
+ public boolean requiresLayout()
+ {
+ return false;
+ }
+
+ @Override
+ public void setErrorHandler(ErrorHandler errorHandler)
+ {
+ _errorHandler = errorHandler;
+ }
+
+ @Override
+ public void setLayout(Layout layout)
+ {
+
+ }
+
+ @Override
+ public void setName(String name)
+ {
+ _name = name;
+ }
+
+ @Override
+ public Iterator<Record> iterator()
+ {
+ return new RecordIterator(Math.max(_recordId-_bufferSize, 0l));
+ }
+
+ private class RecordIterator implements Iterator<Record>
+ {
+ private long _id;
+
+ public RecordIterator(long currentRecordId)
+ {
+ _id = currentRecordId;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return _id < _recordId;
+ }
+
+ @Override
+ public Record next()
+ {
+ Record record = _records[((int) (_id & _mask))];
+ while(_id < _recordId-_bufferSize)
+ {
+ _id = _recordId-_bufferSize;
+ record = _records[((int) (_id & _mask))];
+ }
+ _id++;
+ return record;
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java
deleted file mode 100644
index 6cfc827046..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.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.management;
-
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-
-import javax.management.JMException;
-import javax.management.MBeanNotificationInfo;
-import javax.management.NotCompliantMBeanException;
-import javax.management.Notification;
-import javax.management.ObjectName;
-import javax.management.monitor.MonitorNotification;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularType;
-
-public abstract class AbstractAMQManagedConnectionObject extends AMQManagedObject implements ManagedConnection
-{
- private final String _name;
-
- protected static final OpenType[] _channelAttributeTypes = { SimpleType.INTEGER, SimpleType.BOOLEAN, SimpleType.STRING, SimpleType.INTEGER, SimpleType.BOOLEAN };
- protected static final CompositeType _channelType;
- protected static final TabularType _channelsType;
-
- protected static final String BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION_STR =
- "Broker Management Console has closed the connection.";
-
- static
- {
- try
- {
- _channelType = new CompositeType("Channel", "Channel Details", COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]),
- COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]), _channelAttributeTypes);
- _channelsType = new TabularType("Channels", "Channels", _channelType, (String[]) TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()]));
- }
- catch (JMException ex)
- {
- // This is not expected to ever occur.
- throw new RuntimeException("Got JMException in static initializer.", ex);
- }
- }
-
- protected AbstractAMQManagedConnectionObject(final String remoteAddress) throws NotCompliantMBeanException
- {
- super(ManagedConnection.class, ManagedConnection.TYPE);
- _name = "anonymous".equals(remoteAddress) ? (remoteAddress + hashCode()) : remoteAddress;
- }
-
- public String getObjectInstanceName()
- {
- return ObjectName.quote(_name);
- }
-
- public void notifyClients(String notificationMsg)
- {
- final Notification n = new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this, incrementAndGetSequenceNumber(),
- System.currentTimeMillis(), notificationMsg);
- getBroadcaster().sendNotification(n);
- }
-
- @Override
- public MBeanNotificationInfo[] getNotificationInfo()
- {
- String[] notificationTypes = new String[] { MonitorNotification.THRESHOLD_VALUE_EXCEEDED };
- String name = MonitorNotification.class.getName();
- String description = "Channel count has reached threshold value";
- MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description);
-
- return new MBeanNotificationInfo[] { info1 };
- }
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java
index faac14f8a7..63bd1e45a0 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.message;
+import java.util.Collection;
import java.util.Set;
public interface AMQMessageHeader
@@ -28,6 +29,10 @@ public interface AMQMessageHeader
long getExpiration();
+ String getUserId();
+
+ String getAppId();
+
String getMessageId();
String getMimeType();
@@ -52,4 +57,5 @@ public interface AMQMessageHeader
boolean containsHeader(String name);
+ Collection<String> getHeaderNames();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java
index e87b67d242..01c1021070 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.message;
+import java.util.Collection;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.FieldTable;
@@ -50,6 +51,16 @@ public class ContentHeaderBodyAdapter implements AMQMessageHeader
return getProperties().getExpiration();
}
+ public String getUserId()
+ {
+ return getProperties().getUserIdAsString();
+ }
+
+ public String getAppId()
+ {
+ return getProperties().getAppIdAsString();
+ }
+
public String getMessageId()
{
return getProperties().getMessageIdAsString();
@@ -117,6 +128,13 @@ public class ContentHeaderBodyAdapter implements AMQMessageHeader
return true;
}
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ FieldTable ft = getProperties().getHeaders();
+ return ft.keys();
+ }
+
public boolean containsHeader(String name)
{
FieldTable ft = getProperties().getHeaders();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java
index 583f0c09a7..e890bf5ef8 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.message;
+import java.util.Collection;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
@@ -242,6 +243,16 @@ public class MessageMetaData implements StorableMessageMetaData
return (BasicContentHeaderProperties) getContentHeaderBody().getProperties();
}
+ public String getUserId()
+ {
+ return getProperties().getUserIdAsString();
+ }
+
+ public String getAppId()
+ {
+ return getProperties().getAppIdAsString();
+ }
+
public String getCorrelationId()
{
return getProperties().getCorrelationIdAsString();
@@ -318,6 +329,12 @@ public class MessageMetaData implements StorableMessageMetaData
return true;
}
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ return getProperties().getHeaders().keys();
+ }
+
public boolean containsHeader(String name)
{
FieldTable ft = getProperties().getHeaders();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java
index 7d030fe711..2cc1a92853 100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java
@@ -21,11 +21,7 @@
package org.apache.qpid.server.message;
import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import org.apache.qpid.amqp_1_0.codec.ValueHandler;
import org.apache.qpid.amqp_1_0.messaging.SectionDecoder;
import org.apache.qpid.amqp_1_0.type.AmqpErrorException;
@@ -486,6 +482,18 @@ public class MessageMetaData_1_0 implements StorableMessageMetaData
return null; //TODO
}
+ public String getAppId()
+ {
+ //TODO
+ return null;
+ }
+
+ public String getUserId()
+ {
+ // TODO
+ return null;
+ }
+
public Object getHeader(final String name)
{
return _appProperties == null ? null : _appProperties.get(name);
@@ -508,6 +516,16 @@ public class MessageMetaData_1_0 implements StorableMessageMetaData
return true;
}
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ if(_appProperties == null)
+ {
+ return Collections.emptySet();
+ }
+ return Collections.unmodifiableCollection(_appProperties.keySet());
+ }
+
public boolean containsHeader(final String name)
{
return _appProperties != null && _appProperties.containsKey(name);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java
index 126e7c28cb..91384f7c22 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java
@@ -20,14 +20,11 @@
*/
package org.apache.qpid.server.message;
+import java.util.*;
import org.apache.qpid.transport.DeliveryProperties;
import org.apache.qpid.transport.MessageDeliveryPriority;
import org.apache.qpid.transport.MessageProperties;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
class MessageTransferHeader implements AMQMessageHeader
{
@@ -60,10 +57,22 @@ class MessageTransferHeader implements AMQMessageHeader
return _deliveryProps == null ? 0L : _deliveryProps.getExpiration();
}
+ public String getUserId()
+ {
+ byte[] userIdBytes = _messageProps == null ? null : _messageProps.getUserId();
+ return userIdBytes == null ? null : new String(userIdBytes);
+ }
+
+ public String getAppId()
+ {
+ byte[] appIdBytes = _messageProps == null ? null : _messageProps.getAppId();
+ return appIdBytes == null ? null : new String(appIdBytes);
+ }
+
public String getMessageId()
{
UUID id = _messageProps == null ? null : _messageProps.getMessageId();
-
+
return id == null ? null : String.valueOf(id);
}
@@ -93,7 +102,7 @@ class MessageTransferHeader implements AMQMessageHeader
public String getType()
{
Object type = getHeader(JMS_TYPE);
- return type instanceof String ? (String) type : null;
+ return type instanceof String ? (String) type : null;
}
public String getReplyTo()
@@ -145,6 +154,14 @@ class MessageTransferHeader implements AMQMessageHeader
}
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ Map<String, Object> appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders();
+ return appHeaders != null ? Collections.unmodifiableCollection(appHeaders.keySet()) : Collections.EMPTY_SET ;
+
+ }
+
public boolean containsHeader(String name)
{
Map<String, Object> appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Attribute.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Attribute.java
new file mode 100644
index 0000000000..4fccf47e0e
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Attribute.java
@@ -0,0 +1,199 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.model;
+
+public abstract class Attribute<C extends ConfiguredObject, T>
+{
+ private final String _name;
+ public Attribute(String name)
+ {
+ _name = name;
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ abstract public Class<T> getType();
+
+ public T getValue(C configuredObject)
+ {
+ Object o = configuredObject.getAttribute(_name);
+ if(getType().isInstance(o))
+ {
+ return (T) o;
+ }
+ return null;
+ }
+
+ public T setValue(T expected, T desired, C configuredObject)
+ {
+ return (T) configuredObject.setAttribute(_name, expected, desired);
+ }
+
+ abstract public T setValue(String stringValue, C configuredObject);
+
+ static class StringAttribute<C extends ConfiguredObject> extends Attribute<C, String>
+ {
+
+ public StringAttribute(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ public Class<String> getType()
+ {
+ return String.class;
+ }
+
+ @Override
+ public String setValue(String stringValue, C configuredObject)
+ {
+ return setValue(getValue(configuredObject), stringValue, configuredObject);
+ }
+
+ }
+
+ static class IntegerAttribute<C extends ConfiguredObject> extends Attribute<C, Integer>
+ {
+
+ public IntegerAttribute(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ public Class<Integer> getType()
+ {
+ return Integer.class;
+ }
+
+ @Override
+ public Integer setValue(String stringValue, C configuredObject)
+ {
+ try
+ {
+ Integer val = Integer.valueOf(stringValue);
+ return setValue(getValue(configuredObject), val, configuredObject);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ }
+
+
+ static class LongAttribute<C extends ConfiguredObject> extends Attribute<C, Long>
+ {
+
+ public LongAttribute(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ public Class<Long> getType()
+ {
+ return Long.class;
+ }
+
+ @Override
+ public Long setValue(String stringValue, C configuredObject)
+ {
+ try
+ {
+ Long val = Long.valueOf(stringValue);
+ return setValue(getValue(configuredObject), val, configuredObject);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ }
+
+
+ static class DoubleAttribute<C extends ConfiguredObject> extends Attribute<C, Double>
+ {
+
+ public DoubleAttribute(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ public Class<Double> getType()
+ {
+ return Double.class;
+ }
+
+ @Override
+ public Double setValue(String stringValue, C configuredObject)
+ {
+ try
+ {
+ Double val = Double.valueOf(stringValue);
+ return setValue(getValue(configuredObject), val, configuredObject);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ }
+
+
+ static class FloatAttribute<C extends ConfiguredObject> extends Attribute<C, Float>
+ {
+
+ public FloatAttribute(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ public Class<Float> getType()
+ {
+ return Float.class;
+ }
+
+ @Override
+ public Float setValue(String stringValue, C configuredObject)
+ {
+ try
+ {
+ Float val = Float.valueOf(stringValue);
+ return setValue(getValue(configuredObject), val, configuredObject);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ }
+
+
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationMethod.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationMethod.java
new file mode 100644
index 0000000000..7a5927a365
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationMethod.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.model;
+
+import java.util.Collection;
+
+public interface AuthenticationMethod extends ConfiguredObject
+{
+ // name is the SASL mech where this is a SASL authentication
+
+ // parents
+ VirtualHostAlias getVirtualHostAlias();
+ AuthenticationProvider getAuthenticationProvider();
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java
new file mode 100644
index 0000000000..6000886956
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.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.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public interface AuthenticationProvider 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<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableList(
+ Arrays.asList(ID,
+ NAME,
+ DESCRIPTION,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ TYPE));
+ //children
+ Collection<VirtualHostAlias> getVirtualHostPortBindings();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java
new file mode 100644
index 0000000000..ca1de0f189
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java
@@ -0,0 +1,82 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.security.AccessControlException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+public interface Broker extends ConfiguredObject
+{
+
+ String BUILD_VERSION = "buildVersion";
+ String BYTES_RETAINED = "bytesRetained";
+ String OPERATING_SYSTEM = "operatingSystem";
+ String PLATFORM = "platform";
+ String PROCESS_PID = "processPid";
+ String PRODUCT_VERSION = "productVersion";
+ String STATISTICS_ENABLED = "statisticsEnabled";
+ String SUPPORTED_STORE_TYPES = "supportedStoreTypes";
+ 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<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableList(
+ Arrays.asList(BUILD_VERSION,
+ BYTES_RETAINED,
+ OPERATING_SYSTEM,
+ PLATFORM,
+ PROCESS_PID,
+ PRODUCT_VERSION,
+ STATISTICS_ENABLED,
+ SUPPORTED_STORE_TYPES,
+ CREATED,
+ DURABLE,
+ ID,
+ LIFETIME_POLICY,
+ NAME,
+ STATE,
+ TIME_TO_LIVE,
+ UPDATED));
+
+ //children
+ Collection < VirtualHost > getVirtualHosts();
+
+ Collection<Port> getPorts();
+
+ Collection<AuthenticationProvider> getAuthenticationProviders();
+
+ VirtualHost createVirtualHost(String name, State initialState, boolean durable,
+ LifetimePolicy lifetime, long ttl, Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException;
+
+ void deleteVirtualHost(VirtualHost virtualHost)
+ throws AccessControlException, IllegalStateException;
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java
index 6477633a9b..78b98faffe 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java
@@ -30,7 +30,8 @@ public interface ConfigurationChangeListener
* @param newState the state after the change
*/
void stateChanged(ConfiguredObject object, State oldState, State newState);
-
+
+
void childAdded(ConfiguredObject object, ConfiguredObject child);
void childRemoved(ConfiguredObject object, ConfiguredObject child);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
index fb47a54d0a..414b2d083a 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
@@ -22,6 +22,7 @@ package org.apache.qpid.server.model;
import java.security.AccessControlException;
import java.util.Collection;
+import java.util.Map;
import java.util.UUID;
public interface ConfiguredObject
@@ -81,7 +82,7 @@ public interface ConfiguredObject
* @param desiredState the state the caller wishes the object to attain
* @return the new current state
* @throws IllegalStateTransitionException the requested state tranisition is invalid
- * @throws AccessControlException the current context does not have sufficeint permissions to change the state
+ * @throws AccessControlException the current context does not have sufficient permissions to change the state
*/
State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException,
AccessControlException;
@@ -89,7 +90,7 @@ public interface ConfiguredObject
/**
* Get the actual state of the object.
*
- * This state is derived fromt the desired state of the object itself and
+ * This state is derived from the desired state of the object itself and
* the actual state of its parents. If an object "desires" to be ACTIVE, but one of its parents is STOPPED, then
* the actual state of the object will be STOPPED
*
@@ -126,7 +127,7 @@ public interface ConfiguredObject
/**
* Returns whether the the object configuration is durably stored
*
- * @return the durablity
+ * @return the durability
*/
boolean isDurable();
@@ -188,7 +189,7 @@ public interface ConfiguredObject
/**
* Get the names of attributes that are set on this object
*
- * Not that the returned collection is correct at the time the method is called, but will not reflect future
+ * Note that the returned collection is correct at the time the method is called, but will not reflect future
* additions or removals when they occur
*
* @return the collection of attribute names
@@ -226,4 +227,20 @@ public interface ConfiguredObject
* @return the Statistics holder for the ConfiguredObject (or null if none exists)
*/
Statistics getStatistics();
+
+ /**
+ * Return children of the ConfiguredObject of the given class
+ *
+ * @param clazz the class of the children to return
+ * @return the children
+ *
+ * @throws NullPointerException if the supplied class null
+ *
+ */
+ <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz);
+
+
+ <C extends ConfiguredObject> C createChild(Class<C> childClass,
+ Map<String, Object> attributes,
+ ConfiguredObject... otherParents);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java
new file mode 100644
index 0000000000..6a7d6f8f7b
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java
@@ -0,0 +1,38 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.util.Collection;
+
+public class ConfiguredObjectFinder
+{
+ public static <C extends ConfiguredObject> C findConfiguredObjectByName(Collection<C> configuredObjects, String name)
+ {
+ for (C configuredObject : configuredObjects)
+ {
+ if (name.equals(configuredObject.getName()))
+ {
+ return configuredObject;
+ }
+ }
+ return null;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Connection.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Connection.java
new file mode 100644
index 0000000000..aaf6007afd
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Connection.java
@@ -0,0 +1,107 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public interface Connection extends ConfiguredObject
+{
+
+ // Statistics
+
+ String BYTES_IN = "bytesIn";
+ String BYTES_OUT = "bytesOut";
+ String LAST_IO_TIME = "lastIoTime";
+ String LOCAL_TRANSACTION_BEGINS = "localTransactionBegins";
+ String LOCAL_TRANSACTION_ROLLBACKS = "localTransactionRollbacks";
+ String MESSAGES_IN = "messagesIn";
+ String MESSAGES_OUT = "messagesOut";
+ String SESSION_COUNT = "sessionCount";
+ String STATE_CHANGED = "stateChanged";
+ String XA_TRANSACTION_BRANCH_ENDS = "xaTransactionBranchEnds";
+ String XA_TRANSACTION_BRANCH_STARTS = "xaTransactionBranchStarts";
+ String XA_TRANSACTION_BRANCH_SUSPENDS = "xaTransactionBranchSuspends";
+
+ public static final Collection<String> AVAILABLE_STATISTICS =
+ Collections.unmodifiableCollection(
+ Arrays.asList(BYTES_IN,
+ BYTES_OUT,
+ LAST_IO_TIME,
+ LOCAL_TRANSACTION_BEGINS,
+ LOCAL_TRANSACTION_ROLLBACKS,
+ MESSAGES_IN,
+ MESSAGES_OUT,
+ SESSION_COUNT,
+ STATE_CHANGED,
+ XA_TRANSACTION_BRANCH_ENDS,
+ XA_TRANSACTION_BRANCH_STARTS,
+ XA_TRANSACTION_BRANCH_SUSPENDS));
+
+ // Attributes
+
+ public static final String ID = "id";
+ 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 CLIENT_ID = "clientId";
+ public static final String CLIENT_VERSION = "clientVersion";
+ public static final String INCOMING = "incoming";
+ public static final String LOCAL_ADDRESS = "localAddress";
+ public static final String PRINCIPAL = "principal";
+ public static final String PROPERTIES = "properties";
+ public static final String REMOTE_ADDRESS = "remoteAddress";
+ public static final String REMOTE_PROCESS_NAME = "remoteProcessName";
+ public static final String REMOTE_PROCESS_PID = "remoteProcessPid";
+ public static final String SESSION_COUNT_LIMIT = "sessionCountLimit";
+
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableCollection(
+ Arrays.asList( ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ CLIENT_ID,
+ CLIENT_VERSION,
+ INCOMING,
+ LOCAL_ADDRESS,
+ PRINCIPAL,
+ PROPERTIES,
+ REMOTE_ADDRESS,
+ REMOTE_PROCESS_NAME,
+ REMOTE_PROCESS_PID,
+ SESSION_COUNT_LIMIT));
+
+ //children
+ Collection<Session> getSessions();
+
+ void delete();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Event.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Event.java
new file mode 100644
index 0000000000..91b684f06e
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Event.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.server.model;
+
+abstract public class Event<T extends EventType>
+{
+ abstract public T getEventType();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/EventType.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/EventType.java
new file mode 100644
index 0000000000..edd5ce4250
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/EventType.java
@@ -0,0 +1,60 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.model;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A type of event generated by a ConfiguredObject.
+ */
+public abstract class EventType<T extends EventType<T>>
+{
+ private static final Map<Class<? extends EventType>, Integer> EVENT_TYPES =
+ new HashMap<Class<? extends EventType>, Integer>();
+
+ private final int _classId;
+
+ protected EventType()
+ {
+ synchronized (EVENT_TYPES)
+ {
+ if(EVENT_TYPES.containsKey(getClass()))
+ {
+ throw new IllegalArgumentException("Cannot define more one instance of the same EventType " +
+ getClass().getName());
+ }
+ else
+ {
+ _classId = EVENT_TYPES.size();
+ EVENT_TYPES.put(getClass(), _classId);
+ }
+ }
+ }
+
+ public final int getId()
+ {
+ return _classId;
+ }
+
+ abstract public Event<T> newEvent();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java
index e872273d05..e63c71e955 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java
@@ -77,7 +77,7 @@ public interface Exchange extends ConfiguredObject
//children
Collection<Binding> getBindings();
Collection<Publisher> getPublishers();
-
+
//operations
Binding createBinding(String bindingKey,
Queue queue,
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java
new file mode 100644
index 0000000000..fd429321c8
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.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.model;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Model
+{
+ private static final Map<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>>
+ PARENTS = new HashMap<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>>();
+
+
+ private static final Map<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>>
+ CHILDREN = new HashMap<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>>();
+
+ static void addRelationship(Class<? extends ConfiguredObject> parent, Class<? extends ConfiguredObject> child)
+ {
+ Collection<Class<? extends ConfiguredObject>> parents = PARENTS.get(child);
+ if(parents == null)
+ {
+ parents = new ArrayList<Class<? extends ConfiguredObject>>();
+ PARENTS.put(child, parents);
+ }
+ parents.add(parent);
+
+ Collection<Class<? extends ConfiguredObject>> children = CHILDREN.get(parent);
+ if(children == null)
+ {
+ children = new ArrayList<Class<? extends ConfiguredObject>>();
+ CHILDREN.put(parent, children);
+ }
+ children.add(child);
+ }
+
+ static
+ {
+ addRelationship(Broker.class, VirtualHost.class);
+ addRelationship(Broker.class, Port.class);
+ addRelationship(Broker.class, AuthenticationProvider.class);
+
+ addRelationship(VirtualHost.class, Exchange.class);
+ addRelationship(VirtualHost.class, Queue.class);
+ addRelationship(VirtualHost.class, Connection.class);
+ addRelationship(VirtualHost.class, VirtualHostAlias.class);
+
+ addRelationship(AuthenticationProvider.class, User.class);
+
+ addRelationship(Connection.class, Session.class);
+
+ addRelationship(Exchange.class, Binding.class);
+ addRelationship(Exchange.class, Publisher.class);
+
+ addRelationship(Queue.class, Binding.class);
+ addRelationship(Queue.class, Consumer.class);
+
+ addRelationship(Session.class, Consumer.class);
+ addRelationship(Session.class, Publisher.class);
+
+ }
+
+ public static Collection<Class<? extends ConfiguredObject>> getParentTypes(Class<? extends ConfiguredObject> child)
+ {
+ Collection<Class<? extends ConfiguredObject>> parentTypes = PARENTS.get(child);
+ return parentTypes == null ? Collections.EMPTY_LIST
+ : Collections.unmodifiableCollection(parentTypes);
+ }
+
+ public static Collection<Class<? extends ConfiguredObject>> getChildTypes(Class<? extends ConfiguredObject> parent)
+ {
+ Collection<Class<? extends ConfiguredObject>> childTypes = CHILDREN.get(parent);
+ return childTypes == null ? Collections.EMPTY_LIST
+ : Collections.unmodifiableCollection(childTypes);
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PasswordCredentialManagingAuthenticationProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PasswordCredentialManagingAuthenticationProvider.java
new file mode 100644
index 0000000000..1027e5ce8c
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PasswordCredentialManagingAuthenticationProvider.java
@@ -0,0 +1,46 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.security.auth.login.AccountNotFoundException;
+
+public interface PasswordCredentialManagingAuthenticationProvider extends AuthenticationProvider
+{
+ boolean createUser(String username, String password, Map<String, String> attributes);
+
+ void deleteUser(String user) throws AccountNotFoundException;
+
+ void setPassword(String username, String password) throws AccountNotFoundException;
+
+ Map<String, Map<String,String>> getUsers();
+
+ /**
+ * Refreshes the cache of user and password data from the underlying storage.
+ *
+ * If there is a failure whilst reloading the data, the implementation must
+ * throw an {@link IOException} and revert to using the previous cached username
+ * and password data. In this way, the broker will remain usable.
+ */
+ void reload() throws IOException;
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java
new file mode 100644
index 0000000000..50c0ebcd14
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.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.server.model;
+
+import java.security.AccessControlException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public interface Port 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";
+ String BINDING_ADDRESS = "bindingAddress";
+ String PORT = "port";
+ String PROTOCOLS = "protocols";
+ String TRANSPORTS = "transports";
+
+ // Attributes
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableList(
+ Arrays.asList(
+ ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ BINDING_ADDRESS,
+ PORT,
+ PROTOCOLS,
+ TRANSPORTS
+ ));
+
+
+ String getBindingAddress();
+
+ int getPort();
+
+ Collection<Transport> getTransports();
+
+ void addTransport(Transport transport) throws IllegalStateException,
+ AccessControlException,
+ IllegalArgumentException;
+
+ Transport removeTransport(Transport transport) throws IllegalStateException,
+ AccessControlException,
+ IllegalArgumentException;
+
+
+ Collection<Protocol> getProtocols();
+
+ void addProtocol(Protocol protocol) throws IllegalStateException,
+ AccessControlException,
+ IllegalArgumentException;
+
+ Protocol removeProtocol(Protocol protocol) throws IllegalStateException,
+ AccessControlException,
+ IllegalArgumentException;
+
+
+ //children
+ Collection<VirtualHostAlias> getVirtualHostBindings();
+ Collection<Connection> getConnections();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java
new file mode 100644
index 0000000000..fecbcec194
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.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.model;
+
+public enum Protocol
+{
+ AMQP_0_8,
+ AMQP_0_9,
+ AMQP_0_9_1,
+ AMQP_0_10,
+ AMQP_1_0,
+ JMX,
+ HTTP
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java
index 7c4f0de22b..5dda4d66cd 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java
@@ -25,7 +25,6 @@ import java.util.Collection;
import java.util.Collections;
import org.apache.qpid.server.queue.QueueEntryVisitor;
-
public interface Queue extends ConfiguredObject
{
public static final String BINDING_COUNT = "bindingCount";
@@ -71,6 +70,7 @@ public interface Queue 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";
@@ -78,6 +78,7 @@ public interface Queue extends ConfiguredObject
public static final String TIME_TO_LIVE = "timeToLive";
public static final String CREATED = "created";
public static final String UPDATED = "updated";
+ public static final String ARGUMENTS = "arguments";
public static final String ALERT_REPEAT_GAP = "alertRepeatGap";
public static final String ALERT_THRESHOLD_MESSAGE_AGE = "alertThresholdMessageAge";
@@ -106,6 +107,7 @@ public interface Queue extends ConfiguredObject
Collections.unmodifiableList(
Arrays.asList(ID,
NAME,
+ DESCRIPTION,
STATE,
DURABLE,
LIFETIME_POLICY,
@@ -143,4 +145,6 @@ public interface Queue extends ConfiguredObject
void visit(QueueEntryVisitor visitor);
void delete();
+
+ void setNotificationListener(QueueNotificationListener listener);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/QueueNotificationListener.java
index 959ca03c80..ab601f685c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/QueueNotificationListener.java
@@ -18,10 +18,11 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.model;
+import org.apache.qpid.server.queue.NotificationCheck;
public interface QueueNotificationListener
{
- void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg);
+ void notifyClients(NotificationCheck notification, Queue queue, String notificationMsg);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Session.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Session.java
new file mode 100644
index 0000000000..e813d0c129
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Session.java
@@ -0,0 +1,82 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public interface Session extends ConfiguredObject
+{
+ // Statistics
+
+ public static final String BYTES_IN = "bytesIn";
+ public static final String BYTES_OUT = "bytesOut";
+ public static final String CONSUMER_COUNT = "consumerCount";
+ public static final String LOCAL_TRANSACTION_BEGINS = "localTransactionBegins";
+ public static final String LOCAL_TRANSACTION_OPEN = "localTransactionOpen";
+ public static final String LOCAL_TRANSACTION_ROLLBACKS = "localTransactionRollbacks";
+ public static final String STATE_CHANGED = "stateChanged";
+ public static final String UNACKNOWLEDGED_BYTES = "unacknowledgedBytes";
+ public static final String UNACKNOWLEDGED_MESSAGES = "unacknowledgedMessages";
+ public static final String XA_TRANSACTION_BRANCH_ENDS = "xaTransactionBranchEnds";
+ public static final String XA_TRANSACTION_BRANCH_STARTS = "xaTransactionBranchStarts";
+ public static final String XA_TRANSACTION_BRANCH_SUSPENDS = "xaTransactionBranchSuspends";
+
+ public static final Collection<String> AVAILABLE_STATISTICS =
+ Collections.unmodifiableCollection(Arrays.asList(BYTES_IN, BYTES_OUT, CONSUMER_COUNT,
+ LOCAL_TRANSACTION_BEGINS,
+ LOCAL_TRANSACTION_OPEN,
+ LOCAL_TRANSACTION_ROLLBACKS, STATE_CHANGED,
+ UNACKNOWLEDGED_BYTES, UNACKNOWLEDGED_MESSAGES,
+ XA_TRANSACTION_BRANCH_ENDS, XA_TRANSACTION_BRANCH_STARTS,
+ XA_TRANSACTION_BRANCH_SUSPENDS));
+
+
+ public static final String ID = "id";
+ 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 CHANNEL_ID = "channelId";
+ // PRODUCER_FLOW_BLOCKED is exposed as an interim step. We will expose attribute(s) that exposing
+ // available credit of both producer and consumer sides.
+ public static final String PRODUCER_FLOW_BLOCKED = "producerFlowBlocked";
+
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableCollection(Arrays.asList(ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ CHANNEL_ID,
+ PRODUCER_FLOW_BLOCKED));
+
+ Collection<Consumer> getSubscriptions();
+ Collection<Publisher> getPublishers();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java
index 2cb81eae82..92d6f47741 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java
@@ -1,8 +1,4 @@
-package org.apache.qpid.server.model;
-
-import java.util.Collection;
-
-/**
+/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
@@ -18,6 +14,11 @@ import java.util.Collection;
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+package org.apache.qpid.server.model;
+
+import java.util.Collection;
+
public interface Statistics
{
Collection<String> getStatisticNames();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java
new file mode 100644
index 0000000000..03cd46be01
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Transport.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.server.model;
+
+public enum Transport
+{
+ TCP,
+ SSL
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java
index d8493c6df4..920088d61c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java
@@ -40,11 +40,11 @@ public class UUIDGenerator
return UUID.nameUUIDFromBytes(sb.toString().getBytes());
}
- public static UUID generateExchangeUUID(String echangeName, String virtualHostName)
+ public static UUID generateExchangeUUID(String exchangeName, String virtualHostName)
{
- if(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString().equals(echangeName) || echangeName.startsWith("amq.") || echangeName.startsWith("qpid."))
+ if(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString().equals(exchangeName) || exchangeName.startsWith("amq.") || exchangeName.startsWith("qpid."))
{
- return generateUUID(echangeName, virtualHostName);
+ return generateUUID(exchangeName, virtualHostName);
}
else
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/User.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/User.java
new file mode 100644
index 0000000000..d97bf46d31
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/User.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.model;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public interface User 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";
+ String PASSWORD = "password";
+
+ // Attributes
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableList(
+ Arrays.asList(
+ ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ PASSWORD
+ ));
+
+ public String getPassword();
+
+ public void setPassword(String password);
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java
new file mode 100644
index 0000000000..53faefc954
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java
@@ -0,0 +1,154 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import org.apache.qpid.server.queue.QueueEntry;
+import java.security.AccessControlException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+public interface VirtualHost extends ConfiguredObject
+{
+ // Statistics
+
+ public static final String BYTES_IN = "bytesIn";
+ public static final String BYTES_OUT = "bytesOut";
+ public static final String BYTES_RETAINED = "bytesRetained";
+ public static final String LOCAL_TRANSACTION_BEGINS = "localTransactionBegins";
+ public static final String LOCAL_TRANSACTION_ROLLBACKS = "localTransactionRollbacks";
+ public static final String MESSAGES_IN = "messagesIn";
+ public static final String MESSAGES_OUT = "messagesOut";
+ public static final String MESSAGES_RETAINED = "messagesRetained";
+ public static final String STATE_CHANGED = "stateChanged";
+ public static final String XA_TRANSACTION_BRANCH_ENDS = "xaTransactionBranchEnds";
+ public static final String XA_TRANSACTION_BRANCH_STARTS = "xaTransactionBranchStarts";
+ public static final String XA_TRANSACTION_BRANCH_SUSPENDS = "xaTransactionBranchSuspends";
+ public static final String QUEUE_COUNT = "queueCount";
+ public static final String EXCHANGE_COUNT = "exchangeCount";
+ public static final String CONNECTION_COUNT = "connectionCount";
+
+ public static final Collection<String> AVAILABLE_STATISTICS =
+ Collections.unmodifiableList(
+ Arrays.asList(BYTES_IN, BYTES_OUT, BYTES_RETAINED, LOCAL_TRANSACTION_BEGINS,
+ LOCAL_TRANSACTION_ROLLBACKS, MESSAGES_IN, MESSAGES_OUT, MESSAGES_RETAINED, STATE_CHANGED,
+ XA_TRANSACTION_BRANCH_ENDS, XA_TRANSACTION_BRANCH_STARTS, XA_TRANSACTION_BRANCH_SUSPENDS,
+ QUEUE_COUNT, EXCHANGE_COUNT, CONNECTION_COUNT));
+
+ String ALERT_REPEAT_GAP = "alertRepeatGap";
+ String ALERT_THRESHOLD_MESSAGE_AGE = "alertThresholdMessageAge";
+ String ALERT_THRESHOLD_MESSAGE_SIZE = "alertThresholdMessageSize";
+ 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 SUPPORTED_EXCHANGE_TYPES = "supportedExchangeTypes";
+ String SUPPORTED_QUEUE_TYPES = "supportedQueueTypes";
+ 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<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableList(
+ Arrays.asList(
+ ID,
+ NAME,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ 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_TRANSACTION_IDLE_TIMEOUT_CLOSE,
+ STORE_TRANSACTION_IDLE_TIMEOUT_WARN,
+ STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE,
+ STORE_TRANSACTION_OPEN_TIMEOUT_WARN,
+ ALERT_REPEAT_GAP,
+ ALERT_THRESHOLD_MESSAGE_AGE,
+ ALERT_THRESHOLD_MESSAGE_SIZE,
+ ALERT_THRESHOLD_QUEUE_DEPTH_BYTES,
+ ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES));
+
+
+
+ String getReplicationGroupName();
+
+ //children
+ Collection<VirtualHostAlias> getAliases();
+ Collection<Connection> getConnections();
+ Collection<Queue> getQueues();
+ Collection<Exchange> getExchanges();
+
+ Exchange createExchange(String name, State initialState, boolean durable,
+ LifetimePolicy lifetime, long ttl, String type, Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException;
+
+ Queue createQueue(String name, State initialState, boolean durable,
+ boolean exclusive, LifetimePolicy lifetime, long ttl, Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException;
+
+ void deleteQueue(Queue queue) throws AccessControlException, IllegalStateException;
+
+ Collection<String> getExchangeTypes();
+
+ public static interface Transaction
+ {
+ void dequeue(QueueEntry entry);
+
+ void copy(QueueEntry entry, Queue queue);
+
+ void move(QueueEntry entry, Queue queue);
+
+ }
+
+ public static interface TransactionalOperation
+ {
+ void withinTransaction(Transaction txn);
+ }
+
+ void executeTransaction(TransactionalOperation op);
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java
new file mode 100644
index 0000000000..31403d78e5
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.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.model;
+
+import java.security.AccessControlException;
+import java.util.Collection;
+
+public interface VirtualHostAlias extends ConfiguredObject
+{
+ // parents
+ Port getPort();
+ VirtualHost getVirtualHost();
+
+ // children
+ Collection<AuthenticationMethod> getAuthenticationMethods();
+
+
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java
new file mode 100644
index 0000000000..78880c232d
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java
@@ -0,0 +1,293 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+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;
+
+abstract class AbstractAdapter implements ConfiguredObject
+{
+ private final Map<String,Object> _attributes = new HashMap<String, Object>();
+ private final Map<Class<? extends ConfiguredObject>, ConfiguredObject> _parents =
+ new HashMap<Class<? extends ConfiguredObject>, ConfiguredObject>();
+ private final Collection<ConfigurationChangeListener> _changeListeners =
+ new ArrayList<ConfigurationChangeListener>();
+
+ private final UUID _id;
+
+ protected AbstractAdapter(String... names)
+ {
+ StringBuilder sb = new StringBuilder();
+ for(String name : names)
+ {
+ sb.append('/').append(name);
+ }
+ _id = UUID.nameUUIDFromBytes(sb.toString().getBytes());
+ }
+
+ protected AbstractAdapter()
+ {
+ _id = UUID.randomUUID();
+ }
+
+ static String getStringAttribute(String name, Map<String,Object> attributes, String defaultVal)
+ {
+ final Object value = attributes.get(name);
+ return value == null ? defaultVal : String.valueOf(value);
+ }
+
+ static Map getMapAttribute(String name, Map<String,Object> attributes, Map defaultVal)
+ {
+ final Object value = attributes.get(name);
+ if(value == null)
+ {
+ return defaultVal;
+ }
+ else if(value instanceof Map)
+ {
+ return (Map) value;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Map");
+ }
+ }
+
+
+ static <E extends Enum> E getEnumAttribute(Class<E> clazz, String name, Map<String,Object> 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());
+ }
+ }
+
+ static Boolean getBooleanAttribute(String name, Map<String,Object> attributes, Boolean defaultValue)
+ {
+ 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");
+ }
+ }
+
+ static Integer getIntegerAttribute(String name, Map<String,Object> attributes, Integer defaultValue)
+ {
+ 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");
+ }
+ }
+
+ static Long getLongAttribute(String name, Map<String,Object> attributes, Long defaultValue)
+ {
+ Object obj = attributes.get(name);
+ 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 final UUID getId()
+ {
+ return _id;
+ }
+
+ public State getDesiredState()
+ {
+ return null; //TODO
+ }
+
+ public State setDesiredState(final State currentState, final State desiredState)
+ throws IllegalStateTransitionException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public void addChangeListener(final ConfigurationChangeListener listener)
+ {
+ if(listener == null)
+ {
+ throw new NullPointerException("Cannot add a null listener");
+ }
+ synchronized (this)
+ {
+ if(!_changeListeners.contains(listener))
+ {
+ _changeListeners.add(listener);
+ }
+ }
+ }
+
+ public boolean removeChangeListener(final ConfigurationChangeListener listener)
+ {
+ if(listener == null)
+ {
+ throw new NullPointerException("Cannot remove a null listener");
+ }
+ synchronized (this)
+ {
+ return _changeListeners.remove(listener);
+ }
+ }
+
+
+ protected void childAdded(ConfiguredObject child)
+ {
+ synchronized (this)
+ {
+ for(ConfigurationChangeListener listener : _changeListeners)
+ {
+ listener.childAdded(this, child);
+ }
+ }
+ }
+
+
+ protected void childRemoved(ConfiguredObject child)
+ {
+ synchronized (this)
+ {
+ for(ConfigurationChangeListener listener : _changeListeners)
+ {
+ listener.childRemoved(this, child);
+ }
+ }
+ }
+
+ public Object getAttribute(final String name)
+ {
+ synchronized (this)
+ {
+ return _attributes.get(name);
+ }
+ }
+
+ public Object setAttribute(final String name, final Object expected, final Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ synchronized (this)
+ {
+ Object currentValue = _attributes.get(name);
+ if((currentValue == null && expected == null)
+ || (currentValue != null && currentValue.equals(expected)))
+ {
+ _attributes.put(name, desired);
+ return desired;
+ }
+ else
+ {
+ return currentValue;
+ }
+ }
+ }
+
+ public <T extends ConfiguredObject> T getParent(final Class<T> clazz)
+ {
+ synchronized (this)
+ {
+ return (T) _parents.get(clazz);
+ }
+ }
+
+ protected <T extends ConfiguredObject> void addParent(Class<T> clazz, T parent)
+ {
+ synchronized (this)
+ {
+ _parents.put(clazz, parent);
+ }
+ }
+
+ protected <T extends ConfiguredObject> void removeParent(Class<T> clazz)
+ {
+ synchronized (this)
+ {
+ _parents.remove(clazz);
+ }
+ }
+
+ public Collection<String> getAttributeNames()
+ {
+ synchronized(_attributes)
+ {
+ return new ArrayList<String>(_attributes.keySet());
+ }
+ }
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java
new file mode 100644
index 0000000000..8a75818f04
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java
@@ -0,0 +1,487 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.io.IOException;
+import java.security.AccessControlException;
+import java.security.Principal;
+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 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.security.access.Operation;
+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;
+
+public abstract class AuthenticationProviderAdapter<T extends AuthenticationManager> extends AbstractAdapter implements AuthenticationProvider
+{
+ private static final Logger LOGGER = Logger.getLogger(AuthenticationProviderAdapter.class);
+
+ private final BrokerAdapter _broker;
+ private final T _authManager;
+
+ private AuthenticationProviderAdapter(BrokerAdapter brokerAdapter,
+ final T authManager)
+ {
+ _broker = brokerAdapter;
+ _authManager = authManager;
+ }
+
+ public static AuthenticationProviderAdapter createAuthenticationProviderAdapter(BrokerAdapter brokerAdapter,
+ final AuthenticationManager authManager)
+ {
+ return authManager instanceof PrincipalDatabaseAuthenticationManager
+ ? new PrincipalDatabaseAuthenticationManagerAdapter(brokerAdapter, (PrincipalDatabaseAuthenticationManager) authManager)
+ : new SimpleAuthenticationProviderAdapter(brokerAdapter, authManager);
+ }
+
+ T getAuthManager()
+ {
+ return _authManager;
+ }
+
+ @Override
+ public Collection<VirtualHostAlias> getVirtualHostPortBindings()
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public String getName()
+ {
+ return _authManager.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<String> getAttributeNames()
+ {
+ return AuthenticationProvider.AVAILABLE_ATTRIBUTES;
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+ if(TYPE.equals(name))
+ {
+ return _authManager.getClass().getSimpleName();
+ }
+ 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 extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ return null;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass,
+ Map<String, Object> attributes,
+ ConfiguredObject... otherParents)
+ {
+ return null;
+ }
+
+ private static class SimpleAuthenticationProviderAdapter extends AuthenticationProviderAdapter<AuthenticationManager>
+ {
+ public SimpleAuthenticationProviderAdapter(
+ BrokerAdapter brokerAdapter, AuthenticationManager authManager)
+ {
+ super(brokerAdapter,authManager);
+ }
+ }
+
+ private static class PrincipalDatabaseAuthenticationManagerAdapter
+ extends AuthenticationProviderAdapter<PrincipalDatabaseAuthenticationManager>
+ implements PasswordCredentialManagingAuthenticationProvider
+ {
+ public PrincipalDatabaseAuthenticationManagerAdapter(
+ BrokerAdapter brokerAdapter, PrincipalDatabaseAuthenticationManager authManager)
+ {
+ super(brokerAdapter, authManager);
+ }
+
+ @Override
+ public boolean createUser(String username, String password, Map<String, String> attributes)
+ {
+ return getPrincipalDatabase().createPrincipal(new UsernamePrincipal(username), password.toCharArray());
+ }
+
+ @Override
+ public void deleteUser(String username) throws AccountNotFoundException
+ {
+ if(getSecurityManager().authoriseMethod(Operation.DELETE,
+ "UserManagement",
+ "deleteUser"))
+ {
+
+ getPrincipalDatabase().deletePrincipal(new UsernamePrincipal(username));
+ }
+ else
+ {
+ throw new AccessControlException("Cannot delete user " + username);
+ }
+ }
+
+ private org.apache.qpid.server.security.SecurityManager getSecurityManager()
+ {
+ return ApplicationRegistry.getInstance().getSecurityManager();
+ }
+
+ private PrincipalDatabase getPrincipalDatabase()
+ {
+ return getAuthManager().getPrincipalDatabase();
+ }
+
+ @Override
+ public void setPassword(String username, String password) throws AccountNotFoundException
+ {
+ getPrincipalDatabase().updatePassword(new UsernamePrincipal(username), password.toCharArray());
+ }
+
+ public void reload() throws IOException
+ {
+ if(getSecurityManager().authoriseMethod(Operation.UPDATE, "UserManagement", "reload"))
+ {
+ getPrincipalDatabase().reload();
+ }
+ else
+ {
+ throw new AccessControlException("Do not have permission to reload principal database");
+ }
+ }
+
+ @Override
+ public Map<String, Map<String, String>> getUsers()
+ {
+
+ Map<String, Map<String,String>> users = new HashMap<String, Map<String, String>>();
+ for(Principal principal : getPrincipalDatabase().getUsers())
+ {
+ users.put(principal.getName(), Collections.EMPTY_MAP);
+ }
+ return users;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass,
+ Map<String, Object> attributes,
+ ConfiguredObject... otherParents)
+ {
+ if(childClass == User.class)
+ {
+ Principal p = new UsernamePrincipal((String) attributes.get("name"));
+ if(getSecurityManager().authoriseMethod(Operation.UPDATE, "UserManagement", "createUser"))
+ {
+ if(getPrincipalDatabase().createPrincipal(p, ((String)attributes.get("password")).toCharArray()))
+ {
+ return (C) new PrincipalAdapter(p);
+ }
+ }
+ else
+ {
+ throw new AccessControlException("Do not have permission to create a new user");
+ }
+
+ }
+
+ return super.createChild(childClass, attributes, otherParents);
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == User.class)
+ {
+ List<Principal> users = getPrincipalDatabase().getUsers();
+ Collection<User> principals = new ArrayList<User>(users.size());
+ for(Principal user : users)
+ {
+ principals.add(new PrincipalAdapter(user));
+ }
+ return (Collection<C>) Collections.unmodifiableCollection(principals);
+ }
+ else
+ {
+ return super.getChildren(clazz);
+ }
+ }
+
+ private class PrincipalAdapter extends AbstractAdapter implements User
+ {
+ private final Principal _user;
+
+
+ public PrincipalAdapter(Principal user)
+ {
+ super(PrincipalDatabaseAuthenticationManagerAdapter.this.getName(), user.getName());
+ _user = user;
+
+ }
+
+ @Override
+ public String getPassword()
+ {
+ return null;
+ }
+
+ @Override
+ public void setPassword(String password)
+ {
+ try
+ {
+ PrincipalDatabaseAuthenticationManagerAdapter.this.setPassword(_user.getName(), password);
+ }
+ catch (AccountNotFoundException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public String getName()
+ {
+ return _user.getName();
+ }
+
+ @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 <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ return null;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass,
+ Map<String, Object> attributes,
+ ConfiguredObject... otherParents)
+ {
+ return null;
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return User.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 Object setAttribute(String name, Object expected, Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ if(name.equals(PASSWORD))
+ {
+ setPassword((String)desired);
+ }
+ return super.setAttribute(name,
+ expected,
+ desired);
+ }
+
+ @Override
+ public State setDesiredState(State currentState, State desiredState)
+ throws IllegalStateTransitionException, AccessControlException
+ {
+ if(desiredState == State.DELETED)
+ {
+ try
+ {
+ deleteUser(_user.getName());
+ }
+ catch (AccountNotFoundException e)
+ {
+ LOGGER.warn("Failed to delete user " + _user, e);
+ }
+ return State.DELETED;
+ }
+ return super.setDesiredState(currentState, desiredState);
+ }
+ }
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java
new file mode 100644
index 0000000000..d3d04be70f
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.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.security.AccessControlException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.qpid.AMQInternalException;
+import org.apache.qpid.AMQSecurityException;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
+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.State;
+import org.apache.qpid.server.model.Statistics;
+
+final class BindingAdapter extends AbstractAdapter implements Binding
+{
+ private final org.apache.qpid.server.binding.Binding _binding;
+ private Statistics _statistics = NoStatistics.getInstance();
+ private final ExchangeAdapter _exchange;
+ private QueueAdapter _queue;
+
+ public BindingAdapter(final org.apache.qpid.server.binding.Binding binding,
+ ExchangeAdapter exchangeAdapter,
+ QueueAdapter queueAdapter)
+ {
+ super(exchangeAdapter.getExchange().getVirtualHost().getName(),
+ exchangeAdapter.getName(),
+ queueAdapter.getName(),
+ binding.getBindingKey());
+ _binding = binding;
+ _exchange = exchangeAdapter;
+ _queue = queueAdapter;
+ addParent(Queue.class, queueAdapter);
+ addParent(Exchange.class, exchangeAdapter);
+ }
+
+
+ public ExchangeAdapter getExchange()
+ {
+ return _exchange;
+ }
+
+ public QueueAdapter getQueue()
+ {
+ return _queue;
+ }
+
+ public String getName()
+ {
+ return _binding.getBindingKey();
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+ public boolean isDurable()
+ {
+ return _binding.getQueue().isDurable() && _binding.getExchange().isDurable();
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ //TODO
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public long getTimeToLive()
+ {
+ return 0; //TODO
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0; //TODO
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new IllegalArgumentException("Cannot add children to a binding");
+ }
+
+ public Map<String, Object> getArguments()
+ {
+ return new HashMap<String, Object> (_binding.getArguments());
+ }
+
+ public void delete()
+ {
+ try
+ {
+ _queue.getAMQQueue().getVirtualHost().getBindingFactory().removeBinding(_binding);
+ }
+ catch(AMQSecurityException e)
+ {
+ throw new AccessControlException(e.getMessage());
+ }
+ catch(AMQInternalException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public Object getAttribute(final String name)
+ {
+ if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(NAME.equals(name))
+ {
+ return getName();
+ }
+ else if(STATE.equals(name))
+ {
+
+ }
+ else if(DURABLE.equals(name))
+ {
+ return _queue.isDurable() && _exchange.isDurable();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return _queue.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE || _exchange.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT;
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+
+ }
+ else if(CREATED.equals(name))
+ {
+
+ }
+ else if(UPDATED.equals(name))
+ {
+
+ }
+ else if(EXCHANGE.equals(name))
+ {
+ return _exchange.getName();
+ }
+ else if(QUEUE.equals(name))
+ {
+ return _queue.getName();
+ }
+ else if(ARGUMENTS.equals(name))
+ {
+ return getArguments();
+ }
+
+ 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<String> getAttributeNames()
+ {
+ return Binding.AVAILABLE_ATTRIBUTES;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
new file mode 100644
index 0000000000..ad88dbc613
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
@@ -0,0 +1,484 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.net.InetSocketAddress;
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.qpid.common.QpidProperties;
+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.LifetimePolicy;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+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.virtualhost.VirtualHostRegistry;
+
+public class BrokerAdapter extends AbstractAdapter implements Broker, VirtualHostRegistry.RegistryChangeListener,
+ IApplicationRegistry.PortBindingListener,
+ IAuthenticationManagerRegistry.RegistryChangeListener
+{
+
+
+ private final IApplicationRegistry _applicationRegistry;
+ private String _name;
+ private final Map<org.apache.qpid.server.virtualhost.VirtualHost, VirtualHostAdapter> _vhostAdapters =
+ new HashMap<org.apache.qpid.server.virtualhost.VirtualHost, VirtualHostAdapter>();
+ private final StatisticsAdapter _statistics;
+ private final Map<QpidAcceptor, PortAdapter> _portAdapters = new HashMap<QpidAcceptor, PortAdapter>();
+ private HTTPPortAdapter _httpManagementPort;
+ private final Map<AuthenticationManager, AuthenticationProviderAdapter> _authManagerAdapters =
+ new HashMap<AuthenticationManager, AuthenticationProviderAdapter>();
+
+
+ public BrokerAdapter(final IApplicationRegistry instance)
+ {
+ _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<org.apache.qpid.server.virtualhost.VirtualHost> actualVhosts =
+ _applicationRegistry.getVirtualHostRegistry().getVirtualHosts();
+ for(org.apache.qpid.server.virtualhost.VirtualHost vh : actualVhosts)
+ {
+ if(!_vhostAdapters.containsKey(vh))
+ {
+ _vhostAdapters.put(vh, new VirtualHostAdapter(this, vh));
+ }
+ }
+
+ }
+ }
+
+
+ public Collection<VirtualHost> getVirtualHosts()
+ {
+ synchronized(_vhostAdapters)
+ {
+ return new ArrayList<VirtualHost>(_vhostAdapters.values());
+ }
+
+ }
+ private void populatePorts()
+ {
+ synchronized (_portAdapters)
+ {
+ Map<InetSocketAddress, QpidAcceptor> acceptors = _applicationRegistry.getAcceptors();
+
+ for(Map.Entry<InetSocketAddress, QpidAcceptor> entry : acceptors.entrySet())
+ {
+ if(!_portAdapters.containsKey(entry.getValue()))
+ {
+ _portAdapters.put(entry.getValue(), new PortAdapter(this, entry.getValue(), entry.getKey()));
+ }
+ }
+ if(_applicationRegistry.useHTTPManagement())
+ {
+ _httpManagementPort = new HTTPPortAdapter(this, _applicationRegistry.getHTTPManagementPort());
+ }
+
+ }
+ }
+
+ public Collection<Port> getPorts()
+ {
+ synchronized (_portAdapters)
+ {
+ final ArrayList<Port> ports = new ArrayList<Port>(_portAdapters.values());
+ if(_httpManagementPort != null)
+ {
+ ports.add(_httpManagementPort);
+ }
+ return ports;
+ }
+ }
+
+ private void populateAuthenticationManagers()
+ {
+ synchronized (_authManagerAdapters)
+ {
+ IAuthenticationManagerRegistry authenticationManagerRegistry =
+ _applicationRegistry.getAuthenticationManagerRegistry();
+ if(authenticationManagerRegistry != null)
+ {
+ Map<String, AuthenticationManager> authenticationManagers =
+ authenticationManagerRegistry.getAvailableAuthenticationManagers();
+
+ for(Map.Entry<String, AuthenticationManager> entry : authenticationManagers.entrySet())
+ {
+ if(!_authManagerAdapters.containsKey(entry.getValue()))
+ {
+ _authManagerAdapters.put(entry.getValue(),
+ AuthenticationProviderAdapter.createAuthenticationProviderAdapter(this,
+ entry.getValue()));
+ }
+ }
+ }
+ }
+ }
+
+ public Collection<AuthenticationProvider> getAuthenticationProviders()
+ {
+ synchronized (_authManagerAdapters)
+ {
+ final ArrayList<AuthenticationProvider> authManagers =
+ new ArrayList<AuthenticationProvider>(_authManagerAdapters.values());
+ return authManagers;
+ }
+
+ }
+
+ public VirtualHost createVirtualHost(final String name,
+ final State initialState,
+ final boolean durable,
+ final LifetimePolicy lifetime,
+ final long ttl,
+ final Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public VirtualHost createVirtualHost(final Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public void deleteVirtualHost(final VirtualHost vhost)
+ throws AccessControlException, IllegalStateException
+ {
+ //TODO
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+
+ public boolean isDurable()
+ {
+ return true;
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ public long getTimeToLive()
+ {
+ return 0;
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == VirtualHost.class)
+ {
+ return (Collection<C>) getVirtualHosts();
+ }
+ else if(clazz == Port.class)
+ {
+ return (Collection<C>) getPorts();
+ }
+ else if(clazz == AuthenticationProvider.class)
+ {
+ return (Collection<C>) getAuthenticationProviders();
+ }
+
+ return Collections.emptySet();
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ if(childClass == VirtualHost.class)
+ {
+ return (C) createVirtualHost(attributes);
+ }
+ else if(childClass == Port.class)
+ {
+ return (C) createPort(attributes);
+ }
+ else if(childClass == AuthenticationProvider.class)
+ {
+ return (C) createAuthenticationProvider(attributes);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot create child of class " + childClass.getSimpleName());
+ }
+ }
+
+ private Port createPort(Map<String, Object> attributes)
+ {
+ // TODO
+ return null;
+ }
+
+ private AuthenticationProvider createAuthenticationProvider(Map<String,Object> attributes)
+ {
+ // TODO
+ return null;
+ }
+
+
+ public void virtualHostRegistered(org.apache.qpid.server.virtualhost.VirtualHost virtualHost)
+ {
+ VirtualHostAdapter adapter = null;
+ synchronized (_vhostAdapters)
+ {
+ if(!_vhostAdapters.containsKey(virtualHost))
+ {
+ adapter = new VirtualHostAdapter(this, virtualHost);
+ _vhostAdapters.put(virtualHost, adapter);
+ }
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+ }
+
+ public void virtualHostUnregistered(org.apache.qpid.server.virtualhost.VirtualHost virtualHost)
+ {
+ VirtualHostAdapter adapter = null;
+
+ synchronized (_vhostAdapters)
+ {
+ adapter = _vhostAdapters.remove(virtualHost);
+ }
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ @Override
+ public void authenticationManagerRegistered(AuthenticationManager authenticationManager)
+ {
+ AuthenticationProviderAdapter adapter = null;
+ synchronized (_authManagerAdapters)
+ {
+ if(!_authManagerAdapters.containsKey(authenticationManager))
+ {
+ adapter =
+ AuthenticationProviderAdapter.createAuthenticationProviderAdapter(this, authenticationManager);
+ _authManagerAdapters.put(authenticationManager, adapter);
+ }
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+ }
+
+ @Override
+ public void authenticationManagerUnregistered(AuthenticationManager authenticationManager)
+ {
+ AuthenticationProviderAdapter adapter;
+ synchronized (_authManagerAdapters)
+ {
+ adapter = _authManagerAdapters.remove(authenticationManager);
+ }
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+
+ @Override
+ public void bound(QpidAcceptor acceptor, InetSocketAddress bindAddress)
+ {
+ synchronized (_portAdapters)
+ {
+ if(!_portAdapters.containsKey(acceptor))
+ {
+ PortAdapter adapter = new PortAdapter(this, acceptor, bindAddress);
+ _portAdapters.put(acceptor, adapter);
+ childAdded(adapter);
+ }
+ }
+ }
+
+ @Override
+ public void unbound(QpidAcceptor acceptor)
+ {
+ PortAdapter adapter = null;
+
+ synchronized (_portAdapters)
+ {
+ adapter = _portAdapters.remove(acceptor);
+ }
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return AVAILABLE_ATTRIBUTES;
+ }
+
+ @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 State.ACTIVE;
+ }
+ else if(DURABLE.equals(name))
+ {
+ return isDurable();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+ // TODO
+ }
+ else if(CREATED.equals(name))
+ {
+ // TODO
+ }
+ else if(UPDATED.equals(name))
+ {
+ // TODO
+ }
+ else if(BUILD_VERSION.equals(name))
+ {
+ return QpidProperties.getBuildVersion();
+ }
+ else if(BYTES_RETAINED.equals(name))
+ {
+ // TODO
+ }
+ else if(OPERATING_SYSTEM.equals(name))
+ {
+ return System.getProperty("os.name") + " "
+ + System.getProperty("os.version") + " "
+ + System.getProperty("os.arch");
+ }
+ else if(PLATFORM.equals(name))
+ {
+ return System.getProperty("java.vendor") + " "
+ + System.getProperty("java.runtime.version", System.getProperty("java.version"));
+ }
+ else if(PROCESS_PID.equals(name))
+ {
+ // TODO
+ }
+ else if(PRODUCT_VERSION.equals(name))
+ {
+ return QpidProperties.getReleaseVersion();
+ }
+ else if(STATISTICS_ENABLED.equals(name))
+ {
+ // TODO
+ }
+ else if(SUPPORTED_STORE_TYPES.equals(name))
+ {
+ // TODO
+ }
+
+ 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.
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java
new file mode 100644
index 0000000000..8114156e3a
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java
@@ -0,0 +1,315 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQConstant;
+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.Session;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.protocol.AMQConnectionModel;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.stats.StatisticsGatherer;
+
+final class ConnectionAdapter extends AbstractAdapter implements Connection
+{
+
+
+
+
+ private AMQConnectionModel _connection;
+
+ private final Map<AMQSessionModel, SessionAdapter> _sessionAdapters =
+ new HashMap<AMQSessionModel, SessionAdapter>();
+ private final Statistics _statistics;
+
+ public ConnectionAdapter(final AMQConnectionModel conn)
+ {
+ _connection = conn;
+ _statistics = new ConnectionStatisticsAdapter(conn);
+ }
+
+ public Collection<Session> getSessions()
+ {
+ List<AMQSessionModel> actualSessions = _connection.getSessionModels();
+
+ synchronized (_sessionAdapters)
+ {
+ for(AMQSessionModel session : _sessionAdapters.keySet())
+ {
+ if(!actualSessions.contains(session))
+ {
+ _sessionAdapters.remove(session);
+ }
+ }
+ for(AMQSessionModel session : actualSessions)
+ {
+ if(!_sessionAdapters.containsKey(session))
+ {
+ _sessionAdapters.put(session, new SessionAdapter(session));
+ }
+ }
+ return new ArrayList<Session>(_sessionAdapters.values());
+ }
+ }
+
+ public void delete()
+ {
+ try
+ {
+ _connection.close(AMQConstant.CONNECTION_FORCED, "Connection closed by external action");
+ }
+ catch(AMQException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public String getName()
+ {
+ final String remoteAddressString = _connection.getRemoteAddressString();
+ return remoteAddressString.replaceAll("/","");
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+ public boolean isDurable()
+ {
+ return false; //TODO
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ //TODO
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return null; //TODO
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public long getTimeToLive()
+ {
+ return 0; //TODO
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0; //TODO
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+
+ if(name.equals(ID))
+ {
+ return getId();
+ }
+ else if (name.equals(NAME))
+ {
+ return getName();
+ }
+ else if(name.equals(CLIENT_ID))
+ {
+ return _connection.getClientId();
+ }
+ else if(name.equals(CLIENT_VERSION))
+ {
+ return _connection.getClientVersion();
+ }
+ else if(name.equals(INCOMING))
+ {
+
+ }
+ else if(name.equals(LOCAL_ADDRESS))
+ {
+
+ }
+ else if(name.equals(PRINCIPAL))
+ {
+ return _connection.getPrincipalAsString();
+ }
+ else if(name.equals(PROPERTIES))
+ {
+
+ }
+ else if(name.equals(REMOTE_ADDRESS))
+ {
+ return _connection.getRemoteAddressString();
+ }
+ else if(name.equals(REMOTE_PROCESS_NAME))
+ {
+
+ }
+ else if(name.equals(REMOTE_PROCESS_PID))
+ {
+
+ }
+ else if(name.equals(SESSION_COUNT_LIMIT))
+ {
+ return _connection.getSessionCountLimit();
+ }
+ 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<String> getAttributeNames()
+ {
+ final HashSet<String> attrNames = new HashSet<String>(super.getAttributeNames());
+ attrNames.addAll(Connection.AVAILABLE_ATTRIBUTES);
+ return Collections.unmodifiableCollection(attrNames);
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == Session.class)
+ {
+ return (Collection<C>) getSessions();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ if(childClass == Session.class)
+ {
+ throw new IllegalStateException();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot create a child of class " + childClass.getSimpleName());
+ }
+
+ }
+
+ private class ConnectionStatisticsAdapter extends StatisticsAdapter
+ {
+ public ConnectionStatisticsAdapter(StatisticsGatherer applicationRegistry)
+ {
+ super(applicationRegistry);
+ }
+
+ @Override
+ public Collection<String> getStatisticNames()
+ {
+ return Connection.AVAILABLE_STATISTICS;
+ }
+
+ @Override
+ public Object getStatistic(String name)
+ {
+ if(LAST_IO_TIME.equals(name))
+ {
+ return _connection.getLastIoTime();
+ }
+ else if(SESSION_COUNT.equals(name))
+ {
+ return _connection.getSessionModels().size();
+ }
+ return super.getStatistic(name);
+ }
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java
new file mode 100644
index 0000000000..6fb6f4971d
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.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.server.model.adapter;
+
+import java.util.Map;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Consumer;
+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.subscription.Subscription;
+
+import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.Collections;
+
+public class ConsumerAdapter extends AbstractAdapter implements Consumer
+{
+ private final Subscription _subscription;
+ private final QueueAdapter _queue;
+ private final ConsumerStatistics _statistics;
+
+ public ConsumerAdapter(final QueueAdapter queueAdapter, final Subscription subscription)
+ {
+ super(queueAdapter.getVirtualHost().getName(),
+ queueAdapter.getName(),
+ subscription.getSessionModel().getConnectionModel().getRemoteAddressString(),
+ String.valueOf(subscription.getSessionModel().getChannelId()),
+ subscription.getConsumerName() );
+
+ _subscription = subscription;
+ _queue = queueAdapter;
+ _statistics = new ConsumerStatistics();
+ //TODO
+ }
+
+ public String getName()
+ {
+ return _subscription.getConsumerName();
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+ public boolean isDurable()
+ {
+ return false; //TODO
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ //TODO
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return null; //TODO
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public long getTimeToLive()
+ {
+ return 0; //TODO
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0; //TODO
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ 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)
+ {
+ if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(NAME.equals(name))
+ {
+ return getName();
+ }
+ else if(STATE.equals(name))
+ {
+
+ }
+ else if(DURABLE.equals(name))
+ {
+ return false;
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return LifetimePolicy.AUTO_DELETE;
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+
+ }
+ else if(CREATED.equals(name))
+ {
+
+ }
+ else if(UPDATED.equals(name))
+ {
+
+ }
+ else if(DISTRIBUTION_MODE.equals(name))
+ {
+ return _subscription.acquires() ? "MOVE" : "COPY";
+ }
+ else if(SETTLEMENT_MODE.equals(name))
+ {
+
+ }
+ else if(EXCLUSIVE.equals(name))
+ {
+
+ }
+ else if(NO_LOCAL.equals(name))
+ {
+
+ }
+ else if(SELECTOR.equals(name))
+ {
+
+ }
+ return super.getAttribute(name); //TODO
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ private class ConsumerStatistics implements Statistics
+ {
+
+ public Collection<String> getStatisticNames()
+ {
+ return AVAILABLE_STATISTICS;
+ }
+
+ public Object getStatistic(String name)
+ {
+ if(name.equals(BYTES_OUT))
+ {
+ return _subscription.getBytesOut();
+ }
+ else if(name.equals(MESSAGES_OUT))
+ {
+ return _subscription.getMessagesOut();
+ }
+ else if(name.equals(STATE_CHANGED))
+ {
+
+ }
+ else if(name.equals(UNACKNOWLEDGED_BYTES))
+ {
+ return _subscription.getUnacknowledgedBytes();
+ }
+ else if(name.equals(UNACKNOWLEDGED_MESSAGES))
+ {
+ return _subscription.getUnacknowledgedMessages();
+ }
+ return null; // TODO - Implement
+ }
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java
new file mode 100644
index 0000000000..dd22804355
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java
@@ -0,0 +1,409 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQInternalException;
+import org.apache.qpid.AMQSecurityException;
+import org.apache.qpid.server.binding.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Exchange;
+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.model.UUIDGenerator;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apache.qpid.server.exchange.Exchange.BindingListener
+{
+
+ private final org.apache.qpid.server.exchange.Exchange _exchange;
+ private final Map<Binding, BindingAdapter> _bindingAdapters =
+ new HashMap<Binding, BindingAdapter>();
+ private VirtualHostAdapter _vhost;
+ private final ExchangeStatistics _statistics;
+
+
+ public ExchangeAdapter(final VirtualHostAdapter virtualHostAdapter,
+ final org.apache.qpid.server.exchange.Exchange exchange)
+ {
+ super(virtualHostAdapter.getName(), exchange.getName());
+ _statistics = new ExchangeStatistics();
+ _vhost = virtualHostAdapter;
+ _exchange = exchange;
+ addParent(org.apache.qpid.server.model.VirtualHost.class, virtualHostAdapter);
+
+ exchange.addBindingListener(this);
+ populateBindings();
+ }
+
+ private void populateBindings()
+ {
+ Collection<Binding> actualBindings = _exchange.getBindings();
+ synchronized (_bindingAdapters)
+ {
+ for(Binding binding : actualBindings)
+ {
+ if(!_bindingAdapters.containsKey(binding))
+ {
+ QueueAdapter queueAdapter = _vhost.getQueueAdapter(binding.getQueue());
+ BindingAdapter adapter = new BindingAdapter(binding, this, queueAdapter);
+ _bindingAdapters.put(binding, adapter);
+
+ queueAdapter.bindingRegistered(binding, adapter);
+ }
+ }
+ }
+
+ }
+
+ public String getExchangeType()
+ {
+ return _exchange.getType().getName().toString();
+ }
+
+ public Collection<org.apache.qpid.server.model.Binding> getBindings()
+ {
+ synchronized (_bindingAdapters)
+ {
+ return new ArrayList<org.apache.qpid.server.model.Binding>(_bindingAdapters.values());
+ }
+
+ }
+
+ public Collection<Publisher> getPublishers()
+ {
+ // TODO
+ return Collections.emptyList();
+ }
+
+
+ public org.apache.qpid.server.model.Binding createBinding(Queue queue,
+ Map<String, Object> attributes)
+ throws AccessControlException, IllegalStateException
+ {
+ attributes = new HashMap<String, Object>(attributes);
+ String bindingKey = getStringAttribute(org.apache.qpid.server.model.Binding.NAME, attributes, "");
+ Map<String, Object> bindingArgs = getMapAttribute(org.apache.qpid.server.model.Binding.ARGUMENTS, attributes, Collections.EMPTY_MAP);
+
+ attributes.remove(org.apache.qpid.server.model.Binding.NAME);
+ attributes.remove(org.apache.qpid.server.model.Binding.ARGUMENTS);
+
+ return createBinding(bindingKey, queue, bindingArgs, attributes);
+
+ }
+
+ public org.apache.qpid.server.model.Binding createBinding(String bindingKey, Queue queue,
+ Map<String, Object> bindingArguments,
+ Map<String, Object> attributes)
+ throws AccessControlException, IllegalStateException
+ {
+ VirtualHost virtualHost = _vhost.getVirtualHost();
+
+
+ AMQQueue amqQueue = ((QueueAdapter)queue).getAMQQueue();
+
+ try
+ {
+ if(!virtualHost.getBindingFactory().addBinding(bindingKey, amqQueue, _exchange, bindingArguments))
+ {
+ Binding oldBinding = virtualHost.getBindingFactory().getBinding(bindingKey, amqQueue, _exchange,
+ bindingArguments);
+
+ Map<String, Object> oldArgs = oldBinding.getArguments();
+ if((oldArgs == null && !bindingArguments.isEmpty()) || (oldArgs != null && !oldArgs.equals(bindingArguments)))
+ {
+ //TODO: generate deterministic UUID
+ virtualHost.getBindingFactory().replaceBinding(UUIDGenerator.generateUUID(), bindingKey, amqQueue, _exchange, bindingArguments);
+ }
+ }
+ Binding binding = virtualHost.getBindingFactory().getBinding(bindingKey, amqQueue, _exchange, bindingArguments);
+
+ synchronized (_bindingAdapters)
+ {
+ return binding == null ? null : _bindingAdapters.get(binding);
+ }
+ }
+ catch(AMQSecurityException e)
+ {
+ throw new AccessControlException(e.toString());
+ }
+ catch(AMQInternalException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void delete()
+ {
+ try
+ {
+ _vhost.getVirtualHost().getExchangeRegistry().unregisterExchange(getName(), false);
+ }
+ catch(AMQException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public String getName()
+ {
+ return _exchange.getName();
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+ public boolean isDurable()
+ {
+ return _exchange.isDurable();
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ //TODO
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return _exchange.isAutoDelete() ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT;
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public long getTimeToLive()
+ {
+ return 0; //TODO
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0; //TODO
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == org.apache.qpid.server.model.Binding.class)
+ {
+ return (Collection<C>) getBindings();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ if(childClass == org.apache.qpid.server.model.Binding.class)
+ {
+ if(otherParents != null && otherParents.length == 1 && otherParents[0] instanceof Queue)
+ {
+ Queue queue = (Queue) otherParents[0];
+ if(queue.getParent(org.apache.qpid.server.model.VirtualHost.class) == getParent(org.apache.qpid.server.model.VirtualHost.class))
+ {
+ return (C) createBinding(queue, attributes);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Queue and Exchange parents of a binding must be on same virtual host");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Other parent must be a queue");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public void bindingAdded(org.apache.qpid.server.exchange.Exchange exchange, Binding binding)
+ {
+ BindingAdapter adapter = null;
+ synchronized (_bindingAdapters)
+ {
+ if(!_bindingAdapters.containsKey(binding))
+ {
+ QueueAdapter queueAdapter = _vhost.getQueueAdapter(binding.getQueue());
+ adapter = new BindingAdapter(binding, this, queueAdapter);
+ _bindingAdapters.put(binding,adapter);
+ queueAdapter.bindingRegistered(binding,adapter);
+ }
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+ }
+
+ public void bindingRemoved(org.apache.qpid.server.exchange.Exchange exchange, Binding binding)
+ {
+ BindingAdapter adapter = null;
+ synchronized (_bindingAdapters)
+ {
+ adapter = _bindingAdapters.remove(binding);
+ }
+ if(adapter != null)
+ {
+ _vhost.getQueueAdapter(binding.getQueue()).bindingUnregistered(binding);
+ childRemoved(adapter);
+ }
+ }
+
+ org.apache.qpid.server.exchange.Exchange getExchange()
+ {
+ return _exchange;
+ }
+
+ @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 State.ACTIVE;
+ }
+ else if(DURABLE.equals(name))
+ {
+ return isDurable();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return _exchange.isAutoDelete() ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT;
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+
+ }
+ else if(CREATED.equals(name))
+ {
+
+ }
+ else if(UPDATED.equals(name))
+ {
+
+ }
+ else if(ALTERNATE_EXCHANGE.equals(name))
+ {
+ return _exchange.getAlternateExchange();
+ }
+ else if(TYPE.equals(name))
+ {
+ return _exchange.getType().getName().asString();
+ }
+ 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<String> getAttributeNames()
+ {
+ return AVAILABLE_ATTRIBUTES;
+ }
+
+ private class ExchangeStatistics implements Statistics
+ {
+
+ public Collection<String> getStatisticNames()
+ {
+ return AVAILABLE_STATISTICS;
+ }
+
+ public Object getStatistic(String name)
+ {
+ if(BINDING_COUNT.equals(name))
+ {
+ return _exchange.getBindingCount();
+ }
+ else if(BYTES_DROPPED.equals(name))
+ {
+ return _exchange.getByteDrops();
+ }
+ else if(BYTES_IN.equals(name))
+ {
+ return _exchange.getByteReceives();
+ }
+ else if(MESSAGES_DROPPED.equals(name))
+ {
+ return _exchange.getMsgDrops();
+ }
+ else if(MESSAGES_IN.equals(name))
+ {
+ return _exchange.getMsgReceives();
+ }
+ else if(PRODUCER_COUNT.equals(name))
+ {
+
+ }
+ else if(STATE_CHANGED.equals(name))
+ {
+
+ }
+ return null; // TODO - Implement
+ }
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java
new file mode 100644
index 0000000000..fdcc5e0184
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java
@@ -0,0 +1,262 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.VirtualHostAlias;
+
+public class HTTPPortAdapter extends AbstractAdapter implements Port
+{
+ private final BrokerAdapter _broker;
+ private int _port;
+ public HTTPPortAdapter(BrokerAdapter brokerAdapter, int port)
+ {
+ _broker = brokerAdapter;
+ _port = port;
+
+ }
+
+ @Override
+ public String getBindingAddress()
+ {
+ return "0.0.0.0";
+ }
+
+ @Override
+ public int getPort()
+ {
+ return _port;
+ }
+
+ @Override
+ public Collection<Transport> getTransports()
+ {
+ return Collections.singleton(Transport.TCP);
+ }
+
+ @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<Protocol> getProtocols()
+ {
+ return Collections.singleton(Protocol.HTTP);
+ }
+
+ @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<VirtualHostAlias> getVirtualHostBindings()
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Collection<Connection> 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 <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == Connection.class)
+ {
+ return (Collection<C>) getConnections();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> 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<String> 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/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.java
new file mode 100644
index 0000000000..b83887ffe5
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.java
@@ -0,0 +1,46 @@
+package org.apache.qpid.server.model.adapter;
+
+import org.apache.qpid.server.model.Statistics;
+
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class NoStatistics implements Statistics
+{
+ private static final NoStatistics INSTANCE = new NoStatistics();
+
+ private NoStatistics()
+ {
+ }
+
+ public Collection<String> getStatisticNames()
+ {
+ return Collections.emptyList();
+ }
+
+ public Object getStatistic(String name)
+ {
+ return null;
+ }
+
+ public static NoStatistics getInstance()
+ {
+ return INSTANCE;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
new file mode 100644
index 0000000000..0021431ee3
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
@@ -0,0 +1,318 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.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.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;
+
+public class PortAdapter extends AbstractAdapter implements Port
+{
+ private final BrokerAdapter _broker;
+ private final QpidAcceptor _acceptor;
+ private final InetSocketAddress _address;
+ private final Collection<Protocol> _protocols;
+
+ public PortAdapter(BrokerAdapter brokerAdapter, QpidAcceptor acceptor, InetSocketAddress address)
+ {
+ _broker = brokerAdapter;
+ _acceptor = acceptor;
+ _address = address;
+
+ List<Protocol> protocols = new ArrayList<Protocol>();
+
+ 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;
+ }
+ }
+
+ _protocols = Collections.unmodifiableCollection(protocols);
+
+ }
+
+ @Override
+ public String getBindingAddress()
+ {
+ return _address.getHostName();
+ }
+
+ @Override
+ public int getPort()
+ {
+ return _address.getPort();
+ }
+
+ @Override
+ public Collection<Transport> getTransports()
+ {
+ switch (_acceptor.getTransport())
+ {
+ case TCP:
+ return Collections.singleton(Transport.TCP);
+ case SSL:
+ return Collections.singleton(Transport.SSL);
+ }
+
+ return null; // TODO - Implement
+ }
+
+ @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<Protocol> getProtocols()
+ {
+ return _protocols;
+ }
+
+ @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<VirtualHostAlias> getVirtualHostBindings()
+ {
+ List<VirtualHostAlias> aliases = new ArrayList<VirtualHostAlias>();
+ for(VirtualHost vh : _broker.getVirtualHosts())
+ {
+ for(VirtualHostAlias alias : vh.getAliases())
+ {
+ if(alias.getPort().equals(this))
+ {
+ aliases.add(alias);
+ }
+ }
+ }
+ return Collections.unmodifiableCollection(aliases);
+ }
+
+ @Override
+ public Collection<Connection> getConnections()
+ {
+ return null; // 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 <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == Connection.class)
+ {
+ return (Collection<C>) getConnections();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> 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<String> 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/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java
new file mode 100644
index 0000000000..5c35fe5f7b
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java
@@ -0,0 +1,702 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.binding.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectFinder;
+import org.apache.qpid.server.model.Consumer;
+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.QueueNotificationListener;
+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;
+
+final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.SubscriptionRegistrationListener, AMQQueue.NotificationListener
+{
+
+ static final Map<String, String> ATTRIBUTE_MAPPINGS = new HashMap<String, String>();
+ 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-size");
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, "x-qpid-maximum-message-age");
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, "x-qpid-maximum-message-count");
+
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, "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.SORT_KEY, "qpid.sort_key");
+ QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.LVQ_KEY, "qpid.last_value_queue_key");
+
+ }
+
+ private final AMQQueue _queue;
+ private final Map<Binding, BindingAdapter> _bindingAdapters =
+ new HashMap<Binding, BindingAdapter>();
+ private Map<org.apache.qpid.server.subscription.Subscription, ConsumerAdapter> _consumerAdapters =
+ new HashMap<org.apache.qpid.server.subscription.Subscription, ConsumerAdapter>();
+
+
+ private final VirtualHostAdapter _vhost;
+ private QueueStatisticsAdapter _statistics;
+ private QueueNotificationListener _queueNotificationListener;
+
+ public QueueAdapter(final VirtualHostAdapter virtualHostAdapter, final AMQQueue queue)
+ {
+ super(virtualHostAdapter.getName(), queue.getName());
+ _vhost = virtualHostAdapter;
+ addParent(org.apache.qpid.server.model.VirtualHost.class, virtualHostAdapter);
+
+ _queue = queue;
+ _queue.addSubscriptionRegistrationListener(this);
+ populateConsumers();
+ _statistics = new QueueStatisticsAdapter(queue);
+ _queue.setNotificationListener(this);
+ }
+
+ private void populateConsumers()
+ {
+ Collection<org.apache.qpid.server.subscription.Subscription> actualSubscriptions = _queue.getConsumers();
+
+ synchronized (_consumerAdapters)
+ {
+ Iterator<org.apache.qpid.server.subscription.Subscription> iter = _consumerAdapters.keySet().iterator();
+ for(org.apache.qpid.server.subscription.Subscription subscription : actualSubscriptions)
+ {
+ if(!_consumerAdapters.containsKey(subscription))
+ {
+ _consumerAdapters.put(subscription, new ConsumerAdapter(this, subscription));
+ }
+ }
+ }
+ }
+
+ public Collection<org.apache.qpid.server.model.Binding> getBindings()
+ {
+ synchronized (_bindingAdapters)
+ {
+ return new ArrayList<org.apache.qpid.server.model.Binding>(_bindingAdapters.values());
+ }
+ }
+
+ public Collection<Consumer> getConsumers()
+ {
+ synchronized (_consumerAdapters)
+ {
+ return new ArrayList<Consumer>(_consumerAdapters.values());
+ }
+
+ }
+
+ public void visit(final QueueEntryVisitor visitor)
+ {
+ _queue.visit(visitor);
+ }
+
+ public void delete()
+ {
+ try
+ {
+ _queue.delete();
+ if (_queue.isDurable())
+ {
+
+ _queue.getVirtualHost().getMessageStore().removeQueue(_queue);
+ }
+ }
+ catch(AMQException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public String getName()
+ {
+ return _queue.getName();
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+ public boolean isDurable()
+ {
+ return _queue.isDurable();
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ //TODO
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return _queue.isAutoDelete() ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT;
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public long getTimeToLive()
+ {
+ return 0; //TODO
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0; //TODO
+ }
+
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return Queue.AVAILABLE_ATTRIBUTES;
+ }
+
+ @Override
+ public Object setAttribute(String name, Object expected, Object desired) throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ try
+ {
+ if(ALERT_REPEAT_GAP.equals(name))
+ {
+ _queue.setMinimumAlertRepeatGap((Long)desired);
+ return desired;
+ }
+ else if(ALERT_THRESHOLD_MESSAGE_AGE.equals(name))
+ {
+ _queue.setMaximumMessageAge((Long)desired);
+ return desired;
+ }
+ else if(ALERT_THRESHOLD_MESSAGE_SIZE.equals(name))
+ {
+ _queue.setMaximumMessageSize((Long)desired);
+ return desired;
+ }
+ else if(ALERT_THRESHOLD_QUEUE_DEPTH_BYTES.equals(name))
+ {
+ _queue.setMaximumQueueDepth((Long)desired);
+ return desired;
+ }
+ else if(ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES.equals(name))
+ {
+ _queue.setMaximumMessageCount((Long)desired);
+ return desired;
+ }
+ 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;
+ }
+ else if(EXCLUSIVE.equals(name))
+ {
+ Boolean exclusiveFlag = (Boolean) desired;
+ _queue.setExclusive(exclusiveFlag);
+ return desired;
+ }
+ else if(MESSAGE_GROUP_KEY.equals(name))
+ {
+ // TODO
+ }
+ else if(MESSAGE_GROUP_DEFAULT_GROUP.equals(name))
+ {
+ // TODO
+ }
+ else if(MESSAGE_GROUP_SHARED_GROUPS.equals(name))
+ {
+ // TODO
+ }
+ else if(LVQ_KEY.equals(name))
+ {
+ // TODO
+ }
+ else if(MAXIMUM_DELIVERY_ATTEMPTS.equals(name))
+ {
+ _queue.setMaximumDeliveryCount((Integer)desired);
+ return desired;
+ }
+ else if(NO_LOCAL.equals(name))
+ {
+ // TODO
+ }
+ else if(OWNER.equals(name))
+ {
+ // TODO
+ }
+ else if(QUEUE_FLOW_CONTROL_SIZE_BYTES.equals(name))
+ {
+ _queue.setCapacity((Long)desired);
+ return desired;
+ }
+ else if(QUEUE_FLOW_RESUME_SIZE_BYTES.equals(name))
+ {
+ _queue.setFlowResumeCapacity((Long)desired);
+ return desired;
+ }
+ else if(QUEUE_FLOW_STOPPED.equals(name))
+ {
+ // TODO
+ }
+ else if(SORT_KEY.equals(name))
+ {
+ // TODO
+ }
+ else if(TYPE.equals(name))
+ {
+ // TODO
+ }
+ else if (DESCRIPTION.equals(name))
+ {
+ _queue.setDescription((String) desired);
+ return desired;
+ }
+
+ return super.setAttribute(name, expected, desired);
+ }
+ finally
+ {
+ if (_queue.isDurable())
+ {
+ try
+ {
+ _queue.getVirtualHost().getMessageStore().updateQueue(_queue);
+ }
+ catch (AMQStoreException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+
+ if(ALERT_REPEAT_GAP.equals(name))
+ {
+ return _queue.getMinimumAlertRepeatGap();
+ }
+ else if(ALERT_THRESHOLD_MESSAGE_AGE.equals(name))
+ {
+ return _queue.getMaximumMessageAge();
+ }
+ else if(ALERT_THRESHOLD_MESSAGE_SIZE.equals(name))
+ {
+ return _queue.getMaximumMessageSize();
+ }
+ else if(ALERT_THRESHOLD_QUEUE_DEPTH_BYTES.equals(name))
+ {
+ return _queue.getMaximumQueueDepth();
+ }
+ else if(ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES.equals(name))
+ {
+ return _queue.getMaximumMessageCount();
+ }
+ else if(ALTERNATE_EXCHANGE.equals(name))
+ {
+ org.apache.qpid.server.exchange.Exchange alternateExchange = _queue.getAlternateExchange();
+ return alternateExchange == null ? null :
+ ConfiguredObjectFinder.findConfiguredObjectByName(_vhost.getExchanges(),
+ alternateExchange.getName());
+ }
+ else if(EXCLUSIVE.equals(name))
+ {
+ return _queue.isExclusive();
+ }
+ else if(MESSAGE_GROUP_KEY.equals(name))
+ {
+ // TODO
+ }
+ else if(MESSAGE_GROUP_DEFAULT_GROUP.equals(name))
+ {
+ // TODO
+ }
+ else if(MESSAGE_GROUP_SHARED_GROUPS.equals(name))
+ {
+ // TODO
+ }
+ else if(LVQ_KEY.equals(name))
+ {
+ if(_queue instanceof ConflationQueue)
+ {
+ return ((ConflationQueue)_queue).getConflationKey();
+ }
+ }
+ else if(MAXIMUM_DELIVERY_ATTEMPTS.equals(name))
+ {
+ return _queue.getMaximumDeliveryCount();
+ }
+ else if(NO_LOCAL.equals(name))
+ {
+ // TODO
+ }
+ else if(OWNER.equals(name))
+ {
+ return _queue.getOwner() == null ? null : _queue.getOwner().asString();
+ }
+ else if(QUEUE_FLOW_CONTROL_SIZE_BYTES.equals(name))
+ {
+ return _queue.getCapacity();
+ }
+ else if(QUEUE_FLOW_RESUME_SIZE_BYTES.equals(name))
+ {
+ return _queue.getFlowResumeCapacity();
+ }
+ else if(QUEUE_FLOW_STOPPED.equals(name))
+ {
+ return _queue.isOverfull();
+ }
+ else if(SORT_KEY.equals(name))
+ {
+ if(_queue instanceof SortedQueue)
+ {
+ return ((SortedQueue)_queue).getSortedPropertyName();
+ }
+ }
+ else if(TYPE.equals(name))
+ {
+ if(_queue instanceof SortedQueue)
+ {
+ return "sorted";
+ }
+ if(_queue instanceof ConflationQueue)
+ {
+ return "lvq";
+ }
+ if(_queue instanceof AMQPriorityQueue)
+ {
+ return "priority";
+ }
+ return "standard";
+ }
+ else if(CREATED.equals(name))
+ {
+ // TODO
+ }
+ else if(DURABLE.equals(name))
+ {
+ return _queue.isDurable();
+ }
+ else if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return _queue.isAutoDelete() ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT;
+ }
+ else if(NAME.equals(name))
+ {
+ return _queue.getName();
+ }
+ else if(STATE.equals(name))
+ {
+ return State.ACTIVE; // TODO
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+ // TODO
+ }
+ else if(UPDATED.equals(name))
+ {
+ // TODO
+ }
+ else if (DESCRIPTION.equals(name))
+ {
+ return _queue.getDescription();
+ }
+
+ return super.getAttribute(name);
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == Consumer.class)
+ {
+ return (Collection<C>) getConsumers();
+ }
+ else if(clazz == org.apache.qpid.server.model.Binding.class)
+ {
+ return (Collection<C>) getBindings();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ public org.apache.qpid.server.model.Binding createBinding(Exchange exchange, Map<String, Object> attributes)
+ throws AccessControlException, IllegalStateException
+ {
+ attributes = new HashMap<String, Object>(attributes);
+ String bindingKey = getStringAttribute(org.apache.qpid.server.model.Binding.NAME, attributes, "");
+ Map<String, Object> bindingArgs = getMapAttribute(org.apache.qpid.server.model.Binding.ARGUMENTS, attributes, Collections.EMPTY_MAP);
+
+ attributes.remove(org.apache.qpid.server.model.Binding.NAME);
+ attributes.remove(org.apache.qpid.server.model.Binding.ARGUMENTS);
+
+ return exchange.createBinding(bindingKey, this, bindingArgs, attributes);
+
+ }
+
+
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ if(childClass == org.apache.qpid.server.model.Binding.class)
+ {
+ if(otherParents != null && otherParents.length == 1 && otherParents[0] instanceof Exchange)
+ {
+ Exchange exchange = (Exchange) otherParents[0];
+ if(exchange.getParent(org.apache.qpid.server.model.VirtualHost.class) == getParent(org.apache.qpid.server.model.VirtualHost.class))
+ {
+ return (C) createBinding(exchange, attributes);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Queue and Exchange parents of a binding must be on same virtual host");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Other parent must be an exchange");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ void bindingRegistered(Binding binding, BindingAdapter adapter)
+ {
+ synchronized (_bindingAdapters)
+ {
+ _bindingAdapters.put(binding, adapter);
+ }
+ childAdded(adapter);
+ }
+
+ void bindingUnregistered(Binding binding)
+ {
+ BindingAdapter adapter = null;
+ synchronized (_bindingAdapters)
+ {
+ adapter = _bindingAdapters.remove(binding);
+ }
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ AMQQueue getAMQQueue()
+ {
+ return _queue;
+ }
+
+ public void subscriptionRegistered(final AMQQueue queue, final Subscription subscription)
+ {
+ ConsumerAdapter adapter = null;
+ synchronized (_consumerAdapters)
+ {
+ if(!_consumerAdapters.containsKey(subscription))
+ {
+ adapter = new ConsumerAdapter(this, subscription);
+ _consumerAdapters.put(subscription,adapter);
+ // TODO - register with session
+ }
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+ }
+
+ public void subscriptionUnregistered(final AMQQueue queue, final Subscription subscription)
+ {
+ ConsumerAdapter adapter = null;
+
+ synchronized (_consumerAdapters)
+ {
+ adapter = _consumerAdapters.remove(subscription);
+ // TODO - register with session
+ }
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ VirtualHostAdapter getVirtualHost()
+ {
+ return _vhost;
+ }
+
+
+ private static class QueueStatisticsAdapter implements Statistics
+ {
+
+ private final AMQQueue _queue;
+
+ public QueueStatisticsAdapter(AMQQueue queue)
+ {
+ _queue = queue;
+ }
+
+ public Collection<String> getStatisticNames()
+ {
+ return Queue.AVAILABLE_STATISTICS;
+ }
+
+ public Object getStatistic(String name)
+ {
+ if(BINDING_COUNT.equals(name))
+ {
+ return _queue.getBindingCount();
+ }
+ else if(CONSUMER_COUNT.equals(name))
+ {
+ return _queue.getConsumerCount();
+ }
+ else if(CONSUMER_COUNT_WITH_CREDIT.equals(name))
+ {
+ return _queue.getActiveConsumerCount();
+ }
+ else if(DISCARDS_TTL_BYTES.equals(name))
+ {
+ return null; // TODO
+ }
+ else if(DISCARDS_TTL_MESSAGES.equals(name))
+ {
+ return null; // TODO
+ }
+ else if(PERSISTENT_DEQUEUED_BYTES.equals(name))
+ {
+ return _queue.getPersistentByteDequeues();
+ }
+ else if(PERSISTENT_DEQUEUED_MESSAGES.equals(name))
+ {
+ return _queue.getPersistentMsgDequeues();
+ }
+ else if(PERSISTENT_ENQUEUED_BYTES.equals(name))
+ {
+ return _queue.getPersistentByteEnqueues();
+ }
+ else if(PERSISTENT_ENQUEUED_MESSAGES.equals(name))
+ {
+ return _queue.getPersistentMsgEnqueues();
+ }
+ else if(QUEUE_DEPTH_BYTES.equals(name))
+ {
+ return _queue.getQueueDepth();
+ }
+ else if(QUEUE_DEPTH_MESSAGES.equals(name))
+ {
+ return _queue.getMessageCount();
+ }
+ else if(STATE_CHANGED.equals(name))
+ {
+ return null; // TODO
+ }
+ else if(TOTAL_DEQUEUED_BYTES.equals(name))
+ {
+ return _queue.getTotalDequeueSize();
+ }
+ else if(TOTAL_DEQUEUED_MESSAGES.equals(name))
+ {
+ return _queue.getTotalDequeueCount();
+ }
+ else if(TOTAL_ENQUEUED_BYTES.equals(name))
+ {
+ return _queue.getTotalEnqueueSize();
+ }
+ else if(TOTAL_ENQUEUED_MESSAGES.equals(name))
+ {
+ return _queue.getTotalEnqueueCount();
+ }
+ else if(UNACKNOWLEDGED_BYTES.equals(name))
+ {
+ return _queue.getUnackedMessageBytes();
+ }
+ else if(UNACKNOWLEDGED_MESSAGES.equals(name))
+ {
+ return _queue.getUnackedMessageCount();
+ }
+
+ return null;
+ }
+ }
+
+ @Override
+ public void setNotificationListener(QueueNotificationListener listener)
+ {
+ _queueNotificationListener = listener;
+ }
+
+ @Override
+ public void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg)
+ {
+ QueueNotificationListener listener = _queueNotificationListener;
+ if(listener != null)
+ {
+ listener.notifyClients(notification, this, notificationMsg);
+ }
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java
new file mode 100644
index 0000000000..25d9c6feb1
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java
@@ -0,0 +1,239 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model.adapter;
+
+import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+
+import java.util.Map;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Publisher;
+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.Consumer;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+
+final class SessionAdapter extends AbstractAdapter implements Session
+{
+ // Attributes
+
+
+ private AMQSessionModel _session;
+ private SessionStatistics _statistics;
+
+ public SessionAdapter(final AMQSessionModel session)
+ {
+ _session = session;
+ _statistics = new SessionStatistics();
+ }
+
+ public Collection<Consumer> getSubscriptions()
+ {
+ return null; //TODO
+ }
+
+ public Collection<Publisher> getPublishers()
+ {
+ return null; //TODO
+ }
+
+ public String getName()
+ {
+ return String.valueOf(_session.getChannelId());
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ return null; //TODO
+ }
+
+ public State getActualState()
+ {
+ return null; //TODO
+ }
+
+ public boolean isDurable()
+ {
+ return false; //TODO
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ //TODO
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return null; //TODO
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null; //TODO
+ }
+
+ public long getTimeToLive()
+ {
+ return 0; //TODO
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0; //TODO
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ Collection<String> names = new HashSet<String>(super.getAttributeNames());
+ names.addAll(AVAILABLE_ATTRIBUTES);
+
+ return Collections.unmodifiableCollection(names);
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+ if(name.equals(ID))
+ {
+ return getId();
+ }
+ else if (name.equals(NAME))
+ {
+ return getName();
+ }
+ else if(name.equals(CHANNEL_ID))
+ {
+ return _session.getChannelId();
+ }
+ else if(name.equals(PRODUCER_FLOW_BLOCKED))
+ {
+ return _session.getBlocking();
+ }
+ 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;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == Consumer.class)
+ {
+ return (Collection<C>) getSubscriptions();
+ }
+ else if(clazz == Publisher.class)
+ {
+ return (Collection<C>) getPublishers();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ private class SessionStatistics implements Statistics
+ {
+
+ public SessionStatistics()
+ {
+ }
+
+ public Collection<String> getStatisticNames()
+ {
+ return AVAILABLE_STATISTICS;
+ }
+
+ public Object getStatistic(String name)
+ {
+ if(name.equals(BYTES_IN))
+ {
+ }
+ else if(name.equals(BYTES_OUT))
+ {
+ }
+ else if(name.equals(CONSUMER_COUNT))
+ {
+ final Collection<Consumer> subscriptions = getSubscriptions();
+ return subscriptions == null ? 0 : subscriptions.size();
+ }
+ else if(name.equals(LOCAL_TRANSACTION_BEGINS))
+ {
+ return _session.getTxnStart();
+ }
+ else if(name.equals(LOCAL_TRANSACTION_OPEN))
+ {
+ long open = _session.getTxnCount() - (_session.getTxnCommits() + _session.getTxnRejects());
+ return (Boolean) (open > 0l);
+ }
+ else if(name.equals(LOCAL_TRANSACTION_ROLLBACKS))
+ {
+ return _session.getTxnCommits();
+ }
+ else if(name.equals(STATE_CHANGED))
+ {
+ }
+ else if(name.equals(UNACKNOWLEDGED_BYTES))
+ {
+ }
+ else if(name.equals(UNACKNOWLEDGED_MESSAGES))
+ {
+ return _session.getUnacknowledgedMessageCount();
+ }
+ else if(name.equals(XA_TRANSACTION_BRANCH_ENDS))
+ {
+ }
+ else if(name.equals(XA_TRANSACTION_BRANCH_STARTS))
+ {
+ }
+ else if(name.equals(XA_TRANSACTION_BRANCH_SUSPENDS))
+ {
+
+ }
+
+ return null; // TODO - Implement
+ }
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.java
new file mode 100644
index 0000000000..f98e46c911
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.java
@@ -0,0 +1,67 @@
+package org.apache.qpid.server.model.adapter;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.stats.StatisticsCounter;
+import org.apache.qpid.server.stats.StatisticsGatherer;
+
+/**
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+* <p/>
+* http://www.apache.org/licenses/LICENSE-2.0
+* <p/>
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+class StatisticsAdapter implements Statistics
+{
+
+ private final Map<String, StatisticsCounter> _statistics =
+ new HashMap<String, StatisticsCounter>();
+
+
+ private static final String BYTES_IN = "bytesIn";
+ private static final String BYTES_OUT = "bytesOut";
+ private static final String MESSAGES_IN = "messagesIn";
+ private static final String MESSAGES_OUT = "messagesOut";
+
+ private static final Collection<String> STATISTIC_NAMES =
+ Collections.unmodifiableCollection(Arrays.asList(BYTES_IN, BYTES_OUT, MESSAGES_IN, MESSAGES_OUT));
+
+
+
+ public StatisticsAdapter(StatisticsGatherer statGatherer)
+ {
+ _statistics.put(BYTES_OUT, statGatherer.getDataDeliveryStatistics());
+ _statistics.put(BYTES_IN, statGatherer.getDataReceiptStatistics());
+ _statistics.put(MESSAGES_OUT, statGatherer.getMessageDeliveryStatistics());
+ _statistics.put(MESSAGES_IN, statGatherer.getMessageReceiptStatistics());
+ }
+
+
+ public Collection<String> getStatisticNames()
+ {
+ return STATISTIC_NAMES;
+ }
+
+ public Object getStatistic(String name)
+ {
+ StatisticsCounter counter = _statistics.get(name);
+ return counter == null ? null : counter.getTotal();
+
+ }
+
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
new file mode 100644
index 0000000000..204054c8cb
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
@@ -0,0 +1,844 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.FieldTable;
+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.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.Queue;
+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.VirtualHost;
+import org.apache.qpid.server.model.VirtualHostAlias;
+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.store.MessageStore;
+import org.apache.qpid.server.txn.LocalTransaction;
+import org.apache.qpid.server.txn.ServerTransaction;
+
+final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, ExchangeRegistry.RegistryChangeListener,
+ QueueRegistry.RegistryChangeListener,
+ IConnectionRegistry.RegistryChangeListener
+{
+
+ private final org.apache.qpid.server.virtualhost.VirtualHost _virtualHost;
+
+ private final Map<AMQConnectionModel, ConnectionAdapter> _connectionAdapters =
+ new HashMap<AMQConnectionModel, ConnectionAdapter>();
+
+ private final Map<AMQQueue, QueueAdapter> _queueAdapters =
+ new HashMap<AMQQueue, QueueAdapter>();
+
+ private final Map<org.apache.qpid.server.exchange.Exchange, ExchangeAdapter> _exchangeAdapters =
+ new HashMap<org.apache.qpid.server.exchange.Exchange, ExchangeAdapter>();
+
+ private final StatisticsAdapter _statistics;
+
+ private final BrokerAdapter _broker;
+
+ private final List<VirtualHostAlias> _aliases = new ArrayList<VirtualHostAlias>();
+
+
+ VirtualHostAdapter(BrokerAdapter brokerAdapter,
+ final org.apache.qpid.server.virtualhost.VirtualHost virtualHost)
+ {
+ super(virtualHost.getName());
+ _broker = brokerAdapter;
+ _virtualHost = virtualHost;
+ _statistics = new VirtualHostStatisticsAdapter(virtualHost);
+ virtualHost.getQueueRegistry().addRegistryChangeListener(this);
+ populateQueues();
+ virtualHost.getExchangeRegistry().addRegistryChangeListener(this);
+ populateExchanges();
+ virtualHost.getConnectionRegistry().addRegistryChangeListener(this);
+ populateConnections();
+
+
+
+ for(Port port :_broker.getPorts())
+ {
+ _aliases.add(new VirtualHostAliasAdapter(this, port));
+ }
+ }
+
+
+ private void populateExchanges()
+ {
+ Collection<org.apache.qpid.server.exchange.Exchange> actualExchanges =
+ _virtualHost.getExchangeRegistry().getExchanges();
+
+ synchronized (_exchangeAdapters)
+ {
+ for(org.apache.qpid.server.exchange.Exchange exchange : actualExchanges)
+ {
+ if(!_exchangeAdapters.containsKey(exchange))
+ {
+ _exchangeAdapters.put(exchange, new ExchangeAdapter(this,exchange));
+ }
+ }
+ }
+ }
+
+
+ private void populateQueues()
+ {
+ Collection<AMQQueue> 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<AMQConnectionModel> actualConnections = _virtualHost.getConnectionRegistry().getConnections();
+
+ synchronized(_connectionAdapters)
+ {
+ for(AMQConnectionModel conn : actualConnections)
+ {
+ if(!_connectionAdapters.containsKey(conn))
+ {
+ _connectionAdapters.put(conn, new ConnectionAdapter(conn));
+ }
+ }
+ }
+
+ }
+
+ public String getReplicationGroupName()
+ {
+ return null; //TODO
+ }
+
+ public Collection<VirtualHostAlias> getAliases()
+ {
+ return Collections.unmodifiableCollection(_aliases);
+ }
+
+ public Collection<Connection> getConnections()
+ {
+ synchronized(_connectionAdapters)
+ {
+ return new ArrayList<Connection>(_connectionAdapters.values());
+ }
+
+ }
+
+ public Collection<Queue> getQueues()
+ {
+ synchronized(_queueAdapters)
+ {
+ return new ArrayList<Queue>(_queueAdapters.values());
+ }
+ }
+
+ public Collection<Exchange> getExchanges()
+ {
+ synchronized (_exchangeAdapters)
+ {
+ return new ArrayList<Exchange>(_exchangeAdapters.values());
+ }
+ }
+
+
+ public Exchange createExchange(Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ attributes = new HashMap<String, Object>(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);
+
+ attributes.remove(Exchange.NAME);
+ attributes.remove(Exchange.STATE);
+ attributes.remove(Exchange.DURABLE);
+ attributes.remove(Exchange.LIFETIME_POLICY);
+ attributes.remove(Exchange.TYPE);
+ attributes.remove(Exchange.TIME_TO_LIVE);
+
+ return createExchange(name, state, durable, lifetime, ttl, type, attributes);
+ }
+
+
+ public Exchange createExchange(final String name,
+ final State initialState,
+ final boolean durable,
+ final LifetimePolicy lifetime,
+ final long ttl,
+ final String type,
+ final Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ try
+ {
+ org.apache.qpid.server.exchange.Exchange exchange =
+ _virtualHost.getExchangeFactory().createExchange(name, type, durable,
+ lifetime == LifetimePolicy.AUTO_DELETE);
+ _virtualHost.getExchangeRegistry().registerExchange(exchange);
+ if(durable)
+ {
+ _virtualHost.getMessageStore().createExchange(exchange);
+ }
+
+ synchronized (_exchangeAdapters)
+ {
+ return _exchangeAdapters.get(exchange);
+ }
+ }
+ catch(AMQException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public Queue createQueue(Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ attributes = new HashMap<String, Object>(attributes);
+
+ 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);
+
+ attributes.remove(Queue.NAME);
+ attributes.remove(Queue.STATE);
+ attributes.remove(Queue.DURABLE);
+ attributes.remove(Queue.LIFETIME_POLICY);
+ attributes.remove(Queue.TIME_TO_LIVE);
+
+ List<String> attrNames = new ArrayList<String>(attributes.keySet());
+ for(String attr : attrNames)
+ {
+ if(QueueAdapter.ATTRIBUTE_MAPPINGS.containsKey(attr))
+ {
+ attributes.put(QueueAdapter.ATTRIBUTE_MAPPINGS.get(attr),attributes.remove(attr));
+ }
+ }
+
+ return createQueue(name, state, durable, exclusive, lifetime, ttl, attributes);
+ }
+
+ public Queue createQueue(final String name,
+ final State initialState,
+ final boolean durable,
+ boolean exclusive,
+ final LifetimePolicy lifetime,
+ final long ttl,
+ final Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ String owner = null;
+ if(exclusive)
+ {
+ Set<Principal> principals =
+ SecurityManager.getThreadSubject().getPrincipals();
+ if(principals != null && !principals.isEmpty())
+ {
+ owner = principals.iterator().next().getName();
+ }
+ }
+ try
+ {
+ if(_virtualHost.getQueueRegistry().getQueue(name)!=null)
+ {
+ throw new IllegalArgumentException("Queue with name "+name+" already exists");
+ }
+ AMQQueue queue =
+ AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateUUID(name, _virtualHost.getName()), name,
+ durable, owner, lifetime == LifetimePolicy.AUTO_DELETE,
+ exclusive, _virtualHost, attributes);
+ _virtualHost.getBindingFactory().addBinding(name, queue, _virtualHost.getExchangeRegistry().getDefaultExchange(), null);
+
+ if(durable)
+ {
+ _virtualHost.getMessageStore().createQueue(queue, FieldTable.convertToFieldTable(attributes));
+ }
+ synchronized (_queueAdapters)
+ {
+ return _queueAdapters.get(queue);
+ }
+
+ }
+ catch(AMQException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+
+ }
+
+ public String getName()
+ {
+ return _virtualHost.getName();
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ throw new IllegalStateException();
+ }
+
+ public State getActualState()
+ {
+ return getDesiredState();
+ }
+
+ public boolean isDurable()
+ {
+ return true;
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ public long getTimeToLive()
+ {
+ return 0;
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ public Statistics getStatistics()
+ {
+ return _statistics;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == Exchange.class)
+ {
+ return (Collection<C>) getExchanges();
+ }
+ else if(clazz == Queue.class)
+ {
+ return (Collection<C>) getQueues();
+ }
+ else if(clazz == Connection.class)
+ {
+ return (Collection<C>) getConnections();
+ }
+ else if(clazz == VirtualHostAlias.class)
+ {
+ return (Collection<C>) getAliases();
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ if(childClass == Exchange.class)
+ {
+ return (C) createExchange(attributes);
+ }
+ else if(childClass == Queue.class)
+ {
+ return (C) createQueue(attributes);
+ }
+ else if(childClass == VirtualHostAlias.class)
+ {
+ throw new UnsupportedOperationException();
+ }
+ else if(childClass == Connection.class)
+ {
+ throw new UnsupportedOperationException();
+ }
+ throw new IllegalArgumentException("Cannot create a child of class " + childClass.getSimpleName());
+ }
+
+ public void exchangeRegistered(org.apache.qpid.server.exchange.Exchange exchange)
+ {
+ ExchangeAdapter adapter = null;
+ synchronized (_exchangeAdapters)
+ {
+ if(!_exchangeAdapters.containsKey(exchange))
+ {
+ adapter = new ExchangeAdapter(this, exchange);
+ _exchangeAdapters.put(exchange, adapter);
+
+ }
+
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+
+ }
+
+
+ public void exchangeUnregistered(org.apache.qpid.server.exchange.Exchange exchange)
+ {
+ ExchangeAdapter adapter;
+ synchronized (_exchangeAdapters)
+ {
+ adapter = _exchangeAdapters.remove(exchange);
+
+ }
+
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ public void queueRegistered(AMQQueue queue)
+ {
+ QueueAdapter adapter = null;
+ synchronized (_queueAdapters)
+ {
+ if(!_queueAdapters.containsKey(queue))
+ {
+ adapter = new QueueAdapter(this, queue);
+ _queueAdapters.put(queue, adapter);
+
+ }
+
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+
+ }
+
+ public void queueUnregistered(AMQQueue queue)
+ {
+
+ QueueAdapter adapter;
+ synchronized (_queueAdapters)
+ {
+ adapter = _queueAdapters.remove(queue);
+
+ }
+
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ public void connectionRegistered(AMQConnectionModel connection)
+ {
+ ConnectionAdapter adapter = null;
+ synchronized (_connectionAdapters)
+ {
+ if(!_connectionAdapters.containsKey(connection))
+ {
+ adapter = new ConnectionAdapter(connection);
+ _connectionAdapters.put(connection, adapter);
+
+ }
+
+ }
+ if(adapter != null)
+ {
+ childAdded(adapter);
+ }
+ }
+
+ public void connectionUnregistered(AMQConnectionModel connection)
+ {
+
+ ConnectionAdapter adapter;
+ synchronized (_connectionAdapters)
+ {
+ adapter = _connectionAdapters.remove(connection);
+
+ }
+
+ if(adapter != null)
+ {
+ childRemoved(adapter);
+ }
+ }
+
+ QueueAdapter getQueueAdapter(AMQQueue queue)
+ {
+ synchronized (_queueAdapters)
+ {
+ return _queueAdapters.get(queue);
+ }
+ }
+
+ public void deleteQueue(Queue queue)
+ throws AccessControlException, IllegalStateException
+ {
+ // TODO
+ throw new UnsupportedOperationException("Not Yet Implemented");
+ }
+
+ public Collection<String> getExchangeTypes()
+ {
+ Collection<ExchangeType<? extends org.apache.qpid.server.exchange.Exchange>> types =
+ _virtualHost.getExchangeFactory().getRegisteredTypes();
+
+ Collection<String> exchangeTypes = new ArrayList<String>();
+
+ for(ExchangeType<? extends org.apache.qpid.server.exchange.Exchange> type : types)
+ {
+ exchangeTypes.add(type.getName().asString());
+ }
+ return Collections.unmodifiableCollection(exchangeTypes);
+ }
+
+ public void executeTransaction(TransactionalOperation op)
+ {
+ MessageStore store = _virtualHost.getMessageStore();
+ final LocalTransaction txn = new LocalTransaction(store);
+
+ op.withinTransaction(new Transaction()
+ {
+ public void dequeue(final QueueEntry entry)
+ {
+ if(entry.acquire())
+ {
+ txn.dequeue(entry.getQueue(), entry.getMessage(), new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ entry.discard();
+ }
+
+ public void onRollback()
+ {
+ }
+ });
+ }
+ }
+
+ public void copy(QueueEntry entry, Queue queue)
+ {
+ final ServerMessage message = entry.getMessage();
+ final AMQQueue toQueue = ((QueueAdapter)queue).getAMQQueue();
+
+ txn.enqueue(toQueue, message, new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ try
+ {
+ toQueue.enqueue(message);
+ }
+ catch(AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void onRollback()
+ {
+ }
+ });
+
+ }
+
+ public void move(final QueueEntry entry, Queue queue)
+ {
+ final ServerMessage message = entry.getMessage();
+ final AMQQueue toQueue = ((QueueAdapter)queue).getAMQQueue();
+ if(entry.acquire())
+ {
+ txn.enqueue(toQueue, message,
+ new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ try
+ {
+ toQueue.enqueue(message);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void onRollback()
+ {
+ entry.release();
+ }
+ });
+ txn.dequeue(entry.getQueue(), message,
+ new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ entry.discard();
+ }
+
+ public void onRollback()
+ {
+
+ }
+ });
+ }
+ }
+
+ });
+ txn.commit();
+ }
+
+ org.apache.qpid.server.virtualhost.VirtualHost getVirtualHost()
+ {
+ return _virtualHost;
+ }
+
+ @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 State.ACTIVE;
+ }
+ else if(DURABLE.equals(name))
+ {
+ return isDurable();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+ // TODO
+ }
+ else if(CREATED.equals(name))
+ {
+ // TODO
+ }
+ else if(UPDATED.equals(name))
+ {
+ // TODO
+ }
+ else if(SUPPORTED_EXCHANGE_TYPES.equals(name))
+ {
+ List<String> types = new ArrayList<String>();
+ for(ExchangeType type : _virtualHost.getExchangeFactory().getRegisteredTypes())
+ {
+ types.add(type.getName().asString());
+ }
+ return Collections.unmodifiableCollection(types);
+ }
+ else if(SUPPORTED_QUEUE_TYPES.equals(name))
+ {
+ // TODO
+ }
+ else if(DEAD_LETTER_QUEUE_ENABLED.equals(name))
+ {
+ return _virtualHost.getConfiguration().isDeadLetterQueueEnabled();
+ }
+ else if(FEDERATION_TAG.equals(name))
+ {
+ return _virtualHost.getFederationTag();
+ }
+ else if(HOUSEKEEPING_CHECK_PERIOD.equals(name))
+ {
+ return _virtualHost.getConfiguration().getHousekeepingCheckPeriod();
+ }
+ else if(MAXIMUM_DELIVERY_ATTEMPTS.equals(name))
+ {
+ return _virtualHost.getConfiguration().getMaxDeliveryCount();
+ }
+ else if(QUEUE_FLOW_CONTROL_SIZE_BYTES.equals(name))
+ {
+ return _virtualHost.getConfiguration().getCapacity();
+ }
+ else if(QUEUE_FLOW_RESUME_SIZE_BYTES.equals(name))
+ {
+ return _virtualHost.getConfiguration().getFlowResumeCapacity();
+ }
+ else if(STORE_TYPE.equals(name))
+ {
+ return _virtualHost.getMessageStore().getStoreType();
+ }
+ else if(STORE_CONFIGURATION.equals(name))
+ {
+ // TODO
+ }
+ else if(STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE.equals(name))
+ {
+ return _virtualHost.getConfiguration().getTransactionTimeoutIdleClose();
+ }
+ else if(STORE_TRANSACTION_IDLE_TIMEOUT_WARN.equals(name))
+ {
+ return _virtualHost.getConfiguration().getTransactionTimeoutIdleWarn();
+ }
+ else if(STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE.equals(name))
+ {
+ return _virtualHost.getConfiguration().getTransactionTimeoutOpenClose();
+ }
+ else if(STORE_TRANSACTION_OPEN_TIMEOUT_WARN.equals(name))
+ {
+ return _virtualHost.getConfiguration().getTransactionTimeoutOpenWarn();
+ }
+ else if(ALERT_REPEAT_GAP.equals(name))
+ {
+ return _virtualHost.getConfiguration().getMinimumAlertRepeatGap();
+ }
+ else if(ALERT_THRESHOLD_MESSAGE_AGE.equals(name))
+ {
+ return _virtualHost.getConfiguration().getMaximumMessageAge();
+ }
+ else if(ALERT_THRESHOLD_MESSAGE_SIZE.equals(name))
+ {
+ return _virtualHost.getConfiguration().getMaximumMessageSize();
+ }
+ else if(ALERT_THRESHOLD_QUEUE_DEPTH_BYTES.equals(name))
+ {
+ return _virtualHost.getConfiguration().getMaximumQueueDepth();
+ }
+ else if(ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES.equals(name))
+ {
+ return _virtualHost.getConfiguration().getMaximumMessageCount();
+ }
+ 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<String> getAttributeNames()
+ {
+ return AVAILABLE_ATTRIBUTES;
+ }
+
+ private static class VirtualHostStatisticsAdapter extends StatisticsAdapter
+ {
+ private final org.apache.qpid.server.virtualhost.VirtualHost _vhost;
+
+ private static final Collection<String> VHOST_STATS = Arrays.asList(
+ VirtualHost.QUEUE_COUNT,
+ VirtualHost.EXCHANGE_COUNT,
+ VirtualHost.CONNECTION_COUNT);
+
+ public VirtualHostStatisticsAdapter(org.apache.qpid.server.virtualhost.VirtualHost virtualHost)
+ {
+ super(virtualHost);
+ _vhost = virtualHost;
+ }
+
+ @Override
+ public Collection<String> getStatisticNames()
+ {
+ Set<String> stats = new HashSet<String>(super.getStatisticNames());
+ stats.addAll(VHOST_STATS);
+ return stats;
+ }
+
+ @Override
+ public Object getStatistic(String name)
+ {
+ if(VirtualHost.QUEUE_COUNT.equals(name))
+ {
+ return _vhost.getQueueRegistry().getQueues().size();
+ }
+ else if(VirtualHost.EXCHANGE_COUNT.equals(name))
+ {
+ return _vhost.getExchangeRegistry().getExchanges().size();
+ }
+ else if(VirtualHost.CONNECTION_COUNT.equals(name))
+ {
+ return _vhost.getConnectionRegistry().getConnections().size();
+ }
+ else
+ {
+ return super.getStatistic(name);
+ }
+ }
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java
new file mode 100644
index 0000000000..22ea2e612b
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java
@@ -0,0 +1,142 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.model.adapter;
+
+import java.util.Map;
+import org.apache.qpid.server.model.AuthenticationMethod;
+import org.apache.qpid.server.model.ConfiguredObject;
+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.Statistics;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.VirtualHostAlias;
+
+import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.Collections;
+
+public class VirtualHostAliasAdapter extends AbstractAdapter implements VirtualHostAlias
+{
+ private VirtualHostAdapter _vhost;
+ private Port _port;
+
+ public VirtualHostAliasAdapter(VirtualHostAdapter virtualHostAdapter, Port port)
+ {
+ super(virtualHostAdapter.getName(), port.getName());
+ _vhost = virtualHostAdapter;
+ _port = port;
+ }
+
+ @Override
+ public Port getPort()
+ {
+ return _port;
+ }
+
+ @Override
+ public VirtualHost getVirtualHost()
+ {
+ return _vhost;
+ }
+
+ @Override
+ public Collection<AuthenticationMethod> getAuthenticationMethods()
+ {
+ return Collections.emptySet(); // TODO - Implement
+ }
+
+ @Override
+ public String getName()
+ {
+ return _vhost.getName();
+ }
+
+ @Override
+ public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException
+ {
+ throw new IllegalStateException(); // TODO - Implement
+ }
+
+ @Override
+ public State getActualState()
+ {
+ return State.ACTIVE; // TODO - Implement
+ }
+
+ @Override
+ public boolean isDurable()
+ {
+ return true; // TODO - Implement
+ }
+
+ @Override
+ public void setDurable(boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT; // TODO - Implement
+ }
+
+ @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 <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/AbstractConfiguredObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/AbstractConfiguredObject.java
new file mode 100644
index 0000000000..091887bb3d
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/AbstractConfiguredObject.java
@@ -0,0 +1,335 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.impl;
+
+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.LifetimePolicy;
+import org.apache.qpid.server.model.State;
+
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+abstract class AbstractConfiguredObject implements ConfiguredObject
+{
+ public static final Map<String, Object> EMPTY_ATTRIBUTE_MAP =
+ Collections.<String, Object>emptyMap();
+ public static final Map<Class<? extends ConfiguredObject>, ConfiguredObject> EMPTY_PARENT_MAP =
+ Collections.<Class<? extends ConfiguredObject>, ConfiguredObject>emptyMap();
+
+ private UUID _id;
+ private String _name;
+ private State _state;
+ private boolean _isDurable;
+ private LifetimePolicy _lifetimePolicy;
+ private long _timeToLive;
+
+
+ private final Map<String,Object> _attributes = new HashMap<String, Object>();
+ private final Map<Class<? extends ConfiguredObject>, ConfiguredObject> _parents =
+ new HashMap<Class<? extends ConfiguredObject>, ConfiguredObject>();
+ private final Map<Class<? extends ConfiguredObject>, Collection<ConfiguredObject>> _children =
+ new HashMap<Class<? extends ConfiguredObject>, Collection<ConfiguredObject>>();
+
+
+ private final Collection<ConfigurationChangeListener> _changeListeners =
+ new ArrayList<ConfigurationChangeListener>();
+
+ protected AbstractConfiguredObject(final UUID id,
+ final String name,
+ final State state,
+ final boolean durable,
+ final LifetimePolicy lifetimePolicy,
+ final long timeToLive,
+ final Map<String, Object> attributes,
+ final Map<Class<? extends ConfiguredObject>, ConfiguredObject> parents)
+ {
+ _id = id;
+ _name = name;
+ _state = state;
+ _isDurable = durable;
+ _lifetimePolicy = lifetimePolicy;
+ _timeToLive = timeToLive;
+ _attributes.putAll(attributes);
+ _parents.putAll(parents);
+ }
+
+ public UUID getId()
+ {
+ return _id;
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ if(desiredName == null)
+ {
+ throw new NullPointerException("The name may not be null");
+ }
+
+ synchronized (getLock())
+ {
+ if(_name.equals(currentName))
+ {
+ _name = desiredName;
+ }
+ return _name;
+ }
+ }
+
+ public State getDesiredState()
+ {
+ return _state;
+ }
+
+ public State setDesiredState(final State currentState, final State desiredState)
+ throws IllegalStateTransitionException, AccessControlException
+ {
+ synchronized (getLock())
+ {
+ if(_state == currentState && currentState != desiredState)
+ {
+ _state = desiredState;
+ for(ConfigurationChangeListener listener : _changeListeners)
+ {
+ listener.stateChanged(this, currentState, desiredState);
+ }
+ }
+ return _state;
+ }
+ }
+
+ public void addChangeListener(final ConfigurationChangeListener listener)
+ {
+ if(listener == null)
+ {
+ throw new NullPointerException("Cannot add a null listener");
+ }
+ synchronized (getLock())
+ {
+ if(!_changeListeners.contains(listener))
+ {
+ _changeListeners.add(listener);
+ }
+ }
+ }
+
+ public boolean removeChangeListener(final ConfigurationChangeListener listener)
+ {
+ if(listener == null)
+ {
+ throw new NullPointerException("Cannot remove a null listener");
+ }
+ synchronized (getLock())
+ {
+ return _changeListeners.remove(listener);
+ }
+ }
+
+ public boolean isDurable()
+ {
+ return _isDurable;
+ }
+
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ synchronized (getLock())
+ {
+ _isDurable = durable;
+ }
+ }
+
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return _lifetimePolicy;
+ }
+
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ synchronized(getLock())
+ {
+ if((_lifetimePolicy == null && expected == null)
+ || (_lifetimePolicy != null && _lifetimePolicy.equals(expected)))
+ {
+ _lifetimePolicy = desired;
+ }
+
+ return _lifetimePolicy;
+
+ }
+ }
+
+ public long getTimeToLive()
+ {
+ return _timeToLive;
+ }
+
+ public long setTimeToLive(final long expected, final long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ synchronized(getLock())
+ {
+ if(_timeToLive == expected)
+ {
+ _timeToLive = desired;
+ }
+ return _timeToLive;
+ }
+ }
+
+ public Collection<String> getAttributeNames()
+ {
+ synchronized(_attributes)
+ {
+ return new ArrayList<String>(_attributes.keySet());
+ }
+ }
+
+ public Object getAttribute(final String name)
+ {
+ synchronized (getLock())
+ {
+ return _attributes.get(name);
+ }
+ }
+
+ public Object setAttribute(final String name, final Object expected, final Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ synchronized (getLock())
+ {
+ Object currentValue = _attributes.get(name);
+ if ((currentValue == null && expected == null && desired != null)
+ || (currentValue != null && currentValue.equals(expected) && !currentValue.equals(desired)))
+ {
+ _attributes.put(name, desired);
+ return desired;
+ }
+ else
+ {
+ return currentValue;
+ }
+ }
+ }
+
+
+ public <T extends ConfiguredObject> T getParent(final Class<T> clazz)
+ {
+ synchronized (getLock())
+ {
+ return (T) _parents.get(clazz);
+ }
+ }
+
+ protected <T extends ConfiguredObject> void addParent(Class<T> clazz, T parent)
+ {
+ synchronized (getLock())
+ {
+ _parents.put(clazz, parent);
+ }
+ }
+
+ protected <T extends ConfiguredObject> void removeParent(Class<T> clazz)
+ {
+ synchronized (getLock())
+ {
+ _parents.remove(clazz);
+ }
+ }
+
+ protected <T extends ConfiguredObject> void childAdded(Class<T> clazz, T child)
+ {
+ synchronized (getLock())
+ {
+ Collection<ConfiguredObject> children = _children.get(clazz);
+ if(children == null)
+ {
+ children = new ArrayList<ConfiguredObject>();
+ _children.put(clazz, children);
+ }
+ children.add(child);
+ }
+ notifyChildAddedListener(child);
+ }
+
+
+ protected <T extends ConfiguredObject> void childRemoved(Class<T> clazz, T child)
+ {
+ synchronized (getLock())
+ {
+ Collection<ConfiguredObject> children = _children.get(clazz);
+ if(children != null)
+ {
+
+ children.remove(child);
+ }
+ }
+ notifyChildRemovedListener(child);
+ }
+
+ protected void notifyChildAddedListener(ConfiguredObject child)
+ {
+ for (ConfigurationChangeListener listener : _changeListeners)
+ {
+ listener.childAdded(this, child);
+ }
+ }
+
+ protected void notifyChildRemovedListener(ConfiguredObject child)
+ {
+ synchronized (getLock())
+ {
+ for (ConfigurationChangeListener listener : _changeListeners)
+ {
+ listener.childRemoved(this, child);
+ }
+ }
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ synchronized (getLock())
+ {
+ Collection<C> children = new ArrayList<C>();
+ if(_children.containsKey(clazz))
+ {
+ children.addAll((Collection<? extends C>) _children.get(clazz));
+ }
+ return children;
+ }
+ }
+
+ abstract protected Object getLock();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/BrokerImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/BrokerImpl.java
new file mode 100644
index 0000000000..fe554e2e1c
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/BrokerImpl.java
@@ -0,0 +1,148 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model.impl;
+
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+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.LifetimePolicy;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.model.VirtualHost;
+
+public class BrokerImpl extends AbstractConfiguredObject implements Broker
+{
+ private final Collection<VirtualHost> _virtualHosts = new ArrayList<VirtualHost>();
+ private final Collection<Port> _ports = new ArrayList<Port>();
+ private final Collection<AuthenticationProvider> _authenticationProviders = new ArrayList<AuthenticationProvider>();
+
+ public BrokerImpl(final UUID id,
+ final String name,
+ final State state,
+ final boolean durable,
+ final LifetimePolicy lifetimePolicy,
+ final long timeToLive,
+ final Map<String, Object> attributes)
+ {
+ super(id, name, state, durable, lifetimePolicy, timeToLive, attributes, Collections.EMPTY_MAP);
+ }
+
+ @Override
+ protected Object getLock()
+ {
+ return this;
+ }
+
+ public Collection<VirtualHost> getVirtualHosts()
+ {
+ synchronized (getLock())
+ {
+ return new ArrayList<VirtualHost>(_virtualHosts);
+ }
+ }
+
+ public Collection<Port> getPorts()
+ {
+ synchronized (getLock())
+ {
+ return new ArrayList<Port>(_ports);
+ }
+ }
+
+ public Collection<AuthenticationProvider> getAuthenticationProviders()
+ {
+ synchronized (getLock())
+ {
+ return new ArrayList<AuthenticationProvider>(_authenticationProviders);
+ }
+ }
+
+ public State getActualState()
+ {
+ return getDesiredState();
+ }
+
+ public Statistics getStatistics()
+ {
+ // TODO
+ return null;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public VirtualHost createVirtualHost(String name, State initialState,boolean durable,
+ LifetimePolicy lifetime, long ttl, Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ // TODO - check name is valid and not reserved
+ // TODO - check permissions
+
+ synchronized (getLock())
+ {
+ for(VirtualHost virtualHost : _virtualHosts)
+ {
+ if(virtualHost.getName().equals(name))
+ {
+ throw new IllegalArgumentException("A virtual host with the name '"+name+"' already exists");
+ }
+ }
+ VirtualHostImpl vhost = new VirtualHostImpl(UUID.randomUUID(),
+ name,
+ initialState,
+ durable,
+ lifetime,
+ ttl,
+ attributes,
+ this);
+ _virtualHosts.add(vhost);
+
+ // TODO - create a mapping for each port with "default" authentication provider and alias of the vhost name?
+
+ childAdded(VirtualHost.class, vhost);
+ return vhost;
+ }
+ }
+
+ public void deleteVirtualHost(VirtualHost virtualHost)
+ {
+ synchronized (getLock())
+ {
+ boolean found = _virtualHosts.remove(virtualHost);
+ if (!found)
+ {
+ throw new IllegalArgumentException("A virtual host with the name '" + virtualHost.getName() + "' does not exist");
+ }
+ childRemoved(VirtualHost.class, virtualHost);
+ }
+ }
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/ExchangeImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/ExchangeImpl.java
new file mode 100644
index 0000000000..91caf52f3a
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/ExchangeImpl.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.model.impl;
+
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Exchange;
+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.model.VirtualHost;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+class ExchangeImpl extends AbstractConfiguredObject implements Exchange
+{
+
+ private final VirtualHostImpl _virtualHost;
+
+ ExchangeImpl(final UUID id,
+ final String name,
+ final State state,
+ final boolean durable,
+ final LifetimePolicy lifetimePolicy,
+ final long timeToLive,
+ final String exchangeType,
+ final Map<String, Object> attributes,
+ final VirtualHostImpl parent)
+ {
+ super(id, name, state, durable, lifetimePolicy, timeToLive, fixAttributes(attributes, exchangeType),
+ (Map) Collections.singletonMap(VirtualHost.class, parent));
+ _virtualHost = parent;
+
+ }
+
+ private static Map<String, Object> fixAttributes(final Map<String, Object> attributes, final String exchangeType)
+ {
+ Map<String,Object> fixedAttributes = new HashMap<String, Object>(attributes);
+ fixedAttributes.put(TYPE, exchangeType);
+ return fixedAttributes;
+ }
+
+ @Override
+ protected Object getLock()
+ {
+ return _virtualHost.getLock();
+ }
+
+ public String getExchangeType()
+ {
+ return (String) getAttribute(TYPE);
+ }
+
+ public Collection<Binding> getBindings()
+ {
+ return null; //TODO
+ }
+
+ public Collection<Publisher> getPublishers()
+ {
+ return null; //TODO
+ }
+
+ public Binding createBinding(String bindingKey, Queue queue, Map<String, Object> bindingArguments,
+ Map<String, Object> attributes)
+ {
+ return null; // TODO - Implement
+ }
+
+ public void delete()
+ {
+ // TODO - Implement
+ }
+
+ public State getActualState()
+ {
+ State vhostState = _virtualHost.getActualState();
+ return vhostState == State.ACTIVE ? getDesiredState() : vhostState;
+ }
+
+ public Statistics getStatistics()
+ {
+ return null; // TODO
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new UnsupportedOperationException(); //TODO
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/QueueImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/QueueImpl.java
new file mode 100644
index 0000000000..bdd7ac5b45
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/QueueImpl.java
@@ -0,0 +1,107 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.QueueNotificationListener;
+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.VirtualHost;
+import org.apache.qpid.server.queue.QueueEntryVisitor;
+
+class QueueImpl extends AbstractConfiguredObject implements Queue
+{
+
+ private final VirtualHostImpl _virtualHost;
+
+ QueueImpl(final UUID id,
+ final String name,
+ final State state,
+ final boolean durable,
+ final LifetimePolicy lifetimePolicy,
+ final long timeToLive,
+ final Map<String, Object> attributes,
+ final VirtualHostImpl parent)
+ {
+ super(id, name, state, durable, lifetimePolicy, timeToLive, attributes,
+ (Map) Collections.singletonMap(VirtualHost.class, parent));
+
+ _virtualHost = parent;
+
+ }
+
+ @Override
+ protected Object getLock()
+ {
+ return _virtualHost.getLock();
+ }
+
+ public Collection<Binding> getBindings()
+ {
+ return null; //TODO
+ }
+
+ public Collection<Consumer> getConsumers()
+ {
+ return null; //TODO
+ }
+
+ public void visit(QueueEntryVisitor visitor)
+ {
+ //TODO
+ }
+
+ public void delete()
+ {
+ // TODO - Implement
+ }
+
+ public State getActualState()
+ {
+ State vhostState = _virtualHost.getActualState();
+ return vhostState == State.ACTIVE ? getDesiredState() : vhostState;
+ }
+
+ public Statistics getStatistics()
+ {
+ return null; //TODO
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new UnsupportedOperationException(); // TODO
+ }
+
+ @Override
+ public void setNotificationListener(QueueNotificationListener listener)
+ {
+ // TODO - implement
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/VirtualHostImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/VirtualHostImpl.java
new file mode 100644
index 0000000000..4a1b0b7127
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/impl/VirtualHostImpl.java
@@ -0,0 +1,248 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model.impl;
+
+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.Queue;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.VirtualHostAlias;
+
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+class VirtualHostImpl extends AbstractConfiguredObject implements VirtualHost
+{
+ // attribute names
+ private static final String REPLICATION_GROUP_NAME = "replicationGroupName";
+
+ private final Collection<VirtualHostAlias> _aliases = new ArrayList<VirtualHostAlias>();
+ private final Collection<Connection> _connections = new ArrayList<Connection>();
+ private final Collection<Queue> _queues = new ArrayList<Queue>();
+ private final Collection<Exchange> _exchanges = new ArrayList<Exchange>();
+
+ private final Map<String, Queue> _queueMap = new ConcurrentHashMap<String, Queue>();
+ private final Map<String, Exchange> _exchangeMap= new ConcurrentHashMap<String, Exchange>();
+
+ private final BrokerImpl _broker;
+
+
+ VirtualHostImpl(final UUID id,
+ final String name,
+ final State state,
+ final boolean durable,
+ final LifetimePolicy lifetimePolicy,
+ final long timeToLive,
+ final Map<String, Object> attributes,
+ final BrokerImpl parent)
+ {
+ super(id, name, state, durable, lifetimePolicy, timeToLive, attributes,
+ (Map) Collections.singletonMap(Broker.class, parent));
+
+ _broker = parent;
+ }
+
+ @Override
+ protected Object getLock()
+ {
+ return this;
+ }
+
+ public String getReplicationGroupName()
+ {
+ return (String) getAttribute(REPLICATION_GROUP_NAME);
+ }
+
+ @Override
+ public Object setAttribute(final String name, final Object expected, final Object desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ synchronized(getLock())
+ {
+ if(REPLICATION_GROUP_NAME.equals(name))
+ {
+ if(getActualState() != State.STOPPED)
+ {
+ throw new IllegalStateException("A virtual host must be stopped before you can change the replication group");
+ }
+ if(!(desired instanceof String))
+ {
+ throw new IllegalArgumentException("The desired replication group MUST be a String");
+ }
+ }
+ return super.setAttribute(name, expected, desired);
+ }
+ }
+
+ public Statistics getStatistics()
+ {
+ return null; //TODO
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ throw new UnsupportedOperationException(); // TODO
+ }
+
+ public Collection<VirtualHostAlias> getAliases()
+ {
+ synchronized(getLock())
+ {
+ return new ArrayList<VirtualHostAlias>(_aliases);
+ }
+ }
+
+ public Collection<Connection> getConnections()
+ {
+ synchronized (getLock())
+ {
+ return new ArrayList<Connection>(_connections);
+ }
+ }
+
+ public Collection<Queue> getQueues()
+ {
+ synchronized (getLock())
+ {
+ return new ArrayList<Queue>(_queues);
+ }
+ }
+
+ public Collection<Exchange> getExchanges()
+ {
+ synchronized (getLock())
+ {
+ return new ArrayList<Exchange>(_exchanges);
+ }
+ }
+
+ public State getActualState()
+ {
+ final State brokerActualState = _broker.getActualState();
+ return brokerActualState == State.ACTIVE ? getDesiredState() : brokerActualState;
+ }
+
+
+ public Exchange createExchange(String name, State initialState,boolean durable,
+ LifetimePolicy lifetime, long ttl, String type, Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ // TODO - check name is valid and not reserved
+ // TODO - check type
+ // TODO - check permissions
+
+ synchronized (getLock())
+ {
+ for(Exchange exchange : _exchanges)
+ {
+ if(exchange.getName().equals(name))
+ {
+ throw new IllegalArgumentException("A exchange with the name '"+name+"' already exists");
+ }
+ }
+ ExchangeImpl exchange = new ExchangeImpl(UUID.randomUUID(),
+ name,
+ initialState,
+ durable,
+ lifetime,
+ ttl,
+ type,
+ attributes,
+ this);
+ _exchanges.add(exchange);
+ _exchangeMap.put(name, exchange);
+
+ notifyChildAddedListener(exchange);
+ return exchange;
+ }
+ }
+
+
+ public Queue createQueue(String name, State initialState,boolean durable,
+ boolean exclusive, LifetimePolicy lifetime, long ttl, Map<String, Object> attributes)
+ throws AccessControlException, IllegalArgumentException
+ {
+ // TODO - check name is valid and not reserved
+ // TODO - check permissions
+
+ synchronized (getLock())
+ {
+ for(Queue queue : _queues)
+ {
+ if(queue.getName().equals(name))
+ {
+ throw new IllegalArgumentException("A queue with the name '"+name+"' already exists");
+ }
+ }
+ QueueImpl queue = new QueueImpl(UUID.randomUUID(),
+ name,
+ initialState,
+ durable,
+ lifetime,
+ ttl,
+ attributes,
+ this);
+
+ _queues.add(queue);
+ _queueMap.put(name, queue);
+
+ notifyChildAddedListener(queue);
+ // TODO - add binding to default exchange?, or make the default exchange work directly off the map held here
+
+ return queue;
+ }
+ }
+
+ public void deleteQueue(Queue queue)
+ {
+ synchronized (getLock())
+ {
+ boolean found = _queues.remove(queue);
+ if (!found)
+ {
+ throw new IllegalArgumentException("A queue with the name '" + queue.getName()+ "' does not exist");
+ }
+ _queueMap.remove(queue.getName());
+ notifyChildRemovedListener(queue);
+ }
+ }
+
+ public Collection<String> getExchangeTypes()
+ {
+ return null; // TODO - Implement
+ }
+
+ public void executeTransaction(TransactionalOperation op)
+ {
+ // TODO - Implement
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties
index badeffca05..4677d4b9e6 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties
@@ -31,12 +31,24 @@
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
@@ -46,37 +58,57 @@ 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.12
+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.servlet=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.junit.extensions.util=0.0.0
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.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.management=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
@@ -88,7 +120,10 @@ 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/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java
index b7fd2387a5..69ba7279bc 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java
@@ -77,4 +77,16 @@ public interface AMQConnectionModel extends StatisticsGatherer
public String getUserName();
public boolean isSessionNameUnique(byte[] name);
+
+ String getRemoteAddressString();
+
+ String getClientId();
+
+ String getClientVersion();
+
+ String getPrincipalAsString();
+
+ long getSessionCountLimit();
+
+ long getLastIoTime();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
index 5db336649f..850e293c3b 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
@@ -34,7 +34,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicBoolean;
-import javax.management.JMException;
import javax.security.auth.Subject;
import javax.security.sasl.SaslServer;
import org.apache.log4j.Logger;
@@ -62,8 +61,6 @@ 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.management.Managable;
-import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.output.ProtocolOutputConverterRegistry;
import org.apache.qpid.server.queue.QueueEntry;
@@ -81,7 +78,7 @@ import org.apache.qpid.transport.TransportException;
import org.apache.qpid.transport.network.NetworkConnection;
import org.apache.qpid.util.BytesDataOutput;
-public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQProtocolSession, ConnectionConfig
+public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSession, ConnectionConfig
{
private static final Logger _logger = Logger.getLogger(AMQProtocolEngine.class);
@@ -106,8 +103,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
private AMQCodecFactory _codecFactory;
- private AMQProtocolSessionMBean _managedObject;
-
private SaslServer _saslServer;
private Object _lastReceived;
@@ -148,8 +143,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
private final ConfigStore _configStore;
private long _createTime = System.currentTimeMillis();
- private ApplicationRegistry _registry;
- private boolean _statisticsEnabled = false;
private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
private NetworkConnection _network;
@@ -159,11 +152,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
private long _lastReceivedTime;
private boolean _blocking;
- public ManagedObject getManagedObject()
- {
- return _managedObject;
- }
-
public AMQProtocolEngine(VirtualHostRegistry virtualHostRegistry, NetworkConnection network, final long connectionId)
{
_stateManager = new AMQStateManager(virtualHostRegistry, this);
@@ -181,8 +169,8 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
_actor.message(ConnectionMessages.OPEN(null, null, null, false, false, false));
- _registry = virtualHostRegistry.getApplicationRegistry();
initialiseStatistics();
+
}
public void setNetworkConnection(NetworkConnection network)
@@ -196,11 +184,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
_sender = sender;
}
- private AMQProtocolSessionMBean createMBean() throws JMException
- {
- return new AMQProtocolSessionMBean(this);
- }
-
public long getSessionID()
{
return _connectionID;
@@ -649,17 +632,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
{
_cachedChannels[channelId] = channel;
}
-
- checkForNotification();
- }
-
- private void checkForNotification()
- {
- int channelsCount = _channelMap.size();
- if (_managedObject != null && channelsCount >= _maxNoOfChannels)
- {
- _managedObject.notifyClients("Channel count (" + channelsCount + ") has reached the threshold value");
- }
}
public Long getMaximumNumberOfChannels()
@@ -811,13 +783,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
getConfigStore().removeConfiguredObject(this);
- if (_managedObject != null)
- {
- _managedObject.unregister();
- // Ensure we only do this once.
- _managedObject = null;
- }
-
for (Task task : _taskList)
{
task.doTask(this);
@@ -1004,16 +969,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
_virtualHost.getConnectionRegistry().registerConnection(this);
_configStore.addConfiguredObject(this);
-
- try
- {
- _managedObject = createMBean();
- _managedObject.register();
- }
- catch (JMException e)
- {
- _logger.error(e);
- }
}
public void addSessionCloseTask(Task task)
@@ -1170,6 +1125,16 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
return _clientVersion;
}
+ public String getPrincipalAsString()
+ {
+ return getAuthId();
+ }
+
+ public long getSessionCountLimit()
+ {
+ return getMaximumNumberOfChannels();
+ }
+
public Boolean isIncoming()
{
return true;
@@ -1400,12 +1365,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
public List<AMQSessionModel> getSessionModels()
{
- List<AMQSessionModel> sessions = new ArrayList<AMQSessionModel>();
- for (AMQChannel channel : getChannels())
- {
- sessions.add((AMQSessionModel) channel);
- }
- return sessions;
+ return new ArrayList<AMQSessionModel>(getChannels());
}
public LogSubject getLogSubject()
@@ -1415,21 +1375,15 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
public void registerMessageDelivered(long messageSize)
{
- if (isStatisticsEnabled())
- {
- _messagesDelivered.registerEvent(1L);
- _dataDelivered.registerEvent(messageSize);
- }
+ _messagesDelivered.registerEvent(1L);
+ _dataDelivered.registerEvent(messageSize);
_virtualHost.registerMessageDelivered(messageSize);
}
public void registerMessageReceived(long messageSize, long timestamp)
{
- if (isStatisticsEnabled())
- {
- _messagesReceived.registerEvent(1L, timestamp);
- _dataReceived.registerEvent(messageSize, timestamp);
- }
+ _messagesReceived.registerEvent(1L, timestamp);
+ _dataReceived.registerEvent(messageSize, timestamp);
_virtualHost.registerMessageReceived(messageSize, timestamp);
}
@@ -1463,29 +1417,26 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
public void initialiseStatistics()
{
- setStatisticsEnabled(!StatisticsCounter.DISABLE_STATISTICS &&
- _registry.getConfiguration().isStatisticsGenerationConnectionsEnabled());
-
_messagesDelivered = new StatisticsCounter("messages-delivered-" + getSessionID());
_dataDelivered = new StatisticsCounter("data-delivered-" + getSessionID());
_messagesReceived = new StatisticsCounter("messages-received-" + getSessionID());
_dataReceived = new StatisticsCounter("data-received-" + getSessionID());
}
- public boolean isStatisticsEnabled()
+ public boolean isSessionNameUnique(byte[] name)
{
- return _statisticsEnabled;
+ // 0-8/0-9/0-9-1 sessions don't have names
+ return true;
}
- public void setStatisticsEnabled(boolean enabled)
+ public String getRemoteAddressString()
{
- _statisticsEnabled = enabled;
+ return String.valueOf(getRemoteAddress());
}
- public boolean isSessionNameUnique(byte[] name)
+ public String getClientId()
{
- // 0-8/0-9/0-9-1 sessions don't have names
- return true;
+ return String.valueOf(getContextKey());
}
public void setDeferFlush(boolean deferFlush)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java
deleted file mode 100644
index e70720600e..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-/*
- *
- * Copyright (c) 2006 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License")
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.qpid.server.protocol;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ConnectionCloseBody;
-import org.apache.qpid.framing.MethodRegistry;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.ManagementActor;
-import org.apache.qpid.server.management.AbstractAMQManagedConnectionObject;
-import org.apache.qpid.server.management.ManagedObject;
-
-import javax.management.JMException;
-import javax.management.MBeanException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.Date;
-import java.util.List;
-
-/**
- * This MBean class implements the management interface. In order to make more attributes, operations and notifications
- * available over JMX simply augment the ManagedConnection interface and add the appropriate implementation here.
- */
-@MBeanDescription("Management Bean for an AMQ Broker 0-9-1/0-9/0-8 Connections")
-public class AMQProtocolSessionMBean extends AbstractAMQManagedConnectionObject
-{
- private AMQProtocolSession _protocolSession = null;
-
- private static final AMQShortString BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION =
- new AMQShortString(BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION_STR);
-
- @MBeanConstructor("Creates an MBean exposing an AMQ Broker 0-9-1/0-9/0-8 Connection")
- public AMQProtocolSessionMBean(AMQProtocolSession amqProtocolSession) throws NotCompliantMBeanException, OpenDataException
- {
- super(amqProtocolSession.getRemoteAddress().toString());
- _protocolSession = amqProtocolSession;
- }
-
- public String getClientId()
- {
- return String.valueOf(_protocolSession.getContextKey());
- }
-
- public String getAuthorizedId()
- {
- return (_protocolSession.getAuthorizedPrincipal() != null ) ? _protocolSession.getAuthorizedPrincipal().getName() : null;
- }
-
- public String getVersion()
- {
- return _protocolSession.getClientVersion();
- }
-
- public Date getLastIoTime()
- {
- return new Date(_protocolSession.getLastIoTime());
- }
-
- public String getRemoteAddress()
- {
- return _protocolSession.getRemoteAddress().toString();
- }
-
- public ManagedObject getParentObject()
- {
- return _protocolSession.getVirtualHost().getManagedObject();
- }
-
- public Long getWrittenBytes()
- {
- return _protocolSession.getWrittenBytes();
- }
-
- public Long getReadBytes()
- {
- return _protocolSession.getWrittenBytes();
- }
-
- public Long getMaximumNumberOfChannels()
- {
- return _protocolSession.getMaximumNumberOfChannels();
- }
-
- /**
- * commits transactions for a transactional channel
- *
- * @param channelId
- * @throws JMException if channel with given id doesn't exist or if commit fails
- */
- public void commitTransactions(int channelId) throws JMException
- {
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- AMQChannel channel = _protocolSession.getChannel(channelId);
- if (channel == null)
- {
- throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
- }
-
- _protocolSession.commitTransactions(channel);
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex, ex.toString());
- }
- finally
- {
- CurrentActor.remove();
- }
- }
-
- /**
- * rollsback the transactions for a transactional channel
- *
- * @param channelId
- * @throws JMException if channel with given id doesn't exist or if rollback fails
- */
- public void rollbackTransactions(int channelId) throws JMException
- {
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- AMQChannel channel = _protocolSession.getChannel(channelId);
- if (channel == null)
- {
- throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
- }
-
- _protocolSession.rollbackTransactions(channel);
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex, ex.toString());
- }
- finally
- {
- CurrentActor.remove();
- }
- }
-
- /**
- * Creates the list of channels in tabular form from the _channelMap.
- *
- * @return list of channels in tabular form.
- * @throws OpenDataException
- */
- public TabularData channels() throws OpenDataException
- {
- TabularDataSupport channelsList = new TabularDataSupport(_channelsType);
- List<AMQChannel> list = _protocolSession.getChannels();
-
- for (AMQChannel channel : list)
- {
- Object[] itemValues =
- {
- channel.getChannelId(), channel.isTransactional(),
- (channel.getDefaultQueue() != null) ? channel.getDefaultQueue().getNameShortString().asString() : null,
- channel.getUnacknowledgedMessageMap().size(), channel.getBlocking()
- };
-
- CompositeData channelData = new CompositeDataSupport(_channelType,
- COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues);
- channelsList.put(channelData);
- }
-
- return channelsList;
- }
-
- /**
- * closes the connection. The administrator can use this management operation to close connection to free up
- * resources.
- * @throws JMException
- */
- public void closeConnection() throws JMException
- {
-
- MethodRegistry methodRegistry = _protocolSession.getMethodRegistry();
- ConnectionCloseBody responseBody =
- methodRegistry.createConnectionCloseBody(AMQConstant.REPLY_SUCCESS.getCode(),
- // replyCode
- BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION,
- // replyText,
- 0,
- 0);
-
- // This seems ugly but because we use closeConnection in both normal
- // broker operation and as part of the management interface it cannot
- // be avoided. The Current Actor will be null when this method is
- // called via the Management interface. This is because we allow the
- // Local API connection with JConsole. If we did not allow that option
- // then the CurrentActor could be set in our JMX Proxy object.
- // As it is we need to set the CurrentActor on all MBean methods
- // Ideally we would not have a single method that can be called from
- // two contexts.
- boolean removeActor = false;
- if (CurrentActor.get() == null)
- {
- removeActor = true;
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- }
-
- try
- {
- _protocolSession.writeFrame(responseBody.generateFrame(0));
-
- try
- {
-
- _protocolSession.closeSession();
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex, ex.toString());
- }
- }
- finally
- {
- if (removeActor)
- {
- CurrentActor.remove();
- }
- }
- }
-
- public void resetStatistics() throws Exception
- {
- _protocolSession.resetStatistics();
- }
-
- public double getPeakMessageDeliveryRate()
- {
- return _protocolSession.getMessageDeliveryStatistics().getPeak();
- }
-
- public double getPeakDataDeliveryRate()
- {
- return _protocolSession.getDataDeliveryStatistics().getPeak();
- }
-
- public double getMessageDeliveryRate()
- {
- return _protocolSession.getMessageDeliveryStatistics().getRate();
- }
-
- public double getDataDeliveryRate()
- {
- return _protocolSession.getDataDeliveryStatistics().getRate();
- }
-
- public long getTotalMessagesDelivered()
- {
- return _protocolSession.getMessageDeliveryStatistics().getTotal();
- }
-
- public long getTotalDataDelivered()
- {
- return _protocolSession.getDataDeliveryStatistics().getTotal();
- }
-
- public double getPeakMessageReceiptRate()
- {
- return _protocolSession.getMessageReceiptStatistics().getPeak();
- }
-
- public double getPeakDataReceiptRate()
- {
- return _protocolSession.getDataReceiptStatistics().getPeak();
- }
-
- public double getMessageReceiptRate()
- {
- return _protocolSession.getMessageReceiptStatistics().getRate();
- }
-
- public double getDataReceiptRate()
- {
- return _protocolSession.getDataReceiptStatistics().getRate();
- }
-
- public long getTotalMessagesReceived()
- {
- return _protocolSession.getMessageReceiptStatistics().getTotal();
- }
-
- public long getTotalDataReceived()
- {
- return _protocolSession.getDataReceiptStatistics().getTotal();
- }
-
- public boolean isStatisticsEnabled()
- {
- return _protocolSession.isStatisticsEnabled();
- }
-
- public void setStatisticsEnabled(boolean enabled)
- {
- _protocolSession.setStatisticsEnabled(enabled);
- }
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
index 0896499cda..efc64d9d91 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
@@ -55,7 +55,7 @@ public interface AMQSessionModel extends Comparable<AMQSessionModel>
* is logged or the connection is closed, depending on the configuration. An open
* transaction is one that has recent activity. The transaction age is counted
* from the time the transaction was started. An idle transaction is one that
- * has had no activity, such as publishing or acknowledgeing messages.
+ * has had no activity, such as publishing or acknowledging messages.
*
* @param openWarn time in milliseconds before alerting on open transaction
* @param openClose time in milliseconds before closing connection with open transaction
@@ -72,6 +72,16 @@ public interface AMQSessionModel extends Comparable<AMQSessionModel>
void unblock();
+ boolean getBlocking();
boolean onSameConnection(InboundMessage inbound);
+
+ int getUnacknowledgedMessageCount();
+
+ Long getTxnCount();
+ Long getTxnStart();
+ Long getTxnCommits();
+ Long getTxnRejects();
+
+ int getChannelId();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java
index 08926d000d..b4195d7e5a 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java
@@ -49,6 +49,7 @@ import org.apache.qpid.amqp_1_0.type.transport.Transfer;
import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.logging.LogActor;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.subscription.Subscription;
@@ -631,4 +632,46 @@ class Subscription_1_0 implements Subscription
{
_filters = filters;
}
+
+ @Override
+ public AMQSessionModel getSessionModel()
+ {
+ // TODO
+ return null;
+ }
+
+ @Override
+ public long getBytesOut()
+ {
+ // TODO
+ return 0;
+ }
+
+ @Override
+ public long getMessagesOut()
+ {
+ // TODO
+ return 0;
+ }
+
+ @Override
+ public long getUnacknowledgedBytes()
+ {
+ // TODO
+ return 0;
+ }
+
+ @Override
+ public long getUnacknowledgedMessages()
+ {
+ // TODO
+ return 0;
+ }
+
+ @Override
+ public String getConsumerName()
+ {
+ //TODO
+ return "TODO";
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
index e643338c3d..38847972d5 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
@@ -28,21 +28,25 @@ import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.exchange.ExchangeReferrer;
import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.management.Managable;
-import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.security.AuthorizationHolder;
import org.apache.qpid.server.store.TransactionLogResource;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
-public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeReferrer, TransactionLogResource, BaseQueue,
+public interface AMQQueue extends Comparable<AMQQueue>, ExchangeReferrer, TransactionLogResource, BaseQueue,
QueueConfig
{
+ public interface NotificationListener
+ {
+ void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg);
+ }
+
boolean getDeleteOnNoConsumers();
void setDeleteOnNoConsumers(boolean b);
@@ -57,6 +61,12 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
LogSubject getLogSubject();
+ long getUnackedMessageBytes();
+
+ long getTotalDequeueCount();
+
+ long getTotalEnqueueCount();
+
public interface Context
{
QueueEntry getLastSeenEntry();
@@ -79,6 +89,17 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
void unregisterSubscription(final Subscription subscription) throws AMQException;
+ Collection<Subscription> getConsumers();
+
+ interface SubscriptionRegistrationListener
+ {
+ void subscriptionRegistered(AMQQueue queue, Subscription subscription);
+ void subscriptionUnregistered(AMQQueue queue, Subscription subscription);
+ }
+
+ void addSubscriptionRegistrationListener(SubscriptionRegistrationListener listener);
+ void removeSubscriptionRegistrationListener(SubscriptionRegistrationListener listener);
+
int getConsumerCount();
@@ -109,7 +130,7 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
void dequeue(QueueEntry entry, Subscription sub);
- void decrementUnackedMsgCount();
+ void decrementUnackedMsgCount(QueueEntry queueEntry);
boolean resend(final QueueEntry entry, final Subscription subscription) throws AMQException;
@@ -146,13 +167,8 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
void removeMessagesFromQueue(long fromMessageId, long toMessageId);
- static interface Visitor
- {
- boolean visit(QueueEntry entry);
- }
-
- void visit(Visitor visitor);
-
+ void visit(QueueEntryVisitor visitor);
+
long getMaximumMessageSize();
@@ -216,8 +232,6 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
void setAlternateExchange(Exchange exchange);
- void setAlternateExchange(String exchangeName);
-
Map<String, Object> getArguments();
void checkCapacity(AMQSessionModel channel);
@@ -245,12 +259,12 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
}
/**
- * ExistingSubscriptionPreventsExclusive signals a failure to create an exclusize subscription, as a subscription
+ * ExistingSubscriptionPreventsExclusive signals a failure to create an exclusive subscription, as a subscription
* already exists.
*
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represent failure to create an exclusize subscription, as a subscription already exists.
+ * <tr><td> Represent failure to create an exclusive subscription, as a subscription already exists.
* </table>
*
* @todo Not an AMQP exception as no status code.
@@ -274,9 +288,7 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
ConfigurationPlugin getConfiguration();
- ManagedObject getManagedObject();
-
- void setExclusive(boolean exclusive) throws AMQException;
+ void setExclusive(boolean exclusive);
/**
* Gets the maximum delivery count. If a message on this queue
@@ -295,4 +307,19 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
*/
public void setMaximumDeliveryCount(final int maximumDeliveryCount);
+ void setNotificationListener(NotificationListener listener);
+
+ /**
+ * Sets the free text description of this queue.
+ *
+ * @param description
+ *
+ */
+ void setDescription(String description);
+
+ /**
+ * Gets the free text description of this queue.
+ */
+ String getDescription();
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
index f2b7d7c56b..d93af2fc25 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.queue;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@@ -41,6 +42,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost;
public class AMQQueueFactory
{
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";
public static final String QPID_LAST_VALUE_QUEUE = "qpid.last_value_queue";
public static final String QPID_LAST_VALUE_QUEUE_KEY = "qpid.last_value_queue_key";
@@ -350,32 +352,7 @@ public class AMQQueueFactory
boolean autodelete = config.getAutoDelete();
boolean exclusive = config.getExclusive();
String owner = config.getOwner();
- Map<String,Object> arguments = null;
-
- if(config.isLVQ() || config.getLVQKey() != null)
- {
- arguments = new HashMap<String,Object>();
- arguments.put(QPID_LAST_VALUE_QUEUE, 1);
- arguments.put(QPID_LAST_VALUE_QUEUE_KEY, config.getLVQKey() == null ? QPID_LVQ_KEY : config.getLVQKey());
- }
- else if (config.getPriority() || config.getPriorities() > 0)
- {
- arguments = new HashMap<String,Object>();
- arguments.put(X_QPID_PRIORITIES, config.getPriorities() < 0 ? 10 : config.getPriorities());
- }
- else if (config.getQueueSortKey() != null && !"".equals(config.getQueueSortKey()))
- {
- arguments = new HashMap<String,Object>();
- arguments.put(QPID_QUEUE_SORT_KEY, config.getQueueSortKey());
- }
- if (!config.getAutoDelete() && config.isDeadLetterQueueEnabled())
- {
- if (arguments == null)
- {
- arguments = new HashMap<String,Object>();
- }
- arguments.put(X_QPID_DLQ_ENABLED, true);
- }
+ Map<String, Object> arguments = createQueueArgumentsFromConfig(config);
// we need queues that are defined in config to have deterministic ids.
UUID id = UUIDGenerator.generateUUID(queueName, host.getName());
@@ -385,7 +362,6 @@ public class AMQQueueFactory
return q;
}
-
/**
* Validates DLQ and DLE names
* <p>
@@ -475,4 +451,43 @@ public class AMQQueueFactory
String dlExchangeName = name + serverConfig.getDeadLetterExchangeSuffix();
return dlExchangeName;
}
+
+ private static Map<String, Object> createQueueArgumentsFromConfig(QueueConfiguration config)
+ {
+ Map<String,Object> arguments = new HashMap<String,Object>();
+
+ if(config.isLVQ() || config.getLVQKey() != null)
+ {
+ arguments.put(QPID_LAST_VALUE_QUEUE, 1);
+ arguments.put(QPID_LAST_VALUE_QUEUE_KEY, config.getLVQKey() == null ? QPID_LVQ_KEY : config.getLVQKey());
+ }
+ else if (config.getPriority() || config.getPriorities() > 0)
+ {
+ arguments.put(X_QPID_PRIORITIES, config.getPriorities() < 0 ? 10 : config.getPriorities());
+ }
+ else if (config.getQueueSortKey() != null && !"".equals(config.getQueueSortKey()))
+ {
+ arguments.put(QPID_QUEUE_SORT_KEY, config.getQueueSortKey());
+ }
+
+ if (!config.getAutoDelete() && config.isDeadLetterQueueEnabled())
+ {
+ arguments.put(X_QPID_DLQ_ENABLED, true);
+ }
+
+ if (config.getDescription() != null && !"".equals(config.getDescription()))
+ {
+ arguments.put(X_QPID_DESCRIPTION, config.getDescription());
+ }
+
+ if (arguments.isEmpty())
+ {
+ return Collections.emptyMap();
+ }
+ else
+ {
+ return arguments;
+ }
+ }
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
deleted file mode 100644
index b0d4cb3486..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
+++ /dev/null
@@ -1,664 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import org.apache.commons.lang.time.FastDateFormat;
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.management.AMQManagedObject;
-import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.message.AMQMessage;
-import org.apache.qpid.server.message.AMQMessageHeader;
-import org.apache.qpid.server.message.MessageTransferMessage;
-import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.transport.MessageProperties;
-
-import javax.management.JMException;
-import javax.management.MBeanException;
-import javax.management.MBeanNotificationInfo;
-import javax.management.Notification;
-import javax.management.ObjectName;
-import javax.management.OperationsException;
-import javax.management.monitor.MonitorNotification;
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.TabularType;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-
-/**
- * AMQQueueMBean is the management bean for an {@link AMQQueue}.
- *
- * <p/><table id="crc"><caption>CRC Caption</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * </table>
- */
-@MBeanDescription("Management Interface for AMQQueue")
-public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, QueueNotificationListener
-{
-
- /** Used for debugging purposes. */
- private static final Logger LOGGER = Logger.getLogger(AMQQueueMBean.class);
-
- /** Date/time format used for message expiration and message timestamp formatting */
- public static final String JMSTIMESTAMP_DATETIME_FORMAT = "MM-dd-yy HH:mm:ss.SSS z";
-
- private static final FastDateFormat FAST_DATE_FORMAT = FastDateFormat.getInstance(JMSTIMESTAMP_DATETIME_FORMAT);
-
- private final AMQQueue _queue;
- private final String _queueName;
- // OpenMBean data types for viewMessages method
-
- private static OpenType[] _msgAttributeTypes = new OpenType[6]; // AMQ message attribute types.
- private static CompositeType _messageDataType = null; // Composite type for representing AMQ Message data.
- private static TabularType _messagelistDataType = null; // Datatype for representing AMQ messages list.
-
- // OpenMBean data types for viewMessageContent method
- private static CompositeType _msgContentType = null;
- private static OpenType[] _msgContentAttributeTypes = new OpenType[4];
-
- private final long[] _lastNotificationTimes = new long[NotificationCheck.values().length];
- private Notification _lastNotification = null;
-
-
-
-
- @MBeanConstructor("Creates an MBean exposing an AMQQueue")
- public AMQQueueMBean(AMQQueue queue) throws JMException
- {
- super(ManagedQueue.class, ManagedQueue.TYPE);
- _queue = queue;
- _queueName = queue.getName();
- }
-
- public ManagedObject getParentObject()
- {
- return _queue.getVirtualHost().getManagedObject();
- }
-
- static
- {
- try
- {
- init();
- }
- catch (JMException ex)
- {
- // This is not expected to ever occur.
- throw new RuntimeException("Got JMException in static initializer.", ex);
- }
- }
-
- /**
- * initialises the openmbean data types
- */
- private static void init() throws OpenDataException
- {
- _msgContentAttributeTypes[0] = SimpleType.LONG; // For message id
- _msgContentAttributeTypes[1] = SimpleType.STRING; // For MimeType
- _msgContentAttributeTypes[2] = SimpleType.STRING; // For Encoding
- _msgContentAttributeTypes[3] = new ArrayType(1, SimpleType.BYTE); // For message content
- _msgContentType = new CompositeType("Message Content", "AMQ Message Content",
- VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]),
- VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]),
- _msgContentAttributeTypes);
-
- _msgAttributeTypes[0] = SimpleType.LONG; // For message id
- _msgAttributeTypes[1] = new ArrayType(1, SimpleType.STRING); // For header attributes
- _msgAttributeTypes[2] = SimpleType.LONG; // For size
- _msgAttributeTypes[3] = SimpleType.BOOLEAN; // For redelivered
- _msgAttributeTypes[4] = SimpleType.LONG; // For queue position
- _msgAttributeTypes[5] = SimpleType.INTEGER; // For delivery count
-
- _messageDataType = new CompositeType("Message", "AMQ Message",
- VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.size()]),
- VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.size()]), _msgAttributeTypes);
- _messagelistDataType = new TabularType("Messages", "List of messages", _messageDataType,
- VIEW_MSGS_TABULAR_UNIQUE_INDEX.toArray(new String[VIEW_MSGS_TABULAR_UNIQUE_INDEX.size()]));
- }
-
- public String getObjectInstanceName()
- {
- return ObjectName.quote(_queueName);
- }
-
- public String getName()
- {
- return _queueName;
- }
-
- public boolean isDurable()
- {
- return _queue.isDurable();
- }
-
- public String getOwner()
- {
- return String.valueOf(_queue.getOwner());
- }
-
- public boolean isAutoDelete()
- {
- return _queue.isAutoDelete();
- }
-
- public Integer getMessageCount()
- {
- return _queue.getMessageCount();
- }
-
- public Integer getMaximumDeliveryCount()
- {
- return _queue.getMaximumDeliveryCount();
- }
-
- public Long getMaximumMessageSize()
- {
- return _queue.getMaximumMessageSize();
- }
-
- public Long getMaximumMessageAge()
- {
- return _queue.getMaximumMessageAge();
- }
-
- public void setMaximumMessageAge(Long maximumMessageAge)
- {
- _queue.setMaximumMessageAge(maximumMessageAge);
- }
-
- public void setMaximumMessageSize(Long value)
- {
- _queue.setMaximumMessageSize(value);
- }
-
- public Integer getConsumerCount()
- {
- return _queue.getConsumerCount();
- }
-
- public Integer getActiveConsumerCount()
- {
- return _queue.getActiveConsumerCount();
- }
-
- public Long getReceivedMessageCount()
- {
- return _queue.getReceivedMessageCount();
- }
-
- public Long getMaximumMessageCount()
- {
- return _queue.getMaximumMessageCount();
- }
-
- public void setMaximumMessageCount(Long value)
- {
- _queue.setMaximumMessageCount(value);
- }
-
- /**
- * returns the maximum total size of messages(bytes) in the queue.
- */
- public Long getMaximumQueueDepth()
- {
- return _queue.getMaximumQueueDepth();
- }
-
- public void setMaximumQueueDepth(Long value)
- {
- _queue.setMaximumQueueDepth(value);
- }
-
- /**
- * returns the total size of messages(bytes) in the queue.
- */
- public Long getQueueDepth() throws JMException
- {
- return _queue.getQueueDepth();
- }
-
- public Long getCapacity()
- {
- return _queue.getCapacity();
- }
-
- public void setCapacity(Long capacity) throws IllegalArgumentException
- {
- if( _queue.getFlowResumeCapacity() > capacity )
- {
- throw new IllegalArgumentException("Capacity must not be less than FlowResumeCapacity");
- }
-
- _queue.setCapacity(capacity);
- }
-
- public Long getFlowResumeCapacity()
- {
- return _queue.getFlowResumeCapacity();
- }
-
- public void setFlowResumeCapacity(Long flowResumeCapacity) throws IllegalArgumentException
- {
- if( _queue.getCapacity() < flowResumeCapacity )
- {
- throw new IllegalArgumentException("FlowResumeCapacity must not exceed Capacity");
- }
-
- _queue.setFlowResumeCapacity(flowResumeCapacity);
- }
-
- public boolean isFlowOverfull()
- {
- return _queue.isOverfull();
- }
-
- public boolean isExclusive()
- {
- return _queue.isExclusive();
- }
-
- public void setExclusive(boolean exclusive) throws JMException
- {
- try
- {
- _queue.setExclusive(exclusive);
- }
- catch (AMQException e)
- {
- throw new JMException(e.toString());
- }
- }
-
- public void setAlternateExchange(String exchangeName)
- {
- _queue.setAlternateExchange(exchangeName);
- }
-
- public String getAlternateExchange()
- {
- Exchange exchange = _queue.getAlternateExchange();
- String name = exchange == null ? null : exchange.getName();
- return name == null ? null : name;
- }
-
- /**
- * Checks if there is any notification to be send to the listeners
- */
- public void checkForNotification(ServerMessage msg) throws AMQException
- {
-
- final Set<NotificationCheck> notificationChecks = _queue.getNotificationChecks();
-
- if(!notificationChecks.isEmpty())
- {
- final long currentTime = System.currentTimeMillis();
- final long thresholdTime = currentTime - _queue.getMinimumAlertRepeatGap();
-
- for (NotificationCheck check : notificationChecks)
- {
- if (check.isMessageSpecific() || (_lastNotificationTimes[check.ordinal()] < thresholdTime))
- {
- if (check.notifyIfNecessary(msg, _queue, this))
- {
- _lastNotificationTimes[check.ordinal()] = currentTime;
- }
- }
- }
- }
-
- }
-
- /**
- * Sends the notification to the listeners
- */
- public void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg)
- {
- // important : add log to the log file - monitoring tools may be looking for this
- LOGGER.info(notification.name() + " On Queue " + queue.getNameShortString() + " - " + notificationMsg);
- notificationMsg = notification.name() + " " + notificationMsg;
-
- _lastNotification =
- new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this, incrementAndGetSequenceNumber(),
- System.currentTimeMillis(), notificationMsg);
-
- getBroadcaster().sendNotification(_lastNotification);
- }
-
- public Notification getLastNotification()
- {
- return _lastNotification;
- }
-
- /**
- * @see AMQQueue#deleteMessageFromTop
- */
- public void deleteMessageFromTop() throws JMException
- {
- _queue.deleteMessageFromTop();
- }
-
- /**
- * Clears the queue of non-acquired messages
- *
- * @return the number of messages deleted
- * @see AMQQueue#clearQueue
- */
- public Long clearQueue() throws JMException
- {
- try
- {
- return _queue.clearQueue();
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex, "Error clearing queue " + _queueName);
- }
- }
-
- /**
- * returns message content as byte array and related attributes for the given message id.
- */
- public CompositeData viewMessageContent(long msgId) throws JMException
- {
- QueueEntry entry = _queue.getMessageOnTheQueue(msgId);
-
- if (entry == null)
- {
- throw new OperationsException("AMQMessage with message id = " + msgId + " is not in the " + _queueName);
- }
-
- ServerMessage serverMsg = entry.getMessage();
- final int bodySize = (int) serverMsg.getSize();
-
-
- List<Byte> msgContent = new ArrayList<Byte>();
-
- java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(bodySize);
- int position = 0;
-
- while(position < bodySize)
- {
- position += serverMsg.getContent(buf, position);
- buf.flip();
- for(int i = 0; i < buf.limit(); i++)
- {
- msgContent.add(buf.get(i));
- }
- buf.clear();
- }
-
- AMQMessageHeader header = serverMsg.getMessageHeader();
-
- String mimeType = null, encoding = null;
- if (header != null)
- {
- mimeType = header.getMimeType();
-
- encoding = header.getEncoding();
- }
-
-
- Object[] itemValues = { msgId, mimeType, encoding, msgContent.toArray(new Byte[0]) };
-
- return new CompositeDataSupport(_msgContentType,
- VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(
- new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues);
-
- }
-
- /**
- * Returns the header contents of the messages stored in this queue in tabular form.
- * Deprecated as of Qpid JMX API 1.3
- */
- @Deprecated
- public TabularData viewMessages(int beginIndex, int endIndex) throws JMException
- {
- return viewMessages((long)beginIndex,(long)endIndex);
- }
-
-
- /**
- * Returns the header contents of the messages stored in this queue in tabular form.
- * @param startPosition The queue position of the first message to be viewed
- * @param endPosition The queue position of the last message to be viewed
- */
- public TabularData viewMessages(long startPosition, long endPosition) throws JMException
- {
- if ((startPosition > endPosition) || (startPosition < 1))
- {
- throw new OperationsException("From Index = " + startPosition + ", To Index = " + endPosition
- + "\n\"From Index\" should be greater than 0 and less than \"To Index\"");
- }
-
- if ((endPosition - startPosition) > Integer.MAX_VALUE)
- {
- throw new OperationsException("Specified MessageID interval is too large. Intervals must be less than 2^31 in size");
- }
-
- List<QueueEntry> list = _queue.getMessagesRangeOnTheQueue(startPosition,endPosition);
- TabularDataSupport _messageList = new TabularDataSupport(_messagelistDataType);
-
- try
- {
- // Create the tabular list of message header contents
- int size = list.size();
-
- for (int i = 0; i < size ; i++)
- {
- long position = startPosition + i;
- final QueueEntry queueEntry = list.get(i);
- ServerMessage serverMsg = queueEntry.getMessage();
-
- String[] headerAttributes = null;
- Object[] itemValues = null;
-
- if(serverMsg instanceof AMQMessage)
- {
- AMQMessage msg = (AMQMessage) serverMsg;
- ContentHeaderBody headerBody = msg.getContentHeaderBody();
- // Create header attributes list
- headerAttributes = getMessageHeaderProperties(headerBody);
- itemValues = new Object[]{msg.getMessageId(), headerAttributes, headerBody.getBodySize(), queueEntry.isRedelivered(), position, queueEntry.getDeliveryCount()};
- }
- else if(serverMsg instanceof MessageTransferMessage)
- {
- // We have a 0-10 message
- MessageTransferMessage msg = (MessageTransferMessage) serverMsg;
-
- // Create header attributes list
- headerAttributes = getMessageTransferMessageHeaderProps(msg);
- itemValues = new Object[]{msg.getMessageNumber(), headerAttributes, msg.getSize(), queueEntry.isRedelivered(), position, queueEntry.getDeliveryCount()};
- }
- else
- {
- //unknown message
- headerAttributes = new String[]{"N/A"};
- itemValues = new Object[]{serverMsg.getMessageNumber(), headerAttributes, serverMsg.getSize(), queueEntry.isRedelivered(), position, queueEntry.getDeliveryCount()};
- }
-
- CompositeData messageData = new CompositeDataSupport(_messageDataType,
- VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues);
- _messageList.put(messageData);
- }
- }
- catch (AMQException e)
- {
- JMException jme = new JMException("Error creating message contents: " + e);
- jme.initCause(e);
- throw jme;
- }
-
- return _messageList;
- }
-
- private String[] getMessageHeaderProperties(ContentHeaderBody headerBody)
- {
- List<String> list = new ArrayList<String>();
- BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties) headerBody.getProperties();
- list.add("reply-to = " + headerProperties.getReplyToAsString());
- list.add("propertyFlags = " + headerProperties.getPropertyFlags());
- list.add("ApplicationID = " + headerProperties.getAppIdAsString());
- list.add("ClusterID = " + headerProperties.getClusterIdAsString());
- list.add("UserId = " + headerProperties.getUserIdAsString());
- list.add("JMSMessageID = " + headerProperties.getMessageIdAsString());
- list.add("JMSCorrelationID = " + headerProperties.getCorrelationIdAsString());
-
- int delMode = headerProperties.getDeliveryMode();
- list.add("JMSDeliveryMode = " +
- ((delMode == BasicContentHeaderProperties.PERSISTENT) ? "Persistent" : "Non_Persistent"));
-
- list.add("JMSPriority = " + headerProperties.getPriority());
- list.add("JMSType = " + headerProperties.getType());
-
- final long expirationDate = headerProperties.getExpiration();
- final long timestampDate = headerProperties.getTimestamp();
-
- addStringifiedJMSTimestamoAndJMSExpiration(list, expirationDate,
- timestampDate);
-
- return list.toArray(new String[list.size()]);
- }
-
- private String[] getMessageTransferMessageHeaderProps(MessageTransferMessage msg)
- {
- List<String> list = new ArrayList<String>();
-
- AMQMessageHeader header = msg.getMessageHeader();
- MessageProperties msgProps = msg.getHeader().getMessageProperties();
-
- String appID = null;
- String userID = null;
-
- if(msgProps != null)
- {
- appID = msgProps.getAppId() == null ? "null" : new String(msgProps.getAppId());
- userID = msgProps.getUserId() == null ? "null" : new String(msgProps.getUserId());
- }
-
- list.add("reply-to = " + header.getReplyTo());
- list.add("propertyFlags = "); //TODO
- list.add("ApplicationID = " + appID);
- list.add("ClusterID = "); //TODO
- list.add("UserId = " + userID);
- list.add("JMSMessageID = " + header.getMessageId());
- list.add("JMSCorrelationID = " + header.getCorrelationId());
- list.add("JMSDeliveryMode = " + (msg.isPersistent() ? "Persistent" : "Non_Persistent"));
- list.add("JMSPriority = " + header.getPriority());
- list.add("JMSType = " + header.getType());
-
- final long expirationDate = header.getExpiration();
- final long timestampDate = header.getTimestamp();
- addStringifiedJMSTimestamoAndJMSExpiration(list, expirationDate, timestampDate);
-
- return list.toArray(new String[list.size()]);
- }
-
- private void addStringifiedJMSTimestamoAndJMSExpiration(final List<String> list,
- final long expirationDate, final long timestampDate)
- {
- final String formattedExpirationDate = (expirationDate != 0) ? FAST_DATE_FORMAT.format(expirationDate) : null;
- final String formattedTimestampDate = (timestampDate != 0) ? FAST_DATE_FORMAT.format(timestampDate) : null;
- list.add("JMSExpiration = " + formattedExpirationDate);
- list.add("JMSTimestamp = " + formattedTimestampDate);
- }
-
- /**
- * @see ManagedQueue#moveMessages
- * @param fromMessageId
- * @param toMessageId
- * @param toQueueName
- * @throws JMException
- */
- public void moveMessages(long fromMessageId, long toMessageId, String toQueueName) throws JMException
- {
- if ((fromMessageId > toMessageId) || (fromMessageId < 1))
- {
- throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
- }
-
- _queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName);
- }
-
- /**
- * @see ManagedQueue#deleteMessages
- * @param fromMessageId
- * @param toMessageId
- * @throws JMException
- */
- public void deleteMessages(long fromMessageId, long toMessageId) throws JMException
- {
- if ((fromMessageId > toMessageId) || (fromMessageId < 1))
- {
- throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
- }
-
- _queue.removeMessagesFromQueue(fromMessageId, toMessageId);
- }
-
- /**
- * @see ManagedQueue#copyMessages
- * @param fromMessageId
- * @param toMessageId
- * @param toQueueName
- * @throws JMException
- */
- public void copyMessages(long fromMessageId, long toMessageId, String toQueueName) throws JMException
- {
- if ((fromMessageId > toMessageId) || (fromMessageId < 1))
- {
- throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\"");
- }
-
- _queue.copyMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName);
- }
-
- /**
- * returns Notifications sent by this MBean.
- */
- @Override
- public MBeanNotificationInfo[] getNotificationInfo()
- {
- String[] notificationTypes = new String[] { MonitorNotification.THRESHOLD_VALUE_EXCEEDED };
- String name = MonitorNotification.class.getName();
- String description = "Either Message count or Queue depth or Message size has reached threshold high value";
- MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description);
-
- return new MBeanNotificationInfo[] { info1 };
- }
-
-} // End of AMQQueueMBean class
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java
index 2493974d45..27a9e13617 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java
@@ -20,12 +20,10 @@
*/
package org.apache.qpid.server.queue;
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.exchange.DefaultExchangeRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@@ -33,11 +31,11 @@ import java.util.concurrent.ConcurrentMap;
public class DefaultQueueRegistry implements QueueRegistry
{
- private static final Logger LOGGER = Logger.getLogger(DefaultExchangeRegistry.class);
-
private ConcurrentMap<AMQShortString, AMQQueue> _queueMap = new ConcurrentHashMap<AMQShortString, AMQQueue>();
private final VirtualHost _virtualHost;
+ private final Collection<RegistryChangeListener> _listeners =
+ new ArrayList<RegistryChangeListener>();
public DefaultQueueRegistry(VirtualHost virtualHost)
{
@@ -52,11 +50,28 @@ public class DefaultQueueRegistry implements QueueRegistry
public void registerQueue(AMQQueue queue)
{
_queueMap.put(queue.getNameShortString(), queue);
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.queueRegistered(queue);
+ }
+ }
}
public void unregisterQueue(AMQShortString name)
{
- _queueMap.remove(name);
+ AMQQueue q = _queueMap.remove(name);
+ if(q != null)
+ {
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.queueUnregistered(q);
+ }
+ }
+ }
}
public AMQQueue getQueue(AMQShortString name)
@@ -79,19 +94,30 @@ public class DefaultQueueRegistry implements QueueRegistry
return getQueue(new AMQShortString(queue));
}
+ public void addRegistryChangeListener(RegistryChangeListener listener)
+ {
+ synchronized(_listeners)
+ {
+ _listeners.add(listener);
+ }
+ }
+
@Override
public void stopAllAndUnregisterMBeans()
{
for (final AMQQueue queue : getQueues())
{
queue.stop();
- try
- {
- queue.getManagedObject().unregister();
- }
- catch (AMQException e)
+
+ //TODO: this is a bit of a hack, what if the listeners aren't aware
+ //that we are just unregistering the MBean because of HA, and aren't
+ //actually removing the queue as such.
+ synchronized (_listeners)
{
- LOGGER.warn("Failed to unregister mbean", e);
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.queueUnregistered(queue);
+ }
}
}
_queueMap.clear();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
index c1ebbe412f..3efef9ab98 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.queue;
+import org.apache.log4j.Logger;
import org.apache.qpid.server.message.ServerMessage;
public enum NotificationCheck
@@ -27,13 +28,16 @@ public enum NotificationCheck
MESSAGE_COUNT_ALERT
{
- boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener)
{
int msgCount;
final long maximumMessageCount = queue.getMaximumMessageCount();
if (maximumMessageCount!= 0 && (msgCount = queue.getMessageCount()) >= maximumMessageCount)
{
- listener.notifyClients(this, queue, msgCount + ": Maximum count on queue threshold ("+ maximumMessageCount +") breached.");
+ String notificationMsg = msgCount + ": Maximum count on queue threshold ("+ maximumMessageCount +") breached.";
+
+ logNotification(this, queue, notificationMsg);
+ listener.notifyClients(this, queue, notificationMsg);
return true;
}
return false;
@@ -41,7 +45,7 @@ public enum NotificationCheck
},
MESSAGE_SIZE_ALERT(true)
{
- boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener)
{
final long maximumMessageSize = queue.getMaximumMessageSize();
if(maximumMessageSize != 0)
@@ -50,10 +54,12 @@ public enum NotificationCheck
long messageSize;
messageSize = (msg == null) ? 0 : msg.getSize();
-
if (messageSize >= maximumMessageSize)
{
- listener.notifyClients(this, queue, messageSize + "b : Maximum message size threshold ("+ maximumMessageSize +") breached. [Message ID=" + msg.getMessageNumber() + "]");
+ String notificationMsg = messageSize + "b : Maximum message size threshold ("+ maximumMessageSize +") breached. [Message ID=" + msg.getMessageNumber() + "]";
+
+ logNotification(this, queue, notificationMsg);
+ listener.notifyClients(this, queue, notificationMsg);
return true;
}
}
@@ -63,7 +69,7 @@ public enum NotificationCheck
},
QUEUE_DEPTH_ALERT
{
- boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener)
{
// Check for threshold queue depth in bytes
final long maximumQueueDepth = queue.getMaximumQueueDepth();
@@ -74,7 +80,10 @@ public enum NotificationCheck
if (queueDepth >= maximumQueueDepth)
{
- listener.notifyClients(this, queue, (queueDepth>>10) + "Kb : Maximum queue depth threshold ("+(maximumQueueDepth>>10)+"Kb) breached.");
+ String notificationMsg = (queueDepth>>10) + "Kb : Maximum queue depth threshold ("+(maximumQueueDepth>>10)+"Kb) breached.";
+
+ logNotification(this, queue, notificationMsg);
+ listener.notifyClients(this, queue, notificationMsg);
return true;
}
}
@@ -84,7 +93,7 @@ public enum NotificationCheck
},
MESSAGE_AGE_ALERT
{
- boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener)
{
final long maxMessageAge = queue.getMaximumMessageAge();
@@ -97,7 +106,10 @@ public enum NotificationCheck
if(firstArrivalTime < thresholdTime)
{
long oldestAge = currentTime - firstArrivalTime;
- listener.notifyClients(this, queue, (oldestAge/1000) + "s : Maximum age on queue threshold ("+(maxMessageAge /1000)+"s) breached.");
+ String notificationMsg = (oldestAge/1000) + "s : Maximum age on queue threshold ("+(maxMessageAge /1000)+"s) breached.";
+
+ logNotification(this, queue, notificationMsg);
+ listener.notifyClients(this, queue, notificationMsg);
return true;
}
@@ -109,6 +121,8 @@ public enum NotificationCheck
}
;
+ private static final Logger LOGGER = Logger.getLogger(NotificationCheck.class);
+
private final boolean _messageSpecific;
NotificationCheck()
@@ -126,6 +140,11 @@ public enum NotificationCheck
return _messageSpecific;
}
- abstract boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener);
+ public abstract boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener);
+ //A bit of a hack, only for use until we do the logging listener
+ private static void logNotification(NotificationCheck notification, AMQQueue queue, String notificationMsg)
+ {
+ LOGGER.info(notification.name() + " On Queue " + queue.getNameShortString() + " - " + notificationMsg);
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
index 209553e8fa..25e771a9cf 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
@@ -233,7 +233,7 @@ public abstract class QueueEntryImpl implements QueueEntry
if(state instanceof SubscriptionAcquiredState)
{
- getQueue().decrementUnackedMsgCount();
+ getQueue().decrementUnackedMsgCount(this);
Subscription subscription = ((SubscriptionAcquiredState)state).getSubscription();
if (subscription != null)
{
@@ -369,7 +369,7 @@ public abstract class QueueEntryImpl implements QueueEntry
Subscription s = null;
if (state instanceof SubscriptionAcquiredState)
{
- getQueue().decrementUnackedMsgCount();
+ getQueue().decrementUnackedMsgCount(this);
s = ((SubscriptionAcquiredState) state).getSubscription();
s.onDequeue(this);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java
index 72a54c9889..e8c34128e9 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java
@@ -42,7 +42,15 @@ public interface QueueRegistry
AMQQueue getQueue(String queue);
+ void addRegistryChangeListener(RegistryChangeListener listener);
+
void stopAllAndUnregisterMBeans();
AMQQueue getQueue(UUID queueId);
+
+ interface RegistryChangeListener
+ {
+ void queueRegistered(AMQQueue queue);
+ void queueUnregistered(AMQQueue queue);
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
index d7eb304c92..4e609af254 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
@@ -19,8 +19,10 @@
package org.apache.qpid.server.queue;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -32,8 +34,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
-import javax.management.JMException;
-
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQSecurityException;
@@ -52,7 +52,6 @@ import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.QueueActor;
import org.apache.qpid.server.logging.messages.QueueMessages;
import org.apache.qpid.server.logging.subjects.QueueLogSubject;
-import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.registry.ApplicationRegistry;
@@ -70,6 +69,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost;
public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, MessageGroupManager.SubscriptionResetHelper
{
private static final Logger _logger = Logger.getLogger(SimpleAMQQueue.class);
+
private static final String QPID_GROUP_HEADER_KEY = "qpid.group_header_key";
private static final String QPID_SHARED_MSG_GROUP = "qpid.shared_msg_group";
private static final String QPID_DEFAULT_MESSAGE_GROUP = "qpid.default-message-group";
@@ -77,11 +77,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
// TODO - should make this configurable at the vhost / broker level
private static final int DEFAULT_MAX_GROUPS = 255;
-
private final VirtualHost _virtualHost;
private final AMQShortString _name;
- private final String _resourceName;
/** null means shared */
private final AMQShortString _owner;
@@ -118,6 +116,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private final AtomicLong _dequeueCount = new AtomicLong();
private final AtomicLong _dequeueSize = new AtomicLong();
+ private final AtomicLong _enqueueCount = new AtomicLong();
private final AtomicLong _enqueueSize = new AtomicLong();
private final AtomicLong _persistentMessageEnqueueSize = new AtomicLong();
private final AtomicLong _persistentMessageDequeueSize = new AtomicLong();
@@ -130,6 +129,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private final AtomicLong _byteTxnDequeues = new AtomicLong(0);
private final AtomicLong _unackedMsgCount = new AtomicLong(0);
private final AtomicLong _unackedMsgCountHigh = new AtomicLong(0);
+ private final AtomicLong _unackedMsgBytes = new AtomicLong();
private final AtomicInteger _bindingCountHigh = new AtomicInteger();
@@ -173,7 +173,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private LogSubject _logSubject;
private LogActor _logActor;
- private AMQQueueMBean _managedObject;
private static final String SUB_FLUSH_RUNNER = "SUB_FLUSH_RUNNER";
private boolean _nolocal;
@@ -191,6 +190,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
private int _maximumDeliveryCount = ApplicationRegistry.getInstance().getConfiguration().getMaxDeliveryCount();
private final MessageGroupManager _messageGroupManager;
+ private final Collection<SubscriptionRegistrationListener> _subscriptionListeners =
+ new ArrayList<SubscriptionRegistrationListener>();
+
+ private AMQQueue.NotificationListener _notificationListener;
+ private final long[] _lastNotificationTimes = new long[NotificationCheck.values().length];
+
protected SimpleAMQQueue(UUID id, AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, Map<String,Object> arguments)
{
this(id, name, durable, owner, autoDelete, exclusive,virtualHost, new SimpleQueueEntryList.Factory(), arguments);
@@ -227,14 +232,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
_name = name;
- _resourceName = String.valueOf(name);
_durable = durable;
_owner = owner;
_autoDelete = autoDelete;
_exclusive = exclusive;
_virtualHost = virtualHost;
_entries = entryListFactory.createQueueEntryList(this);
- _arguments = arguments;
+ _arguments = arguments == null ? new HashMap<String, Object>() : new HashMap<String, Object>(arguments);
_id = id;
@@ -255,16 +259,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
getConfigStore().addConfiguredObject(this);
- try
- {
- _managedObject = new AMQQueueMBean(this);
- _managedObject.register();
- }
- catch (JMException e)
- {
- _logger.error("AMQQueue MBean creation has failed ", e);
- }
-
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"))
@@ -339,15 +333,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
return _exclusive;
}
-
- public void setExclusive(boolean exclusive) throws AMQException
+
+ public void setExclusive(boolean exclusive)
{
_exclusive = exclusive;
-
- if(isDurable())
- {
- getVirtualHost().getMessageStore().updateQueue(this);
- }
}
public Exchange getAlternateExchange()
@@ -368,22 +357,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
_alternateExchange = exchange;
}
- public void setAlternateExchange(String exchangeName)
- {
- if(exchangeName == null || exchangeName.equals(""))
- {
- _alternateExchange = null;
- return;
- }
-
- Exchange exchange = getVirtualHost().getExchangeRegistry().getExchange(new AMQShortString(exchangeName));
- if (exchange == null)
- {
- throw new RuntimeException("Exchange '" + exchangeName + "' is not registered with the VirtualHost.");
- }
- setAlternateExchange(exchange);
- }
-
+ /**
+ * Arguments used to create this queue. The caller is assured
+ * that null will never be returned.
+ */
public Map<String, Object> getArguments()
{
return _arguments;
@@ -430,8 +407,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
throw new AMQSecurityException("Permission denied");
}
-
-
+
+
if (hasExclusiveSubscriber())
{
throw new ExistingExclusiveSubscription();
@@ -463,15 +440,24 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
subscription.setNoLocal(_nolocal);
}
+
+ synchronized (_subscriptionListeners)
+ {
+ for(SubscriptionRegistrationListener listener : _subscriptionListeners)
+ {
+ listener.subscriptionRegistered(this, subscription);
+ }
+ }
+
_subscriptionList.add(subscription);
-
+
//Increment consumerCountHigh if necessary. (un)registerSubscription are both
//synchronized methods so we don't need additional synchronization here
if(_counsumerCountHigh.get() < getConsumerCount())
{
_counsumerCountHigh.incrementAndGet();
}
-
+
if (isDeleted())
{
subscription.queueDeleted(this);
@@ -507,6 +493,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
resetSubPointersForGroups(subscription, true);
}
+ synchronized (_subscriptionListeners)
+ {
+ for(SubscriptionRegistrationListener listener : _subscriptionListeners)
+ {
+ listener.subscriptionUnregistered(this, subscription);
+ }
+ }
+
// auto-delete queues must be deleted if there are no remaining subscribers
if (_autoDelete && getDeleteOnNoConsumers() && !subscription.isTransient() && getConsumerCount() == 0 )
@@ -526,6 +520,34 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
+ public Collection<Subscription> getConsumers()
+ {
+ List<Subscription> consumers = new ArrayList<Subscription>();
+ SubscriptionList.SubscriptionNodeIterator iter = _subscriptionList.iterator();
+ while(iter.advance())
+ {
+ consumers.add(iter.getNode().getSubscription());
+ }
+ return consumers;
+
+ }
+
+ public void addSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener)
+ {
+ synchronized (_subscriptionListeners)
+ {
+ _subscriptionListeners.add(listener);
+ }
+ }
+
+ public void removeSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener)
+ {
+ synchronized (_subscriptionListeners)
+ {
+ _subscriptionListeners.remove(listener);
+ }
+ }
+
public void resetSubPointersForGroups(Subscription subscription, boolean clearAssignments)
{
QueueEntry entry = _messageGroupManager.findEarliestAssignedAvailableEntry(subscription);
@@ -576,10 +598,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
break;
}
}
-
+
reconfigure();
}
-
+
private void reconfigure()
{
//Reconfigure the queue for to reflect this new binding.
@@ -604,7 +626,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
public void removeBinding(final Binding binding)
{
_bindings.remove(binding);
-
+
reconfigure();
}
@@ -718,10 +740,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
- if(_managedObject != null)
- {
- _managedObject.checkForNotification(entry.getMessage());
- }
+ checkForNotification(entry.getMessage());
if(action != null)
{
@@ -738,8 +757,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
try
{
- if (!sub.isSuspended()
- && subscriptionReadyAndHasInterest(sub, entry)
+ if (!sub.isSuspended()
+ && subscriptionReadyAndHasInterest(sub, entry)
&& mightAssign(sub, entry)
&& !sub.wouldSuspend(entry))
{
@@ -788,6 +807,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
long size = message.getSize();
getAtomicQueueSize().addAndGet(size);
+ _enqueueCount.incrementAndGet();
_enqueueSize.addAndGet(size);
if(message.isPersistent() && isDurable())
{
@@ -796,19 +816,29 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
+ public long getTotalDequeueCount()
+ {
+ return _dequeueCount.get();
+ }
+
+ public long getTotalEnqueueCount()
+ {
+ return _enqueueCount.get();
+ }
+
private void incrementQueueCount()
{
getAtomicQueueCount().incrementAndGet();
}
-
+
private void incrementTxnEnqueueStats(final ServerMessage message)
{
_msgTxnEnqueues.incrementAndGet();
_byteTxnEnqueues.addAndGet(message.getSize());
}
-
+
private void incrementTxnDequeueStats(QueueEntry entry)
- {
+ {
_msgTxnDequeues.incrementAndGet();
_byteTxnDequeues.addAndGet(entry.getSize());
}
@@ -819,7 +849,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
setLastSeenEntry(sub, entry);
_deliveredMessages.incrementAndGet();
- incrementUnackedMsgCount();
+ incrementUnackedMsgCount(entry);
sub.send(entry, batch);
}
@@ -887,7 +917,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
_deliveredMessages.decrementAndGet();
}
-
+
if(sub != null && sub.isSessionTransactional())
{
incrementTxnDequeueStats(entry);
@@ -940,11 +970,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
}
+
+
public int getConsumerCount()
{
return _subscriptionList.size();
}
-
+
public int getConsumerCountHigh()
{
return _counsumerCountHigh.get();
@@ -1148,7 +1180,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
- public void visit(final Visitor visitor)
+ public void visit(final QueueEntryVisitor visitor)
{
QueueEntryIterator queueListIterator = _entries.iterator();
@@ -1411,7 +1443,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
public long clearQueue() throws AMQException
- {
+ {
return clear(0l);
}
@@ -1422,7 +1454,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
throw new AMQSecurityException("Permission denied: queue " + getName());
}
-
+
QueueEntryIterator queueListIterator = _entries.iterator();
long count = 0;
@@ -1489,7 +1521,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
throw new AMQSecurityException("Permission denied: " + getName());
}
-
+
if (!_deleted.getAndSet(true))
{
@@ -1617,12 +1649,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
txn.commit();
-
- if(_managedObject!=null)
- {
- _managedObject.unregister();
- }
-
for (Task task : _deleteTaskList)
{
task.doTask(this);
@@ -2101,16 +2127,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
}
else
{
- if (_managedObject != null)
+ // There is a chance that the node could be deleted by
+ // the time the check actually occurs. So verify we
+ // can actually get the message to perform the check.
+ ServerMessage msg = node.getMessage();
+ if (msg != null)
{
- // There is a chance that the node could be deleted by
- // the time the check actually occurs. So verify we
- // can actually get the message to perform the check.
- ServerMessage msg = node.getMessage();
- if (msg != null)
- {
- _managedObject.checkForNotification(msg);
- }
+ checkForNotification(msg);
}
}
}
@@ -2235,11 +2258,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return _notificationChecks;
}
- public ManagedObject getManagedObject()
- {
- return _managedObject;
- }
-
private final class QueueEntryListener implements QueueEntry.StateChangeListener
{
@@ -2330,12 +2348,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
return _queueConfiguration;
}
- public String getResourceName()
- {
- return _resourceName;
- }
-
-
public ConfigStore getConfigStore()
{
return getVirtualHost().getConfigStore();
@@ -2355,22 +2367,22 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
return _dequeueSize.get();
}
-
+
public long getByteTxnEnqueues()
{
return _byteTxnEnqueues.get();
}
-
+
public long getByteTxnDequeues()
{
return _byteTxnDequeues.get();
}
-
+
public long getMsgTxnEnqueues()
{
return _msgTxnEnqueues.get();
}
-
+
public long getMsgTxnDequeues()
{
return _msgTxnDequeues.get();
@@ -2407,21 +2419,28 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
{
return _unackedMsgCountHigh.get();
}
-
+
public long getUnackedMessageCount()
{
return _unackedMsgCount.get();
}
-
- public void decrementUnackedMsgCount()
+
+ public long getUnackedMessageBytes()
+ {
+ return _unackedMsgBytes.get();
+ }
+
+ public void decrementUnackedMsgCount(QueueEntry queueEntry)
{
_unackedMsgCount.decrementAndGet();
+ _unackedMsgBytes.addAndGet(-queueEntry.getSize());
}
-
- private void incrementUnackedMsgCount()
+
+ private void incrementUnackedMsgCount(QueueEntry entry)
{
long unackedMsgCount = _unackedMsgCount.incrementAndGet();
-
+ _unackedMsgBytes.addAndGet(entry.getSize());
+
long unackedMsgCountHigh;
while(unackedMsgCount > (unackedMsgCountHigh = _unackedMsgCountHigh.get()))
{
@@ -2447,4 +2466,54 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes
_maximumDeliveryCount = maximumDeliveryCount;
}
+ /**
+ * Checks if there is any notification to send to the listeners
+ */
+ private void checkForNotification(ServerMessage<?> msg) throws AMQException
+ {
+ final Set<NotificationCheck> notificationChecks = getNotificationChecks();
+ final AMQQueue.NotificationListener listener = _notificationListener;
+
+ if(listener != null && !notificationChecks.isEmpty())
+ {
+ final long currentTime = System.currentTimeMillis();
+ final long thresholdTime = currentTime - getMinimumAlertRepeatGap();
+
+ for (NotificationCheck check : notificationChecks)
+ {
+ if (check.isMessageSpecific() || (_lastNotificationTimes[check.ordinal()] < thresholdTime))
+ {
+ if (check.notifyIfNecessary(msg, this, listener))
+ {
+ _lastNotificationTimes[check.ordinal()] = currentTime;
+ }
+ }
+ }
+ }
+ }
+
+ public void setNotificationListener(AMQQueue.NotificationListener listener)
+ {
+ _notificationListener = listener;
+ }
+
+ @Override
+ public void setDescription(String description)
+ {
+ if (description == null)
+ {
+ _arguments.remove(AMQQueueFactory.X_QPID_DESCRIPTION);
+ }
+ else
+ {
+ _arguments.put(AMQQueueFactory.X_QPID_DESCRIPTION, description);
+ }
+ }
+
+ @Override
+ public String getDescription()
+ {
+ return (String) _arguments.get(AMQQueueFactory.X_QPID_DESCRIPTION);
+ }
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
index 80a91be262..10c69b7f97 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
@@ -22,9 +22,9 @@ 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 org.apache.qpid.AMQException;
import org.apache.qpid.common.Closeable;
import org.apache.qpid.common.QpidProperties;
import org.apache.qpid.qmf.QMFService;
@@ -35,18 +35,13 @@ 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.logging.CompositeStartupMessageLogger;
-import org.apache.qpid.server.logging.Log4jMessageLogger;
-import org.apache.qpid.server.logging.LogActor;
-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.messages.BrokerMessages;
import org.apache.qpid.server.logging.messages.VirtualHostMessages;
-import org.apache.qpid.server.management.ManagedObjectRegistry;
-import org.apache.qpid.server.management.NoopManagedObjectRegistry;
+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;
@@ -72,6 +67,7 @@ import java.util.concurrent.atomic.AtomicReference;
*/
public abstract class ApplicationRegistry implements IApplicationRegistry
{
+
private static final Logger _logger = Logger.getLogger(ApplicationRegistry.class);
private static AtomicReference<IApplicationRegistry> _instance = new AtomicReference<IApplicationRegistry>(null);
@@ -81,11 +77,9 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
private final Map<InetSocketAddress, QpidAcceptor> _acceptors =
Collections.synchronizedMap(new HashMap<InetSocketAddress, QpidAcceptor>());
- private ManagedObjectRegistry _managedObjectRegistry;
-
private IAuthenticationManagerRegistry _authenticationManagerRegistry;
- private VirtualHostRegistry _virtualHostRegistry;
+ private final VirtualHostRegistry _virtualHostRegistry = new VirtualHostRegistry(this);
private SecurityManager _securityManager;
@@ -101,30 +95,32 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
private QMFService _qmfService;
- private BrokerConfig _broker;
+ private BrokerConfig _brokerConfig;
+
+ private Broker _broker;
private ConfigStore _configStore;
-
+
private Timer _reportingTimer;
- private boolean _statisticsEnabled = false;
private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
private BundleContext _bundleContext;
+ private final List<PortBindingListener> _portBindingListeners = new ArrayList<PortBindingListener>();
- protected Map<InetSocketAddress, QpidAcceptor> getAcceptors()
- {
- return _acceptors;
- }
+ private int _httpManagementPort = -1;
- protected void setManagedObjectRegistry(ManagedObjectRegistry managedObjectRegistry)
- {
- _managedObjectRegistry = managedObjectRegistry;
- }
+ private LogRecorder _logRecorder;
+
+ private List<IAuthenticationManagerRegistry.RegistryChangeListener> _authManagerChangeListeners =
+ new ArrayList<IAuthenticationManagerRegistry.RegistryChangeListener>();
- protected void setVirtualHostRegistry(VirtualHostRegistry virtualHostRegistry)
+ public Map<InetSocketAddress, QpidAcceptor> getAcceptors()
{
- _virtualHostRegistry = virtualHostRegistry;
+ synchronized (_acceptors)
+ {
+ return new HashMap<InetSocketAddress, QpidAcceptor>(_acceptors);
+ }
}
protected void setSecurityManager(SecurityManager securityManager)
@@ -191,11 +187,11 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
store.setRoot(new SystemConfigImpl(store));
instance.setConfigStore(store);
- BrokerConfig broker = new BrokerConfigAdapter(instance);
+ final BrokerConfig brokerConfig = new BrokerConfigAdapter(instance);
- SystemConfig system = store.getRoot();
- system.addBroker(broker);
- instance.setBroker(broker);
+ final SystemConfig system = store.getRoot();
+ system.addBroker(brokerConfig);
+ instance.setBrokerConfig(brokerConfig);
try
{
@@ -208,7 +204,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
//remove the Broker instance, then re-throw
try
{
- system.removeBroker(broker);
+ system.removeBroker(brokerConfig);
}
catch(Throwable t)
{
@@ -283,18 +279,28 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
public void initialise() throws Exception
{
+ _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);
-
- CurrentActor.set(new BrokerActor(_startupMessageLogger));
+
+ BrokerActor actor = new BrokerActor(_startupMessageLogger);
+ CurrentActor.setDefault(actor);
+ CurrentActor.set(actor);
try
{
- initialiseManagedObjectRegistry();
+ initialiseStatistics();
+
+ if(_configuration.getHTTPManagementEnabled())
+ {
+ _httpManagementPort = _configuration.getHTTPManagementPort();
+ }
+
+ _broker = new BrokerAdapter(this);
configure();
@@ -302,13 +308,23 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
logStartupMessages(CurrentActor.get());
- _virtualHostRegistry = new VirtualHostRegistry(this);
-
_securityManager = new SecurityManager(_configuration, _pluginManager);
_authenticationManagerRegistry = createAuthenticationManagerRegistry(_configuration, _pluginManager);
- _managedObjectRegistry.start();
+ if(!_authManagerChangeListeners.isEmpty())
+ {
+ for(IAuthenticationManagerRegistry.RegistryChangeListener listener : _authManagerChangeListeners)
+ {
+
+ _authenticationManagerRegistry.addRegistryChangeListener(listener);
+ for(AuthenticationManager authMgr : _authenticationManagerRegistry.getAvailableAuthenticationManagers().values())
+ {
+ listener.authenticationManagerRegistered(authMgr);
+ }
+ }
+ _authManagerChangeListeners.clear();
+ }
}
finally
{
@@ -319,7 +335,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
try
{
initialiseVirtualHosts();
- initialiseStatistics();
initialiseStatisticsReporting();
}
finally
@@ -344,23 +359,18 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
getVirtualHostRegistry().setDefaultVirtualHostName(_configuration.getDefaultVirtualHost());
}
- protected void initialiseManagedObjectRegistry() throws AMQException
- {
- _managedObjectRegistry = new NoopManagedObjectRegistry();
- }
-
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();
-
+
/* add a timer task to report statistics if generation is enabled for broker or virtualhosts */
if (report > 0L && (broker || virtualhost))
{
_reportingTimer = new Timer("Statistics-Reporting", true);
-
+
_reportingTimer.scheduleAtFixedRate(new StatisticsReportingTask(broker, virtualhost, reset),
@@ -495,9 +505,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
close(_pluginManager);
- close(_managedObjectRegistry);
-
- BrokerConfig broker = getBroker();
+ BrokerConfig broker = getBrokerConfig();
if(broker != null)
{
broker.getSystem().removeBroker(broker);
@@ -513,12 +521,14 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
private void unbind()
{
+ List<QpidAcceptor> removedAcceptors = new ArrayList<QpidAcceptor>();
synchronized (_acceptors)
{
for (InetSocketAddress bindAddress : _acceptors.keySet())
{
QpidAcceptor acceptor = _acceptors.get(bindAddress);
+ removedAcceptors.add(acceptor);
try
{
acceptor.getNetworkTransport().close();
@@ -531,6 +541,16 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
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()
@@ -544,6 +564,13 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
_acceptors.put(bindAddress, acceptor);
}
+ synchronized (_portBindingListeners)
+ {
+ for(PortBindingListener listener : _portBindingListeners)
+ {
+ listener.bound(acceptor, bindAddress);
+ }
+ }
}
public VirtualHostRegistry getVirtualHostRegistry()
@@ -556,15 +583,16 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
return _securityManager;
}
- public ManagedObjectRegistry getManagedObjectRegistry()
+ @Override
+ public AuthenticationManager getAuthenticationManager(SocketAddress address)
{
- return _managedObjectRegistry;
+ return _authenticationManagerRegistry.getAuthenticationManager(address);
}
@Override
- public AuthenticationManager getAuthenticationManager(SocketAddress address)
+ public IAuthenticationManagerRegistry getAuthenticationManagerRegistry()
{
- return _authenticationManagerRegistry.getAuthenticationManager(address);
+ return _authenticationManagerRegistry;
}
public PluginManager getPluginManager()
@@ -581,7 +609,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
return _rootMessageLogger;
}
-
+
public RootMessageLogger getCompositeStartupMessageLogger()
{
return _startupMessageLogger;
@@ -597,69 +625,63 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
return _qmfService;
}
- public BrokerConfig getBroker()
+ public BrokerConfig getBrokerConfig()
{
- return _broker;
+ return _brokerConfig;
}
- public void setBroker(final BrokerConfig broker)
+ public void setBrokerConfig(final BrokerConfig broker)
{
- _broker = broker;
+ _brokerConfig = broker;
}
public VirtualHost createVirtualHost(final VirtualHostConfiguration vhostConfig) throws Exception
{
VirtualHostImpl virtualHost = new VirtualHostImpl(this, vhostConfig);
_virtualHostRegistry.registerVirtualHost(virtualHost);
- getBroker().addVirtualHost(virtualHost);
+ getBrokerConfig().addVirtualHost(virtualHost);
return virtualHost;
}
-
+
public void registerMessageDelivered(long messageSize)
{
- if (isStatisticsEnabled())
- {
- _messagesDelivered.registerEvent(1L);
- _dataDelivered.registerEvent(messageSize);
- }
+ _messagesDelivered.registerEvent(1L);
+ _dataDelivered.registerEvent(messageSize);
}
-
+
public void registerMessageReceived(long messageSize, long timestamp)
{
- if (isStatisticsEnabled())
- {
- _messagesReceived.registerEvent(1L, timestamp);
- _dataReceived.registerEvent(messageSize, timestamp);
- }
+ _messagesReceived.registerEvent(1L, timestamp);
+ _dataReceived.registerEvent(messageSize, timestamp);
}
-
+
public StatisticsCounter getMessageReceiptStatistics()
{
return _messagesReceived;
}
-
+
public StatisticsCounter getDataReceiptStatistics()
{
return _dataReceived;
}
-
+
public StatisticsCounter getMessageDeliveryStatistics()
{
return _messagesDelivered;
}
-
+
public StatisticsCounter getDataDeliveryStatistics()
{
return _dataDelivered;
}
-
+
public void resetStatistics()
{
_messagesDelivered.reset();
_dataDelivered.reset();
_messagesReceived.reset();
_dataReceived.reset();
-
+
for (VirtualHost vhost : _virtualHostRegistry.getVirtualHosts())
{
vhost.resetStatistics();
@@ -668,25 +690,12 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
public void initialiseStatistics()
{
- setStatisticsEnabled(!StatisticsCounter.DISABLE_STATISTICS &&
- getConfiguration().isStatisticsGenerationBrokerEnabled());
-
_messagesDelivered = new StatisticsCounter("messages-delivered");
_dataDelivered = new StatisticsCounter("bytes-delivered");
_messagesReceived = new StatisticsCounter("messages-received");
_dataReceived = new StatisticsCounter("bytes-received");
}
- public boolean isStatisticsEnabled()
- {
- return _statisticsEnabled;
- }
-
- public void setStatisticsEnabled(boolean enabled)
- {
- _statisticsEnabled = enabled;
- }
-
private void logStartupMessages(LogActor logActor)
{
logActor.message(BrokerMessages.STARTUP(QpidProperties.getReleaseVersion(), QpidProperties.getBuildVersion()));
@@ -700,4 +709,48 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
logActor.message(BrokerMessages.MAX_MEMORY(Runtime.getRuntime().maxMemory()));
}
+ 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;
+ }
+
+ 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/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
index b28e3d6c89..774d0338ef 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
@@ -25,8 +25,6 @@ import org.osgi.framework.BundleContext;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.management.JMXManagedObjectRegistry;
-import org.apache.qpid.server.management.NoopManagedObjectRegistry;
import java.io.File;
@@ -41,18 +39,4 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
{
super(new ServerConfiguration(configurationURL), bundleContext);
}
-
- @Override
- protected void initialiseManagedObjectRegistry() throws AMQException
- {
- if (getConfiguration().getManagementEnabled())
- {
- setManagedObjectRegistry(new JMXManagedObjectRegistry());
- }
- else
- {
- setManagedObjectRegistry(new NoopManagedObjectRegistry());
- }
- }
-
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
index 35e7fe3f61..2baf7ed5ee 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
@@ -27,10 +27,11 @@ 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.management.ManagedObjectRegistry;
+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;
@@ -38,6 +39,7 @@ 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
@@ -61,8 +63,6 @@ public interface IApplicationRegistry extends StatisticsGatherer
*/
ServerConfiguration getConfiguration();
- ManagedObjectRegistry getManagedObjectRegistry();
-
/**
* Get the AuthenticationManager for the given socket address
*
@@ -74,6 +74,8 @@ public interface IApplicationRegistry extends StatisticsGatherer
*/
AuthenticationManager getAuthenticationManager(SocketAddress address);
+ IAuthenticationManagerRegistry getAuthenticationManagerRegistry();
+
VirtualHostRegistry getVirtualHostRegistry();
SecurityManager getSecurityManager();
@@ -95,15 +97,35 @@ public interface IApplicationRegistry extends StatisticsGatherer
QMFService getQMFService();
- void setBroker(BrokerConfig broker);
+ void setBrokerConfig(BrokerConfig broker);
+
+ BrokerConfig getBrokerConfig();
- BrokerConfig getBroker();
+ Broker getBroker();
VirtualHost createVirtualHost(VirtualHostConfiguration vhostConfig) throws Exception;
ConfigStore getConfigStore();
void setConfigStore(ConfigStore store);
-
+
void initialiseStatisticsReporting();
+
+ Map<InetSocketAddress, QpidAcceptor> getAcceptors();
+
+ void addPortBindingListener(PortBindingListener listener);
+
+ boolean useHTTPManagement();
+
+ int getHTTPManagementPort();
+
+ void addRegistryChangeListener(IAuthenticationManagerRegistry.RegistryChangeListener registryChangeListener);
+
+ public interface PortBindingListener
+ {
+ public void bound(QpidAcceptor acceptor, InetSocketAddress bindAddress);
+ public void unbound(QpidAcceptor acceptor);
+
+ }
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java
index 7088fae50c..cac60a5283 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java
@@ -198,7 +198,7 @@ public abstract class AbstractPasswordFilePrincipalDatabase<U extends PasswordPr
try
{
_userUpdate.lock();
- _userMap.clear();
+ final Map<String, U> newUserMap = new HashMap<String, U>();
BufferedReader reader = null;
try
@@ -216,7 +216,7 @@ public abstract class AbstractPasswordFilePrincipalDatabase<U extends PasswordPr
U user = createUserFromFileData(result);
getLogger().info("Created user:" + user);
- _userMap.put(user.getName(), user);
+ newUserMap.put(user.getName(), user);
}
}
finally
@@ -226,6 +226,9 @@ public abstract class AbstractPasswordFilePrincipalDatabase<U extends PasswordPr
reader.close();
}
}
+
+ _userMap.clear();
+ _userMap.putAll(newUserMap);
}
finally
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java
index 0eb3963865..5676c43754 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java
@@ -47,7 +47,7 @@ public class AnonymousAuthenticationManager implements AuthenticationManager
private static final Principal ANONYMOUS_PRINCIPAL = new UsernamePrincipal("ANONYMOUS");
- private static final Subject ANONYMOUS_SUBJECT = new Subject();
+ public static final Subject ANONYMOUS_SUBJECT = new Subject();
static
{
ANONYMOUS_SUBJECT.getPrincipals().add(ANONYMOUS_PRINCIPAL);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java
index 3a1ca4f19d..89a4d8ae66 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java
@@ -21,9 +21,12 @@ 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;
@@ -49,6 +52,8 @@ public class AuthenticationManagerRegistry implements Closeable, IAuthentication
private final Map<String,AuthenticationManager> _classToAuthManagerMap = new HashMap<String,AuthenticationManager>();
private final AuthenticationManager _defaultAuthenticationManager;
private final Map<Integer,AuthenticationManager> _portToAuthenticationManagerMap;
+ private final List<RegistryChangeListener> _listeners =
+ Collections.synchronizedList(new ArrayList<RegistryChangeListener>());
public AuthenticationManagerRegistry(ServerConfiguration serverConfiguration, PluginManager _pluginManager)
throws ConfigurationException
@@ -114,9 +119,8 @@ public class AuthenticationManagerRegistry implements Closeable, IAuthentication
final SecurityConfiguration securityConfiguration)
throws ConfigurationException
{
- for (final Iterator<AuthenticationManagerPluginFactory<? extends Plugin>> iterator = factories.iterator(); iterator.hasNext();)
+ for(AuthenticationManagerPluginFactory<? extends Plugin> factory : factories)
{
- final AuthenticationManagerPluginFactory<? extends Plugin> factory = (AuthenticationManagerPluginFactory<? extends Plugin>) iterator.next();
final AuthenticationManager tmp = factory.newInstance(securityConfiguration);
if (tmp != null)
{
@@ -127,6 +131,11 @@ public class AuthenticationManagerRegistry implements Closeable, IAuthentication
+ " Remove configuration for one of the authentication managers.");
}
_classToAuthManagerMap.put(tmp.getClass().getSimpleName(),tmp);
+
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.authenticationManagerRegistered(tmp);
+ }
}
}
}
@@ -179,5 +188,16 @@ public class AuthenticationManagerRegistry implements Closeable, IAuthentication
return portToAuthenticationManagerMap;
}
+ @Override
+ public Map<String, AuthenticationManager> getAvailableAuthenticationManagers()
+ {
+ return Collections.unmodifiableMap(new HashMap<String, AuthenticationManager>(_classToAuthManagerMap));
+ }
+
+ @Override
+ public void addRegistryChangeListener(RegistryChangeListener listener)
+ {
+ _listeners.add(listener);
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java
index bfb49b8ed6..485ca2e1e9 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java
@@ -21,7 +21,9 @@ 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.
@@ -43,4 +45,15 @@ public interface IAuthenticationManagerRegistry extends Closeable
* @return authentication manager.
*/
public AuthenticationManager getAuthenticationManager(SocketAddress address);
+
+ Map<String, AuthenticationManager> 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/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
index 24b365d34c..e6498919a1 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
@@ -32,7 +32,6 @@ 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.management.AMQUserManagementMBean;
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;
@@ -98,8 +97,6 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
private PrincipalDatabase _principalDatabase = null;
- private AMQUserManagementMBean _mbean = null;
-
public static final AuthenticationManagerPluginFactory<PrincipalDatabaseAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<PrincipalDatabaseAuthenticationManager>()
{
public PrincipalDatabaseAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException
@@ -211,8 +208,6 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
{
_logger.warn("No additional SASL providers registered.");
}
-
- registerManagement();
}
private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, PrincipalDatabase database)
@@ -332,8 +327,6 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
{
_mechanisms = null;
Security.removeProvider(PROVIDER_NAME);
-
- unregisterManagement();
}
private PrincipalDatabase createPrincipalDatabaseImpl(final String pdClazz) throws ConfigurationException
@@ -407,6 +400,11 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
}
}
+ public PrincipalDatabase getPrincipalDatabase()
+ {
+ return _principalDatabase;
+ }
+
private String generateSetterName(String argName) throws ConfigurationException
{
if ((argName == null) || (argName.length() == 0))
@@ -427,41 +425,4 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
{
_principalDatabase = principalDatabase;
}
-
- protected void registerManagement()
- {
- try
- {
- _logger.info("Registering UserManagementMBean");
-
- _mbean = new AMQUserManagementMBean();
- _mbean.setPrincipalDatabase(_principalDatabase);
- _mbean.register();
- }
- catch (Exception e)
- {
- _logger.warn("User management disabled as unable to create MBean:", e);
- _mbean = null;
- }
- }
-
- protected void unregisterManagement()
- {
- try
- {
- if (_mbean != null)
- {
- _logger.info("Unregistering UserManagementMBean");
- _mbean.unregister();
- }
- }
- catch (Exception e)
- {
- _logger.warn("Failed to unregister User management MBean:", e);
- }
- finally
- {
- _mbean = null;
- }
- }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
index e27fd99f90..2e21cfbb07 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
@@ -20,6 +20,9 @@
*/
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.security.auth.AuthenticationResult.AuthenticationStatus;
import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
@@ -37,11 +40,13 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator
static final String INVALID_CREDENTIALS = "Invalid user details supplied";
static final String CREDENTIALS_REQUIRED = "User details are required. " +
"Please ensure you are using an up to date management console to connect.";
-
+
private AuthenticationManager _authenticationManager = null;
+ private SocketAddress _socketAddress;
- public RMIPasswordAuthenticator()
+ public RMIPasswordAuthenticator(SocketAddress socketAddress)
{
+ _socketAddress = socketAddress;
}
public void setAuthenticationManager(final AuthenticationManager authenticationManager)
@@ -79,11 +84,25 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator
{
throw new SecurityException(SHOULD_BE_NON_NULL);
}
-
+
// Verify that an AuthenticationManager has been set.
if (_authenticationManager == null)
{
- throw new SecurityException(UNABLE_TO_LOOKUP);
+ 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);
+ }
}
final AuthenticationResult result = _authenticationManager.authenticate(username, password);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java
index 2bd17cfa2f..f382f90010 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java
@@ -33,8 +33,7 @@ public class StatisticsCounter
private static final Logger _log = LoggerFactory.getLogger(StatisticsCounter.class);
public static final long DEFAULT_SAMPLE_PERIOD = Long.getLong("qpid.statistics.samplePeriod", 2000L); // 2s
- public static final boolean DISABLE_STATISTICS = Boolean.getBoolean("qpid.statistics.disable");
-
+
private static final String COUNTER = "counter";
private static final AtomicLong _counterIds = new AtomicLong(0L);
@@ -78,11 +77,6 @@ public class StatisticsCounter
public void registerEvent(long value, long timestamp)
{
- if (DISABLE_STATISTICS)
- {
- return;
- }
-
long thisSample = (timestamp / _period);
synchronized (this)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java
index 36fec4025a..37d87bb628 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java
@@ -103,16 +103,4 @@ public interface StatisticsGatherer
* Reset the counters for this, and any child {@link StatisticsGatherer}s.
*/
void resetStatistics();
-
- /**
- * Check if this object has statistics generation enabled.
- *
- * @return true if statistics generation is enabled
- */
- boolean isStatisticsEnabled();
-
- /**
- * Enable or disable statistics generation for this object.
- */
- void setStatisticsEnabled(boolean enabled);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
index 1307b1dbd4..f1053f60ad 100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
@@ -32,7 +32,7 @@ public interface ConfigurationRecoveryHandler
public static interface QueueRecoveryHandler
{
- void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments);
+ void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments, UUID alternateExchangeId);
ExchangeRecoveryHandler completeQueueRecovery();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java
index 1a67fdf540..7356e1ae83 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java
@@ -40,12 +40,7 @@ import org.apache.qpid.server.util.MapJsonSerializer;
public class ConfiguredObjectHelper
{
- /**
- * Name of queue attribute to store queue creation arguments.
- * <p>
- * This attribute is not defined yet on Queue configured object interface.
- */
- private static final String QUEUE_ARGUMENTS = "ARGUMENTS";
+
private MapJsonSerializer _serializer = new MapJsonSerializer();
@@ -57,14 +52,15 @@ public class ConfiguredObjectHelper
String queueName = (String) attributeMap.get(Queue.NAME);
String owner = (String) attributeMap.get(Queue.OWNER);
boolean exclusive = (Boolean) attributeMap.get(Queue.EXCLUSIVE);
+ UUID alternateExchangeId = attributeMap.get(Queue.ALTERNATE_EXCHANGE) == null ? null : UUID.fromString((String)attributeMap.get(Queue.ALTERNATE_EXCHANGE));
@SuppressWarnings("unchecked")
- Map<String, Object> queueArgumentsMap = (Map<String, Object>) attributeMap.get(QUEUE_ARGUMENTS);
+ Map<String, Object> queueArgumentsMap = (Map<String, Object>) attributeMap.get(Queue.ARGUMENTS);
FieldTable arguments = null;
if (queueArgumentsMap != null)
{
arguments = FieldTable.convertToFieldTable(queueArgumentsMap);
}
- qrh.queue(configuredObject.getId(), queueName, owner, exclusive, arguments);
+ qrh.queue(configuredObject.getId(), queueName, owner, exclusive, arguments, alternateExchangeId);
}
}
@@ -73,6 +69,24 @@ public class ConfiguredObjectHelper
Map<String, Object> attributesMap = _serializer.deserialize(queueRecord.getAttributes());
attributesMap.put(Queue.NAME, queue.getName());
attributesMap.put(Queue.EXCLUSIVE, queue.isExclusive());
+ if (queue.getAlternateExchange() != null)
+ {
+ attributesMap.put(Queue.ALTERNATE_EXCHANGE, queue.getAlternateExchange().getId());
+ }
+ else
+ {
+ attributesMap.remove(Queue.ALTERNATE_EXCHANGE);
+ }
+ if (attributesMap.containsKey(Queue.ARGUMENTS))
+ {
+ // We wouldn't need this if createQueueConfiguredObject took only AMQQueue
+ Map<String, Object> currentArgs = (Map<String, Object>) attributesMap.get(Queue.ARGUMENTS);
+ currentArgs.putAll(queue.getArguments());
+ }
+ else
+ {
+ attributesMap.put(Queue.ARGUMENTS, queue.getArguments());
+ }
String newJson = _serializer.serialize(attributesMap);
ConfiguredObjectRecord newQueueRecord = new ConfiguredObjectRecord(queue.getId(), queueRecord.getType(), newJson);
return newQueueRecord;
@@ -84,9 +98,15 @@ public class ConfiguredObjectHelper
attributesMap.put(Queue.NAME, queue.getName());
attributesMap.put(Queue.OWNER, AMQShortString.toString(queue.getOwner()));
attributesMap.put(Queue.EXCLUSIVE, queue.isExclusive());
+ if (queue.getAlternateExchange() != null)
+ {
+ attributesMap.put(Queue.ALTERNATE_EXCHANGE, queue.getAlternateExchange().getId());
+ }
+ // TODO KW i think the arguments could come from the queue itself removing the need for the parameter arguments.
+ // It would also do away with the need for the if/then/else within updateQueueConfiguredObject
if (arguments != null)
{
- attributesMap.put(QUEUE_ARGUMENTS, FieldTable.convertToMap(arguments));
+ attributesMap.put(Queue.ARGUMENTS, FieldTable.convertToMap(arguments));
}
String json = _serializer.serialize(attributesMap);
ConfiguredObjectRecord configuredObject = new ConfiguredObjectRecord(queue.getId(), Queue.class.getName(), json);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
index 7b98b30860..262d7d0213 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
@@ -134,4 +134,10 @@ public class MemoryMessageStore extends NullMessageStore
{
_eventManager.addEventListener(eventListener, events);
}
+
+ @Override
+ public String getStoreType()
+ {
+ return "Memory";
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
index cf08ee00ff..0acaf164d9 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
@@ -67,4 +67,6 @@ public interface MessageStore extends DurableConfigurationStore
void addEventListener(EventListener eventListener, Event... events);
String getStoreLocation();
+
+ String getStoreType();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
index 34c7d2d933..be08e309e6 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
@@ -28,7 +28,7 @@ import org.apache.qpid.server.federation.Bridge;
import org.apache.qpid.server.federation.BrokerLink;
import org.apache.qpid.server.queue.AMQQueue;
-public class NullMessageStore implements MessageStore
+public abstract class NullMessageStore implements MessageStore
{
@Override
public void configureConfigStore(String name,
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java
index c065eb263b..ab374b4917 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java
@@ -232,6 +232,8 @@ public class DerbyMessageStore implements MessageStore
private static final String DERBY_SINGLE_DB_SHUTDOWN_CODE = "08006";
+ private static final String DERBY_STORE_TYPE = "DERBY";
+
private final StateManager _stateManager;
private final EventManager _eventManager = new EventManager();
@@ -2651,4 +2653,11 @@ public class DerbyMessageStore implements MessageStore
{
return _persistentSizeHighThreshold;
}
+
+ @Override
+ public String getStoreType()
+ {
+ return DERBY_STORE_TYPE;
+ }
+
} \ No newline at end of file
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java
index 6b2dff7165..efedad1181 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java
@@ -20,10 +20,10 @@
*/
package org.apache.qpid.server.subscription;
+import org.apache.qpid.server.queue.QueueEntryVisitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
import java.util.Iterator;
@@ -102,7 +102,7 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana
return visitor.getEntry();
}
- private class EntryFinder implements AMQQueue.Visitor
+ private class EntryFinder implements QueueEntryVisitor
{
private QueueEntry _entry;
private Subscription _sub;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java
index 62e94f6f2e..f38e23b342 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java
@@ -20,12 +20,12 @@
*/
package org.apache.qpid.server.subscription;
+import org.apache.qpid.server.queue.QueueEntryVisitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.qpid.server.message.AMQMessageHeader;
import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
import java.util.HashMap;
@@ -176,7 +176,7 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager
return visitor.getEntry();
}
- private class EntryFinder implements AMQQueue.Visitor
+ private class EntryFinder implements QueueEntryVisitor
{
private QueueEntry _entry;
private Subscription _sub;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java
index cf2754862d..8f3822be6c 100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java
@@ -45,7 +45,7 @@ class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDi
final Subscription_0_10 subscription = getSubscription();
if(subscription != null && _entry.isAcquiredBy(_sub))
{
- subscription.getSession().acknowledge(subscription, _entry);
+ subscription.getSessionModel().acknowledge(subscription, _entry);
}
else
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java
index 1e37675c98..826082cc65 100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java
@@ -72,6 +72,10 @@ class ImplicitAcceptDispositionChangeListener implements ServerSession.MessageDi
public boolean acquire()
{
boolean acquired = _entry.acquire(getSubscription());
+ if(acquired)
+ {
+ getSubscription().recordUnacknowledged(_entry);
+ }
return acquired;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
index 66825caa24..8911754a66 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.subscription;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
@@ -32,6 +33,14 @@ public interface Subscription
boolean isTransient();
+ long getBytesOut();
+
+ long getMessagesOut();
+
+ long getUnacknowledgedBytes();
+
+ long getUnacknowledgedMessages();
+
public static enum State
{
ACTIVE,
@@ -45,6 +54,7 @@ public interface Subscription
}
AMQQueue getQueue();
+ AMQSessionModel getSessionModel();
QueueEntry.SubscriptionAcquiredState getOwningState();
QueueEntry.SubscriptionAssignedState getAssignedState();
@@ -108,4 +118,6 @@ public interface Subscription
boolean isSessionTransactional();
void queueEmpty() throws AMQException;
+
+ String getConsumerName();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
index 1f25c215cc..baf5d09c95 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
@@ -44,6 +44,7 @@ import org.apache.qpid.server.logging.subjects.SubscriptionLogSubject;
import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
@@ -92,8 +93,13 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
private LogActor _logActor;
private UUID _id;
private final AtomicLong _deliveredCount = new AtomicLong(0);
- private long _createTime = System.currentTimeMillis();
+ private final AtomicLong _deliveredBytes = new AtomicLong(0);
+
+ private final AtomicLong _unacknowledgedCount = new AtomicLong(0);
+ private final AtomicLong _unacknowledgedBytes = new AtomicLong(0);
+ private long _createTime = System.currentTimeMillis();
+
static final class BrowserSubscription extends SubscriptionImpl
{
@@ -276,22 +282,13 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
public void send(QueueEntry entry, boolean batch) throws AMQException
{
- // if we do not need to wait for client acknowledgements
- // we can decrement the reference count immediately.
-
- // By doing this _before_ the send we ensure that it
- // doesn't get sent if it can't be dequeued, preventing
- // duplicate delivery on recovery.
-
- // The send may of course still fail, in which case, as
- // the message is unacked, it will be lost.
-
+
synchronized (getChannel())
{
getChannel().getProtocolSession().setDeferFlush(batch);
long deliveryTag = getChannel().getNextDeliveryTag();
-
+ addUnacknowledgedMessage(entry);
recordMessageDelivery(entry, deliveryTag);
sendToClient(entry, deliveryTag);
@@ -371,6 +368,11 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
}
+ public AMQSessionModel getSessionModel()
+ {
+ return _channel;
+ }
+
public ConfigStore getConfigStore()
{
return getQueue().getConfigStore();
@@ -599,6 +601,11 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
return _consumerTag;
}
+ public String getConsumerName()
+ {
+ return _consumerTag == null ? null : _consumerTag.asString();
+ }
+
public long getSubscriptionID()
{
return _subscriptionID;
@@ -687,6 +694,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
{
_deliveryMethod.deliverToClient(this,entry,deliveryTag);
_deliveredCount.incrementAndGet();
+ _deliveredBytes.addAndGet(entry.getSize());
}
@@ -832,4 +840,44 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
_channel.getProtocolSession().flushBatched();
}
+
+ public long getBytesOut()
+ {
+ return _deliveredBytes.longValue();
+ }
+
+ public long getMessagesOut()
+ {
+ return _deliveredCount.longValue();
+ }
+
+
+ protected void addUnacknowledgedMessage(QueueEntry entry)
+ {
+ final long size = entry.getSize();
+ _unacknowledgedBytes.addAndGet(size);
+ _unacknowledgedCount.incrementAndGet();
+ entry.addStateChangeListener(new QueueEntry.StateChangeListener()
+ {
+ public void stateChanged(QueueEntry entry, QueueEntry.State oldState, QueueEntry.State newState)
+ {
+ if(oldState.equals(QueueEntry.State.ACQUIRED) && !newState.equals(QueueEntry.State.ACQUIRED))
+ {
+ _unacknowledgedBytes.addAndGet(-size);
+ _unacknowledgedCount.decrementAndGet();
+ entry.removeStateChangeListener(this);
+ }
+ }
+ });
+ }
+
+ public long getUnacknowledgedBytes()
+ {
+ return _unacknowledgedBytes.longValue();
+ }
+
+ public long getUnacknowledgedMessages()
+ {
+ return _unacknowledgedCount.longValue();
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
index 76d975a789..db378f2bf3 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
@@ -130,6 +130,10 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
private String _trace;
private final long _createTime = System.currentTimeMillis();
private final AtomicLong _deliveredCount = new AtomicLong(0);
+ private final AtomicLong _deliveredBytes = new AtomicLong(0);
+ private final AtomicLong _unacknowledgedCount = new AtomicLong(0);
+ private final AtomicLong _unacknowledgedBytes = new AtomicLong(0);
+
private final Map<String, Object> _arguments;
private int _deferredMessageCredit;
private long _deferredSizeCredit;
@@ -185,7 +189,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
}
_queue = queue;
- Map<String, Object> arguments = queue.getArguments() == null ? Collections.EMPTY_MAP : queue.getArguments();
+ Map<String, Object> arguments = queue.getArguments();
_traceExclude = (String) arguments.get("qpid.trace.exclude");
_trace = (String) arguments.get("qpid.trace.id");
_id = getConfigStore().createId();
@@ -199,9 +203,13 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
CurrentActor.get().message(this, SubscriptionMessages.CREATE(filterLogString, queue.isDurable() && exclusive,
filterLogString.length() > 0));
}
-
}
+ public String getConsumerName()
+ {
+ return _destination;
+ }
+
public boolean isSuspended()
{
return !isActive() || _deleted.get() || _session.isClosing(); // TODO check for Session suspension
@@ -620,10 +628,15 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
_session.sendMessage(xfr, _postIdSettingAction);
entry.incrementDeliveryCount();
_deliveredCount.incrementAndGet();
+ _deliveredBytes.addAndGet(entry.getSize());
if(_acceptMode == MessageAcceptMode.NONE && _acquireMode == MessageAcquireMode.PRE_ACQUIRED)
{
forceDequeue(entry, false);
}
+ else if(_acquireMode == MessageAcquireMode.PRE_ACQUIRED)
+ {
+ recordUnacknowledged(entry);
+ }
}
else
{
@@ -632,6 +645,12 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
}
}
+ void recordUnacknowledged(QueueEntry entry)
+ {
+ _unacknowledgedCount.incrementAndGet();
+ _unacknowledgedBytes.addAndGet(entry.getSize());
+ }
+
private void deferredAddCredit(final int deferredMessageCredit, final long deferredSizeCredit)
{
_deferredMessageCredit += deferredMessageCredit;
@@ -653,7 +672,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
private void forceDequeue(final QueueEntry entry, final boolean restoreCredit)
{
- AutoCommitTransaction dequeueTxn = new AutoCommitTransaction(getQueue().getVirtualHost().getMessageStore());
+ AutoCommitTransaction dequeueTxn = new AutoCommitTransaction(getQueue().getVirtualHost().getMessageStore());
dequeueTxn.dequeue(entry.getQueue(), entry.getMessage(),
new ServerTransaction.Action()
{
@@ -690,7 +709,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
entry.setRedelivered();
}
- if (getSession().isClosing() || !setRedelivered)
+ if (getSessionModel().isClosing() || !setRedelivered)
{
entry.decrementDeliveryCount();
}
@@ -918,6 +937,8 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
// TODO Fix Store Context / cleanup
if(entry.isAcquiredBy(this))
{
+ _unacknowledgedBytes.addAndGet(-entry.getSize());
+ _unacknowledgedCount.decrementAndGet();
entry.discard();
}
}
@@ -944,7 +965,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
return false;
}
- ServerSession getSession()
+ public ServerSession getSessionModel()
{
return _session;
}
@@ -952,7 +973,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
public SessionConfig getSessionConfig()
{
- return getSession();
+ return getSessionModel();
}
public boolean isBrowsing()
@@ -1073,4 +1094,24 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
{
_session.getConnection().flush();
}
+
+ public long getBytesOut()
+ {
+ return _deliveredBytes.longValue();
+ }
+
+ public long getMessagesOut()
+ {
+ return _deliveredCount.longValue();
+ }
+
+ public long getUnacknowledgedBytes()
+ {
+ return _unacknowledgedBytes.longValue();
+ }
+
+ public long getUnacknowledgedMessages()
+ {
+ return _unacknowledgedCount.longValue();
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java
index 637ea7dffc..7c4188bfcd 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java
@@ -20,25 +20,62 @@
*/
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
{
- private NetworkTransport _transport;
- private String _protocol;
- public QpidAcceptor(NetworkTransport transport, String protocol)
+ public enum Transport
{
- _transport = transport;
- _protocol = protocol;
+ 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<AmqpProtocolVersion> _supported;
+
+
+ public QpidAcceptor(NetworkTransport transport, Transport protocol, Set<AmqpProtocolVersion> supported)
+ {
+ _networkTransport = transport;
+ _transport = protocol;
+ _supported = Collections.unmodifiableSet(new HashSet<AmqpProtocolVersion>(supported));
}
public NetworkTransport getNetworkTransport()
{
+ return _networkTransport;
+ }
+
+ public Transport getTransport()
+ {
return _transport;
}
+ public Set<AmqpProtocolVersion> getSupported()
+ {
+ return _supported;
+ }
+
public String toString()
{
- return _protocol;
+ return _transport.toString();
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java
index c9482b9712..2d0e61ec2e 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java
@@ -37,8 +37,6 @@ import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.GenericActor;
import org.apache.qpid.server.logging.messages.ConnectionMessages;
-import org.apache.qpid.server.management.Managable;
-import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.security.AuthorizationHolder;
@@ -56,7 +54,7 @@ import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTIO
import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SOCKET_FORMAT;
import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.USER_FORMAT;
-public class ServerConnection extends Connection implements Managable, AMQConnectionModel, LogSubject, AuthorizationHolder
+public class ServerConnection extends Connection implements AMQConnectionModel, LogSubject, AuthorizationHolder
{
private ConnectionConfig _config;
private Runnable _onOpenTask;
@@ -65,11 +63,9 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
private Subject _authorizedSubject = null;
private Principal _authorizedPrincipal = null;
- private boolean _statisticsEnabled = false;
private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
private final long _connectionId;
private final Object _reference = new Object();
- private ServerConnectionMBean _mBean;
private VirtualHost _virtualHost;
private AtomicLong _lastIoTime = new AtomicLong();
private boolean _blocking;
@@ -118,7 +114,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
{
_virtualHost.getConnectionRegistry().deregisterConnection(this);
}
- unregisterConnectionMbean();
}
if (state == State.CLOSED)
@@ -156,8 +151,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
_virtualHost = virtualHost;
initialiseStatistics();
-
- registerConnectionMbean();
}
public void setConnectionConfig(final ConnectionConfig config)
@@ -273,7 +266,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
public void close(AMQConstant cause, String message) throws AMQException
{
closeSubscriptions();
- unregisterConnectionMbean();
ConnectionCloseCode replyCode = ConnectionCloseCode.NORMAL;
try
{
@@ -338,21 +330,15 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
public void registerMessageDelivered(long messageSize)
{
- if (isStatisticsEnabled())
- {
- _messagesDelivered.registerEvent(1L);
- _dataDelivered.registerEvent(messageSize);
- }
+ _messagesDelivered.registerEvent(1L);
+ _dataDelivered.registerEvent(messageSize);
_virtualHost.registerMessageDelivered(messageSize);
}
public void registerMessageReceived(long messageSize, long timestamp)
{
- if (isStatisticsEnabled())
- {
- _messagesReceived.registerEvent(1L, timestamp);
- _dataReceived.registerEvent(messageSize, timestamp);
- }
+ _messagesReceived.registerEvent(1L, timestamp);
+ _dataReceived.registerEvent(messageSize, timestamp);
_virtualHost.registerMessageReceived(messageSize, timestamp);
}
@@ -386,25 +372,12 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
public void initialiseStatistics()
{
- setStatisticsEnabled(!StatisticsCounter.DISABLE_STATISTICS &&
- _virtualHost.getApplicationRegistry().getConfiguration().isStatisticsGenerationConnectionsEnabled());
-
_messagesDelivered = new StatisticsCounter("messages-delivered-" + getConnectionId());
_dataDelivered = new StatisticsCounter("data-delivered-" + getConnectionId());
_messagesReceived = new StatisticsCounter("messages-received-" + getConnectionId());
_dataReceived = new StatisticsCounter("data-received-" + getConnectionId());
}
- public boolean isStatisticsEnabled()
- {
- return _statisticsEnabled;
- }
-
- public void setStatisticsEnabled(boolean enabled)
- {
- _statisticsEnabled = enabled;
- }
-
/**
* @return authorizedSubject
*/
@@ -448,6 +421,11 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
return !super.hasSessionWithName(name);
}
+ public String getRemoteAddressString()
+ {
+ return getConfig().getAddress();
+ }
+
public String getUserName()
{
return _authorizedPrincipal.getName();
@@ -476,12 +454,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
}
}
-
- public ManagedObject getManagedObject()
- {
- return _mBean;
- }
-
@Override
public void send(ProtocolEvent event)
{
@@ -489,54 +461,29 @@ public class ServerConnection extends Connection implements Managable, AMQConnec
super.send(event);
}
- public AtomicLong getLastIoTime()
+ public long getLastIoTime()
{
- return _lastIoTime;
+ return _lastIoTime.longValue();
}
- void checkForNotification()
- {
- int channelsCount = getSessionModels().size();
- if (_mBean != null && channelsCount >= getConnectionDelegate().getChannelMax())
- {
- _mBean.notifyClients("Channel count (" + channelsCount + ") has reached the threshold value");
- }
- }
-
- private void registerConnectionMbean()
+ public String getClientId()
{
- try
- {
- _mBean = new ServerConnectionMBean(this);
- _mBean.register();
- }
- catch (JMException jme)
- {
- log.error("Unable to register mBean for ServerConnection", jme);
- }
+ return getConnectionDelegate().getClientId();
}
- private void unregisterConnectionMbean()
+ public String getClientVersion()
{
- if (_mBean != null)
- {
- if (log.isDebugEnabled())
- {
- log.debug("Unregistering mBean for ServerConnection" + _mBean);
- }
- _mBean.unregister();
- _mBean = null;
- }
+ return getConnectionDelegate().getClientVersion();
}
- public String getClientId()
+ public String getPrincipalAsString()
{
- return getConnectionDelegate().getClientId();
+ return getAuthorizedPrincipal().getName();
}
- public String getClientVersion()
+ public long getSessionCountLimit()
{
- return getConnectionDelegate().getClientVersion();
+ return getChannelMax();
}
public Principal getPeerPrincipal()
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
index ad59c56878..c13f63b44d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
@@ -61,7 +61,7 @@ public class ServerConnectionDelegate extends ServerDelegate
public ServerConnectionDelegate(IApplicationRegistry appRegistry, String localFQDN, AuthenticationManager authManager)
{
- this(createConnectionProperties(appRegistry.getBroker()), Collections.singletonList((Object)"en_US"), appRegistry, localFQDN, authManager);
+ this(createConnectionProperties(appRegistry.getBrokerConfig()), Collections.singletonList((Object)"en_US"), appRegistry, localFQDN, authManager);
}
private ServerConnectionDelegate(Map<String, Object> properties,
@@ -226,7 +226,7 @@ public class ServerConnectionDelegate extends ServerDelegate
}
@Override
- protected int getChannelMax()
+ public int getChannelMax()
{
return _maxNoOfChannels;
}
@@ -266,9 +266,6 @@ public class ServerConnectionDelegate extends ServerDelegate
if(isSessionNameUnique(atc.getName(), conn))
{
super.sessionAttach(conn, atc);
- final ServerConnection serverConnection = (ServerConnection) conn;
-
- serverConnection.checkForNotification();
}
else
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionMBean.java
deleted file mode 100644
index bb545164fb..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionMBean.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * 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.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.ManagementActor;
-import org.apache.qpid.server.management.AbstractAMQManagedConnectionObject;
-import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.protocol.AMQSessionModel;
-
-import javax.management.JMException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import java.io.IOException;
-import java.util.Date;
-import java.util.List;
-
-/**
- * This MBean class implements the management interface. In order to make more attributes, operations and notifications
- * available over JMX simply augment the ManagedConnection interface and add the appropriate implementation here.
- */
-@MBeanDescription("Management Bean for an AMQ Broker 0-10 Connection")
-public class ServerConnectionMBean extends AbstractAMQManagedConnectionObject
-{
- private final ServerConnection _serverConnection;
-
- @MBeanConstructor("Creates an MBean exposing an AMQ Broker 0-10 Connection")
- protected ServerConnectionMBean(final ServerConnection serverConnection) throws NotCompliantMBeanException
- {
- super(serverConnection.getConfig().getAddress());
- _serverConnection = serverConnection;
- }
-
- @Override
- public ManagedObject getParentObject()
- {
- return _serverConnection.getVirtualHost().getManagedObject();
- }
-
- @Override
- public String getClientId()
- {
- return _serverConnection.getClientId();
- }
-
- @Override
- public String getAuthorizedId()
- {
- return _serverConnection.getAuthorizedPrincipal().getName();
- }
-
- @Override
- public String getVersion()
- {
- return String.valueOf(_serverConnection.getClientVersion());
- }
-
- @Override
- public String getRemoteAddress()
- {
- return _serverConnection.getConfig().getAddress();
- }
-
- @Override
- public Date getLastIoTime()
- {
- return new Date(_serverConnection.getLastIoTime().longValue());
- }
-
- @Override
- public Long getMaximumNumberOfChannels()
- {
- return (long) _serverConnection.getConnectionDelegate().getChannelMax();
- }
-
- @Override
- public TabularData channels() throws IOException, JMException
- {
- final TabularDataSupport channelsList = new TabularDataSupport(_channelsType);
- final List<AMQSessionModel> list = _serverConnection.getSessionModels();
-
- for (final AMQSessionModel channel : list)
- {
- final ServerSession session = (ServerSession)channel;
- Object[] itemValues =
- {
- session.getChannel(),
- session.isTransactional(),
- null,
- session.getUnacknowledgedMessageCount(),
- session.getBlocking()
- };
-
- final CompositeData channelData = new CompositeDataSupport(_channelType,
- COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues);
- channelsList.put(channelData);
- }
- return channelsList;
- }
-
- @Override
- public void commitTransactions(int channelId) throws JMException
- {
- final ServerSession session = (ServerSession)_serverConnection.getSession(channelId);
- if (session == null)
- {
- throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
- }
- else if (session.isTransactional())
- {
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- session.commit();
- }
- finally
- {
- CurrentActor.remove();
- }
- }
- }
-
- @Override
- public void rollbackTransactions(int channelId) throws JMException
- {
- final ServerSession session = (ServerSession)_serverConnection.getSession(channelId);
- if (session == null)
- {
- throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
- }
- else if (session.isTransactional())
- {
- CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger()));
- try
- {
- session.rollback();
- }
- finally
- {
- CurrentActor.remove();
- }
- }
- }
-
- @Override
- public void closeConnection() throws Exception
- {
- _serverConnection.mgmtClose();
- }
-
- @Override
- public void resetStatistics() throws Exception
- {
- _serverConnection.resetStatistics();
- }
-
- @Override
- public double getPeakMessageDeliveryRate()
- {
- return _serverConnection.getMessageDeliveryStatistics().getPeak();
- }
-
- @Override
- public double getPeakDataDeliveryRate()
- {
- return _serverConnection.getDataDeliveryStatistics().getPeak();
- }
-
- @Override
- public double getMessageDeliveryRate()
- {
- return _serverConnection.getMessageDeliveryStatistics().getRate();
- }
-
- @Override
- public double getDataDeliveryRate()
- {
- return _serverConnection.getDataDeliveryStatistics().getRate();
- }
-
- @Override
- public long getTotalMessagesDelivered()
- {
- return _serverConnection.getMessageDeliveryStatistics().getTotal();
- }
-
- @Override
- public long getTotalDataDelivered()
- {
- return _serverConnection.getDataDeliveryStatistics().getTotal();
- }
-
- @Override
- public double getPeakMessageReceiptRate()
- {
- return _serverConnection.getMessageReceiptStatistics().getPeak();
- }
-
- @Override
- public double getPeakDataReceiptRate()
- {
- return _serverConnection.getDataReceiptStatistics().getPeak();
- }
-
- @Override
- public double getMessageReceiptRate()
- {
- return _serverConnection.getMessageReceiptStatistics().getRate();
- }
-
- @Override
- public double getDataReceiptRate()
- {
- return _serverConnection.getDataReceiptStatistics().getRate();
- }
-
- @Override
- public long getTotalMessagesReceived()
- {
- return _serverConnection.getMessageReceiptStatistics().getTotal();
- }
-
- @Override
- public long getTotalDataReceived()
- {
- return _serverConnection.getDataReceiptStatistics().getTotal();
- }
-
- @Override
- public boolean isStatisticsEnabled()
- {
- return _serverConnection.isStatisticsEnabled();
- }
-
- @Override
- public void setStatisticsEnabled(boolean enabled)
- {
- _serverConnection.setStatisticsEnabled(enabled);
- }
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
index 0cb60fafd3..9914485638 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
@@ -630,11 +630,21 @@ public class ServerSession extends Session
return _txnRejects.get();
}
+ public int getChannelId()
+ {
+ return getChannel();
+ }
+
public Long getTxnCount()
{
return _txnCount.get();
}
+ public Long getTxnStart()
+ {
+ return _txnStarts.get();
+ }
+
public Principal getAuthorizedPrincipal()
{
return getConnection().getAuthorizedPrincipal();
@@ -1059,5 +1069,4 @@ public class ServerSession extends Session
{
return getId().compareTo(session.getId());
}
-
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
index 85ea97c107..3dbc835c45 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
@@ -1226,11 +1226,7 @@ public class ServerSessionDelegate extends SessionDelegate
try
{
queue = createQueue(queueName, method, virtualHost, (ServerSession)session);
- if(method.getExclusive())
- {
- queue.setExclusive(true);
- }
- else if(method.getAutoDelete())
+ if(!method.getExclusive() && method.getAutoDelete())
{
queue.setDeleteOnNoConsumers(true);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
index c59016173a..dcc5acb820 100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
@@ -32,7 +32,6 @@ 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.management.ManagedObject;
import org.apache.qpid.server.protocol.v1_0.LinkRegistry;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
@@ -62,8 +61,6 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo
void close();
- ManagedObject getManagedObject();
-
UUID getBrokerId();
void scheduleHouseKeepingTask(long period, HouseKeepingTask task);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
index e956806823..acd6101ff8 100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
@@ -100,7 +100,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
return this;
}
- public void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments)
+ public void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments, UUID alternateExchangeId)
{
try
{
@@ -111,6 +111,17 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
q = AMQQueueFactory.createAMQQueueImpl(id, queueName, true, owner, false, exclusive, _virtualHost,
FieldTable.convertToMap(arguments));
_virtualHost.getQueueRegistry().registerQueue(q);
+
+ if (alternateExchangeId != null)
+ {
+ Exchange altExchange = _virtualHost.getExchangeRegistry().getExchange(alternateExchangeId);
+ if (altExchange == null)
+ {
+ _logger.error("Unknown exchange id " + alternateExchangeId + ", cannot set alternate exchange on queue with id " + id);
+ return;
+ }
+ q.setAlternateExchange(altExchange);
+ }
}
CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_START(queueName, true));
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
index 5a56fe1765..8945431e99 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
@@ -20,12 +20,20 @@
*/
package org.apache.qpid.server.virtualhost;
+import java.util.HashMap;
+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;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.AMQBrokerManagerMBean;
import org.apache.qpid.server.binding.BindingFactory;
import org.apache.qpid.server.configuration.BrokerConfig;
import org.apache.qpid.server.configuration.ConfigStore;
@@ -45,11 +53,9 @@ 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;
-import org.apache.qpid.server.management.AMQManagedObject;
-import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.protocol.v1_0.LinkRegistry;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.protocol.v1_0.LinkRegistry;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.queue.DefaultQueueRegistry;
@@ -66,20 +72,6 @@ import org.apache.qpid.server.txn.DtxRegistry;
import org.apache.qpid.server.virtualhost.plugins.VirtualHostPlugin;
import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory;
-import javax.management.JMException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.ObjectName;
-import java.util.HashMap;
-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;
-
-
public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.RegistryChangeListener, EventListener
{
private static final Logger _logger = Logger.getLogger(VirtualHostImpl.class);
@@ -104,10 +96,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr
private final VirtualHostConfiguration _vhostConfig;
- private final VirtualHostMBean _virtualHostMBean;
-
- private final AMQBrokerManagerMBean _brokerMBean;
-
private final QueueRegistry _queueRegistry;
private final ExchangeRegistry _exchangeRegistry;
@@ -124,8 +112,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr
private volatile State _state = State.INITIALISING;
- private boolean _statisticsEnabled = false;
-
private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
private final Map<String, LinkRegistry> _linkRegistry = new HashMap<String, LinkRegistry>();
@@ -144,7 +130,7 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr
}
_appRegistry = appRegistry;
- _brokerConfig = _appRegistry.getBroker();
+ _brokerConfig = _appRegistry.getBrokerConfig();
_vhostConfig = hostConfig;
_name = _vhostConfig.getName();
_dtxRegistry = new DtxRegistry();
@@ -153,7 +139,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr
CurrentActor.get().message(VirtualHostMessages.CREATED(_name));
- _virtualHostMBean = new VirtualHostMBean();
_securityManager = new SecurityManager(_appRegistry.getSecurityManager());
_securityManager.configureHostPlugins(_vhostConfig);
@@ -171,8 +156,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr
_bindingFactory = new BindingFactory(this);
- _brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean);
-
_messageStore = initialiseMessageStore(hostConfig.getMessageStoreClass());
configureMessageStore(hostConfig);
@@ -541,16 +524,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr
CurrentActor.get().message(VirtualHostMessages.CLOSED());
}
- public ManagedObject getBrokerMBean()
- {
- return _brokerMBean;
- }
-
- public ManagedObject getManagedObject()
- {
- return _virtualHostMBean;
- }
-
public UUID getBrokerId()
{
return _appRegistry.getBrokerId();
@@ -568,21 +541,15 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr
public void registerMessageDelivered(long messageSize)
{
- if (isStatisticsEnabled())
- {
- _messagesDelivered.registerEvent(1L);
- _dataDelivered.registerEvent(messageSize);
- }
+ _messagesDelivered.registerEvent(1L);
+ _dataDelivered.registerEvent(messageSize);
_appRegistry.registerMessageDelivered(messageSize);
}
public void registerMessageReceived(long messageSize, long timestamp)
{
- if (isStatisticsEnabled())
- {
- _messagesReceived.registerEvent(1L, timestamp);
- _dataReceived.registerEvent(messageSize, timestamp);
- }
+ _messagesReceived.registerEvent(1L, timestamp);
+ _dataReceived.registerEvent(messageSize, timestamp);
_appRegistry.registerMessageReceived(messageSize, timestamp);
}
@@ -621,25 +588,12 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr
public void initialiseStatistics()
{
- setStatisticsEnabled(!StatisticsCounter.DISABLE_STATISTICS &&
- _appRegistry.getConfiguration().isStatisticsGenerationVirtualhostsEnabled());
-
_messagesDelivered = new StatisticsCounter("messages-delivered-" + getName());
_dataDelivered = new StatisticsCounter("bytes-delivered-" + getName());
_messagesReceived = new StatisticsCounter("messages-received-" + getName());
_dataReceived = new StatisticsCounter("bytes-received-" + getName());
}
- public boolean isStatisticsEnabled()
- {
- return _statisticsEnabled;
- }
-
- public void setStatisticsEnabled(boolean enabled)
- {
- _statisticsEnabled = enabled;
- }
-
public BrokerLink createBrokerConnection(UUID id, long createTime, Map<String,String> arguments)
{
BrokerLink blink = new BrokerLink(this, id, createTime, arguments);
@@ -772,36 +726,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr
}
}
-
- /**
- * Virtual host JMX MBean class.
- *
- * This has some of the methods implemented from management interface for exchanges. Any
- * Implementation of an Exchange MBean should extend this class.
- */
- public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtualHost
- {
- public VirtualHostMBean() throws NotCompliantMBeanException
- {
- super(ManagedVirtualHost.class, ManagedVirtualHost.TYPE);
- }
-
- public String getObjectInstanceName()
- {
- return ObjectName.quote(_name);
- }
-
- public String getName()
- {
- return _name;
- }
-
- public VirtualHostImpl getVirtualHost()
- {
- return VirtualHostImpl.this;
- }
- }
-
private final class BeforeActivationListener implements EventListener
{
@Override
@@ -825,17 +749,19 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr
public void event(Event event)
{
State finalState = State.ERRORED;
+
try
{
initialiseHouseKeeping(_vhostConfig.getHousekeepingCheckPeriod());
- try
- {
- _brokerMBean.register();
- }
- catch (JMException e)
- {
- throw new RuntimeException("Failed to register virtual host mbean for virtual host " + getName(), e);
- }
+//TODO: implement state changing for the VirtualHost MBean instead of registering and unregistering
+// try
+// {
+// _brokerMBean.register();
+// }
+// catch (JMException e)
+// {
+// throw new RuntimeException("Failed to register virtual host mbean for virtual host " + getName(), e);
+// }
finalState = State.ACTIVE;
}
finally
@@ -861,7 +787,8 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr
*/
_connectionRegistry.close(IConnectionRegistry.VHOST_PASSIVATE_REPLY_TEXT);
- _brokerMBean.unregister();
+//TODO: implement state changing for the VirtualHost MBean instead of registering and unregistering
+// _brokerMBean.unregister();
removeHouseKeepingTasks();
_queueRegistry.stopAllAndUnregisterMBeans();
@@ -884,7 +811,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr
@Override
public void event(Event event)
{
- _brokerMBean.unregister();
shutdownHouseKeeping();
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
index ef621a166a..1be472844a 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
@@ -22,10 +22,12 @@ 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;
@@ -37,6 +39,8 @@ public class VirtualHostRegistry implements Closeable
private String _defaultVirtualHostName;
private ApplicationRegistry _applicationRegistry;
+ private final Collection<RegistryChangeListener> _listeners =
+ Collections.synchronizedCollection(new ArrayList<RegistryChangeListener>());
public VirtualHostRegistry(ApplicationRegistry applicationRegistry)
{
@@ -50,11 +54,25 @@ public class VirtualHostRegistry implements Closeable
throw new Exception("Virtual Host with name " + host.getName() + " already registered.");
}
_registry.put(host.getName(),host);
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.virtualHostRegistered(host);
+ }
+ }
}
public synchronized void unregisterVirtualHost(VirtualHost host)
{
_registry.remove(host.getName());
+ synchronized (_listeners)
+ {
+ for(RegistryChangeListener listener : _listeners)
+ {
+ listener.virtualHostUnregistered(host);
+ }
+ }
}
public VirtualHost getVirtualHost(String name)
@@ -106,4 +124,17 @@ public class VirtualHostRegistry implements Closeable
}
}
+
+ public static interface RegistryChangeListener
+ {
+ void virtualHostRegistered(VirtualHost virtualHost);
+ void virtualHostUnregistered(VirtualHost virtualHost);
+
+ }
+
+ public void addRegistryChangeListener(RegistryChangeListener listener)
+ {
+ _listeners.add(listener);
+ }
+
}
diff --git a/qpid/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java b/qpid/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java
deleted file mode 100644
index c06ce5e31a..0000000000
--- a/qpid/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- *
- */
-package org.apache.log4j.xml;
-
-
-import junit.framework.TestCase;
-import org.apache.log4j.xml.QpidLog4JConfigurator.IllegalLoggerLevelException;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-
-public class QpidLog4JConfiguratorTest extends TestCase
-{
- private static final String NEWLINE = System.getProperty("line.separator");
-
- private File _testConfigFile;
-
- private File createTempTestLog4JConfig(String loggerLevel,String rootLoggerLevel, boolean missingTagClose, boolean incorrectAttribute)
- {
- File tmpFile = null;
- try
- {
- tmpFile = File.createTempFile("QpidLog4JConfiguratorTestLog4jConfig", ".tmp");
- tmpFile.deleteOnExit();
-
- FileWriter fstream = new FileWriter(tmpFile);
- BufferedWriter writer = new BufferedWriter(fstream);
-
- writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+NEWLINE);
- writer.write("<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">"+NEWLINE);
-
- writer.write("<log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\" debug=\"null\" " +
- "threshold=\"null\">"+NEWLINE);
-
- writer.write(" <appender class=\"org.apache.log4j.ConsoleAppender\" name=\"STDOUT\">"+NEWLINE);
- writer.write(" <layout class=\"org.apache.log4j.PatternLayout\">"+NEWLINE);
- writer.write(" <param name=\"ConversionPattern\" value=\"%d %-5p [%t] %C{2} (%F:%L) - %m%n\"/>"+NEWLINE);
- writer.write(" </layout>"+NEWLINE);
- writer.write(" </appender>"+NEWLINE);
-
- String closeTag="/";
- if(missingTagClose)
- {
- closeTag="";
- }
-
- //Example of a 'category' with a 'priority'
- writer.write(" <category additivity=\"true\" name=\"logger1\">"+NEWLINE);
- writer.write(" <priority value=\"" + loggerLevel+ "\"" + closeTag + ">"+NEWLINE);
- writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
- writer.write(" </category>"+NEWLINE);
-
- String attributeName="value";
- if(incorrectAttribute)
- {
- attributeName="values";
- }
-
- //Example of a 'category' with a 'level'
- writer.write(" <category additivity=\"true\" name=\"logger2\">"+NEWLINE);
- writer.write(" <level " + attributeName + "=\"" + loggerLevel+ "\"/>"+NEWLINE);
- writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
- writer.write(" </category>"+NEWLINE);
-
- //Example of a 'logger' with a 'level'
- writer.write(" <logger additivity=\"true\" name=\"logger3\">"+NEWLINE);
- writer.write(" <level value=\"" + loggerLevel+ "\"/>"+NEWLINE);
- writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
- writer.write(" </logger>"+NEWLINE);
-
- //'root' logger
- writer.write(" <root>"+NEWLINE);
- writer.write(" <priority value=\"" + rootLoggerLevel+ "\"/>"+NEWLINE);
- writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE);
- writer.write(" </root>"+NEWLINE);
-
- writer.write("</log4j:configuration>"+NEWLINE);
-
- writer.flush();
- writer.close();
- }
- catch (IOException e)
- {
- fail("Unable to create temporary test log4j configuration");
- }
-
- return tmpFile;
- }
-
-
-
- //******* Test Methods ******* //
-
- public void testCheckLevelsAndStrictParser()
- {
- //try the valid logger levels
- _testConfigFile = createTempTestLog4JConfig("all", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("trace", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("debug", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("warn", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("error", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("fatal", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("off", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("null", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("inherited", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- //now try an invalid logger level
- _testConfigFile = createTempTestLog4JConfig("madeup", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- fail("IllegalLoggerLevelException expected, invalid levels used");
- }
- catch (IllegalLoggerLevelException e)
- {
- //expected, ignore
- }
- catch (IOException e)
- {
- fail("Incorrect Exception, expected an IllegalLoggerLevelException");
- }
-
-
-
- //now try the valid rootLogger levels
- _testConfigFile = createTempTestLog4JConfig("info", "all", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "trace", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "debug", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "info", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "warn", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "error", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "fatal", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "off", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "null", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "inherited", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "debug", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- }
- catch (Exception e)
- {
- fail("No exception expected, valid levels and xml were used");
- }
-
- //now try an invalid logger level
- _testConfigFile = createTempTestLog4JConfig("info", "madeup", false, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- fail("IllegalLoggerLevelException expected, invalid levels used");
- }
- catch (IllegalLoggerLevelException e)
- {
- //expected, ignore
- }
- catch (IOException e)
- {
- fail("Incorrect Exception, expected an IllegalLoggerLevelException");
- }
-
-
-
- //now try invalid xml
- _testConfigFile = createTempTestLog4JConfig("info", "info", true, false);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- fail("IOException expected, malformed XML used");
- }
- catch (IllegalLoggerLevelException e)
- {
- fail("Incorrect Exception, expected an IOException");
- }
- catch (IOException e)
- {
- //expected, ignore
- }
-
- _testConfigFile = createTempTestLog4JConfig("info", "info", false, true);
- try
- {
- QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath());
- fail("IOException expected, malformed XML used");
- }
- catch (IllegalLoggerLevelException e)
- {
- //expected, ignore
- }
- catch (IOException e)
- {
- fail("Incorrect Exception, expected an IllegalLoggerLevelException");
- }
- }
-}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java
deleted file mode 100644
index d34d1bbef3..0000000000
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server;
-
-import org.apache.commons.configuration.XMLConfiguration;
-
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.server.configuration.ServerConfiguration;
-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.queue.AMQPriorityQueue;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.AMQQueueFactory;
-import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.store.TestableMemoryMessageStore;
-import org.apache.qpid.server.util.TestApplicationRegistry;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.virtualhost.VirtualHostImpl;
-import org.apache.qpid.test.utils.QpidTestCase;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class AMQBrokerManagerMBeanTest extends QpidTestCase
-{
- private QueueRegistry _queueRegistry;
- private ExchangeRegistry _exchangeRegistry;
- private VirtualHost _vHost;
-
- public void testExchangeOperations() throws Exception
- {
- String exchange1 = "testExchange1_" + System.currentTimeMillis();
- String exchange2 = "testExchange2_" + System.currentTimeMillis();
- String exchange3 = "testExchange3_" + System.currentTimeMillis();
-
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange1)) == null);
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange2)) == null);
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange3)) == null);
-
-
- ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject());
- mbean.createNewExchange(exchange1, "direct", false);
- mbean.createNewExchange(exchange2, "topic", false);
- mbean.createNewExchange(exchange3, "headers", false);
-
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange1)) != null);
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange2)) != null);
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange3)) != null);
-
- mbean.unregisterExchange(exchange1);
- mbean.unregisterExchange(exchange2);
- mbean.unregisterExchange(exchange3);
-
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange1)) == null);
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange2)) == null);
- assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange3)) == null);
- }
-
- public void testQueueOperations() throws Exception
- {
- String queueName = "testQueue_" + System.currentTimeMillis();
-
- ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject());
-
- assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) == null);
-
- mbean.createNewQueue(queueName, "test", false);
- assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) != null);
-
- mbean.deleteQueue(queueName);
- assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) == null);
- }
-
- public void testCreateNewQueueBindsToDefaultExchange() throws Exception
- {
- String queueName = "testQueue_" + System.currentTimeMillis();
-
- ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject());
- ExchangeRegistry exReg = _vHost.getExchangeRegistry();
- Exchange defaultExchange = exReg.getDefaultExchange();
-
- mbean.createNewQueue(queueName, "test", false);
- assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) != null);
-
- assertTrue("New queue should be bound to default exchange", defaultExchange.isBound(new AMQShortString(queueName)));
- }
-
- /**
- * Tests that setting the {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument does cause the
- * maximum delivery count to be set on the Queue.
- */
- public void testCreateNewQueueWithMaximumDeliveryCount() throws Exception
- {
- final Map<String,Object> args = new HashMap<String, Object>();
- args.put(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, 5);
-
- final AMQShortString queueName = new AMQShortString("testCreateNewQueueWithMaximumDeliveryCount");
-
- final QueueRegistry qReg = _vHost.getQueueRegistry();
-
- assertNull("The queue should not yet exist", qReg.getQueue(queueName));
-
- final ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject());
- mbean.createNewQueue(queueName.asString(), "test", false, args);
-
- final AMQQueue createdQueue = qReg.getQueue(queueName);
- assertNotNull("The queue was not registered as expected", createdQueue);
- assertEquals("Unexpected maximum delivery count", 5, createdQueue.getMaximumDeliveryCount());
- }
-
- /**
- * Tests that setting the {@link AMQQueueFactory#X_QPID_PRIORITIES} argument prompts creation of
- * a Priority Queue.
- */
- public void testCreatePriorityQueue() throws Exception
- {
- int numPriorities = 7;
- Map<String,Object> args = new HashMap<String, Object>();
- args.put(AMQQueueFactory.X_QPID_PRIORITIES, numPriorities);
-
- AMQShortString queueName = new AMQShortString("testCreatePriorityQueue");
-
- QueueRegistry qReg = _vHost.getQueueRegistry();
-
- assertNull("The queue should not yet exist", qReg.getQueue(queueName));
-
- ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject());
- mbean.createNewQueue(queueName.asString(), "test", false, args);
-
- AMQQueue queue = qReg.getQueue(queueName);
- assertEquals("Queue is not a priorty queue", AMQPriorityQueue.class, queue.getClass());
- assertEquals("Number of priorities supported was not as expected", numPriorities, ((AMQPriorityQueue)queue).getPriorities());
- }
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- CurrentActor.set(new TestLogActor(new SystemOutMessageLogger()));
-
- XMLConfiguration configXml = new XMLConfiguration();
- configXml.addProperty("virtualhosts.virtualhost(-1).name", "test");
- configXml.addProperty("virtualhosts.virtualhost(-1).test.store.class", TestableMemoryMessageStore.class.getName());
-
- ServerConfiguration configuration = new ServerConfiguration(configXml);
-
- ApplicationRegistry registry = new TestApplicationRegistry(configuration);
- ApplicationRegistry.initialise(registry);
- registry.getVirtualHostRegistry().setDefaultVirtualHostName("test");
-
- IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
- _vHost = appRegistry.getVirtualHostRegistry().getVirtualHost("test");
- _queueRegistry = _vHost.getQueueRegistry();
- _exchangeRegistry = _vHost.getExchangeRegistry();
- }
-
- @Override
- public void tearDown() throws Exception
- {
- try
- {
- super.tearDown();
- }
- finally
- {
- ApplicationRegistry.remove();
- }
- }
-}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java
index 36f131a30f..9225f7810a 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java
@@ -204,6 +204,18 @@ public class QueueConfigurationTest extends TestCase
assertEquals("test-sort-key", qConf.getQueueSortKey());
}
+ public void testQueueDescription() throws ConfigurationException
+ {
+ //Check default value
+ QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf);
+ assertNull(qConf.getDescription());
+
+ // Check explicit value
+ final VirtualHostConfiguration vhostConfig = overrideConfiguration("description", "mydescription");
+ qConf = new QueueConfiguration("test", vhostConfig);
+ assertEquals("mydescription", qConf.getDescription());
+ }
+
private VirtualHostConfiguration overrideConfiguration(String property, Object value)
throws ConfigurationException
{
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
index c2d2eb37c1..2ee02430c8 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
@@ -252,13 +252,13 @@ public class ServerConfigurationTest extends QpidTestCase
{
// Check default
_serverConfig.initialise();
- assertEquals(true, _serverConfig.getManagementSSLEnabled());
+ assertEquals(false, _serverConfig.getManagementSSLEnabled());
// Check value we set
- _config.setProperty("management.ssl.enabled", false);
+ _config.setProperty("management.ssl.enabled", true);
_serverConfig = new ServerConfiguration(_config);
_serverConfig.initialise();
- assertEquals(false, _serverConfig.getManagementSSLEnabled());
+ assertEquals(true, _serverConfig.getManagementSSLEnabled());
}
public void testGetManagementKeystorePassword() throws ConfigurationException
@@ -287,25 +287,17 @@ public class ServerConfigurationTest extends QpidTestCase
assertEquals(false, _serverConfig.getQueueAutoRegister());
}
- public void testGetManagementEnabled() throws ConfigurationException
+ public void testGetJMXManagementEnabled() throws ConfigurationException
{
// Check default
_serverConfig.initialise();
- assertEquals(true, _serverConfig.getManagementEnabled());
+ assertEquals(true, _serverConfig.getJMXManagementEnabled());
// Check value we set
_config.setProperty("management.enabled", false);
_serverConfig = new ServerConfiguration(_config);
_serverConfig.initialise();
- assertEquals(false, _serverConfig.getManagementEnabled());
- }
-
- public void testSetManagementEnabled() throws ConfigurationException
- {
- // Check value we set
- _serverConfig.initialise();
- _serverConfig.setManagementEnabled(false);
- assertEquals(false, _serverConfig.getManagementEnabled());
+ assertEquals(false, _serverConfig.getJMXManagementEnabled());
}
public void testGetManagementRightsInferAllAccess() throws Exception
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
deleted file mode 100644
index 9034bf9c3a..0000000000
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.exchange;
-
-import org.apache.commons.lang.ArrayUtils;
-
-import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.management.common.mbeans.ManagedExchange;
-import org.apache.qpid.server.management.ManagedObject;
-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.queue.QueueRegistry;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.util.InternalBrokerBaseCase;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularData;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * Unit test class for testing different Exchange MBean operations
- */
-public class ExchangeMBeanTest extends InternalBrokerBaseCase
-{
- private AMQQueue _queue;
- private QueueRegistry _queueRegistry;
- private VirtualHost _virtualHost;
-
- public void testGeneralProperties() throws Exception
- {
- DirectExchange exchange = new DirectExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true);
- ManagedObject managedObj = exchange.getManagedObject();
- ManagedExchange mbean = (ManagedExchange)managedObj;
-
- // test general exchange properties
- assertEquals("Unexpected exchange name", "amq.direct", mbean.getName());
- assertEquals("Unexpected exchange type", "direct", mbean.getExchangeType());
- assertEquals("Unexpected ticket number", Integer.valueOf(0), mbean.getTicketNo());
- assertFalse("Unexpected durable flag", mbean.isDurable());
- assertTrue("Unexpected auto delete flag", mbean.isAutoDelete());
- }
-
- public void testDirectExchangeMBean() throws Exception
- {
- DirectExchange exchange = new DirectExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true);
- ManagedObject managedObj = exchange.getManagedObject();
- ManagedExchange mbean = (ManagedExchange)managedObj;
-
- mbean.createNewBinding(_queue.getNameShortString().toString(), "binding1");
- mbean.createNewBinding(_queue.getNameShortString().toString(), "binding2");
-
- TabularData data = mbean.bindings();
- ArrayList<Object> list = new ArrayList<Object>(data.values());
- assertTrue(list.size() == 2);
- }
-
- public void testTopicExchangeMBean() throws Exception
- {
- TopicExchange exchange = new TopicExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.TOPIC_EXCHANGE_NAME, false, 0, true);
- ManagedObject managedObj = exchange.getManagedObject();
- ManagedExchange mbean = (ManagedExchange)managedObj;
-
- mbean.createNewBinding(_queue.getNameShortString().toString(), "binding1");
- mbean.createNewBinding(_queue.getNameShortString().toString(), "binding2");
-
- TabularData data = mbean.bindings();
- ArrayList<Object> list = new ArrayList<Object>(data.values());
- assertTrue(list.size() == 2);
- }
-
- public void testHeadersExchangeMBean() throws Exception
- {
- HeadersExchange exchange = new HeadersExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true);
- ManagedObject managedObj = exchange.getManagedObject();
- ManagedExchange mbean = (ManagedExchange)managedObj;
-
- mbean.createNewBinding(_queue.getNameShortString().toString(), "x-match=any,key1=binding1,key2=binding2");
-
- TabularData data = mbean.bindings();
- ArrayList<Object> list = new ArrayList<Object>(data.values());
- assertEquals("Unexpected number of bindings", 1, list.size());
-
- final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) data.values().iterator();
- CompositeDataSupport row = rowItr.next();
- assertBinding(1, _queue.getName(), new String[]{"x-match=any","key1=binding1","key2=binding2"}, row);
- }
-
- /**
- * Included to ensure 0-10 Specification compliance:
- * 2.3.1.4 "the field in the bind arguments has no value and a field of the same name is present in the message headers
- */
- public void testHeadersExchangeMBeanMatchPropertyNoValue() throws Exception
- {
- HeadersExchange exchange = new HeadersExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true);
- ManagedObject managedObj = exchange.getManagedObject();
- ManagedExchange mbean = (ManagedExchange)managedObj;
-
- mbean.createNewBinding(_queue.getNameShortString().toString(), "x-match=any,key4,key5=");
-
- TabularData data = mbean.bindings();
- ArrayList<Object> list = new ArrayList<Object>(data.values());
- assertEquals("Unexpected number of bindings", 1, list.size());
-
- final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) data.values().iterator();
- CompositeDataSupport row = rowItr.next();
- assertBinding(1, _queue.getName(), new String[]{"x-match=any","key4=","key5="}, row);
- }
-
- public void testInvalidHeaderBindingMalformed() throws Exception
- {
- HeadersExchange exchange = new HeadersExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true);
- ManagedObject managedObj = exchange.getManagedObject();
- ManagedExchange mbean = (ManagedExchange)managedObj;
-
- try
- {
- mbean.createNewBinding(_queue.getNameShortString().toString(), "x-match=any,=value4");
- fail("Exception not thrown");
- }
- catch (JMException jme)
- {
- //pass
- }
- }
-
- private void assertBinding(final int expectedBindingNo, final String expectedQueueName, final String[] expectedBindingArray,
- final CompositeDataSupport row)
- {
- final Number bindingNumber = (Number) row.get(ManagedExchange.HDR_BINDING_NUMBER);
- final String queueName = (String) row.get(ManagedExchange.HDR_QUEUE_NAME);
- final String[] bindings = (String[]) row.get(ManagedExchange.HDR_QUEUE_BINDINGS);
- assertEquals("Unexpected binding number", expectedBindingNo, bindingNumber);
- assertEquals("Unexpected queue name", expectedQueueName, queueName);
- assertEquals("Unexpected no of bindings", expectedBindingArray.length, bindings.length);
- for(String binding : bindings)
- {
- assertTrue("Expected binding not found: " + binding, ArrayUtils.contains(expectedBindingArray, binding));
- }
- }
-
- /**
- * Test adding bindings and removing them from the default exchange via JMX.
- * <p>
- * QPID-2700
- */
- public void testDefaultBindings() throws Exception
- {
- int bindings = _queue.getBindingCount();
-
- Exchange exchange = _queue.getVirtualHost().getExchangeRegistry().getDefaultExchange();
- ManagedExchange mbean = (ManagedExchange) ((AbstractExchange) exchange).getManagedObject();
-
- mbean.createNewBinding(_queue.getName(), "robot");
- mbean.createNewBinding(_queue.getName(), "kitten");
-
- assertEquals("Should have added two bindings", bindings + 2, _queue.getBindingCount());
-
- mbean.removeBinding(_queue.getName(), "robot");
-
- assertEquals("Should have one extra binding", bindings + 1, _queue.getBindingCount());
-
- mbean.removeBinding(_queue.getName(), "kitten");
-
- assertEquals("Should have original number of binding", bindings, _queue.getBindingCount());
- }
-
- /**
- * Test adding bindings and removing them from the topic exchange via JMX.
- * <p>
- * QPID-2700
- */
- public void testTopicBindings() throws Exception
- {
- int bindings = _queue.getBindingCount();
-
- Exchange exchange = _queue.getVirtualHost().getExchangeRegistry().getExchange(new AMQShortString("amq.topic"));
- ManagedExchange mbean = (ManagedExchange) ((AbstractExchange) exchange).getManagedObject();
-
- mbean.createNewBinding(_queue.getName(), "robot.#");
- mbean.createNewBinding(_queue.getName(), "#.kitten");
-
- assertEquals("Should have added two bindings", bindings + 2, _queue.getBindingCount());
-
- mbean.removeBinding(_queue.getName(), "robot.#");
-
- assertEquals("Should have one extra binding", bindings + 1, _queue.getBindingCount());
-
- mbean.removeBinding(_queue.getName(), "#.kitten");
-
- assertEquals("Should have original number of binding", bindings, _queue.getBindingCount());
- }
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- IApplicationRegistry applicationRegistry = ApplicationRegistry.getInstance();
- _virtualHost = applicationRegistry.getVirtualHostRegistry().getVirtualHost("test");
- _queueRegistry = _virtualHost.getQueueRegistry();
- _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue"), false, new AMQShortString("ExchangeMBeanTest"), false, false,
- _virtualHost, null);
- _queueRegistry.registerQueue(_queue);
- }
-}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java
index 4305cdadc6..833df34fd8 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.exchange;
+import java.util.Collection;
import junit.framework.TestCase;
import org.apache.qpid.server.binding.Binding;
@@ -50,6 +51,16 @@ public class HeadersBindingTest extends TestCase
return 0;
}
+ public String getUserId()
+ {
+ return null;
+ }
+
+ public String getAppId()
+ {
+ return null;
+ }
+
public String getMessageId()
{
return null;
@@ -57,7 +68,7 @@ public class HeadersBindingTest extends TestCase
public String getMimeType()
{
- return null; //To change body of implemented methods use File | Settings | File Templates.
+ return null;
}
public String getEncoding()
@@ -105,6 +116,12 @@ public class HeadersBindingTest extends TestCase
return _headers.keySet().containsAll(names);
}
+ @Override
+ public Collection<String> getHeaderNames()
+ {
+ return _headers.keySet();
+ }
+
public boolean containsHeader(String name)
{
return _headers.containsKey(name);
@@ -125,13 +142,13 @@ public class HeadersBindingTest extends TestCase
private MockHeader matchHeaders = new MockHeader();
private int _count = 0;
private MockAMQQueue _queue;
-
+
protected void setUp()
{
_count++;
_queue = new MockAMQQueue(getQueueName());
}
-
+
protected String getQueueName()
{
return "Queue" + _count;
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java
deleted file mode 100644
index f7d85c11a8..0000000000
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.server.management;
-
-import org.apache.qpid.management.common.mbeans.UserManagement;
-import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase;
-import org.apache.qpid.server.security.auth.management.AMQUserManagementMBean;
-import org.apache.qpid.server.util.InternalBrokerBaseCase;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularData;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-
-/**
- *
- * Tests the AMQUserManagementMBean and its interaction with the PrincipalDatabase.
- *
- */
-public class AMQUserManagementMBeanTest extends InternalBrokerBaseCase
-{
- private PlainPasswordFilePrincipalDatabase _database;
- private AMQUserManagementMBean _amqumMBean;
-
- private File _passwordFile;
-
- private static final String TEST_USERNAME = "testuser";
- private static final String TEST_PASSWORD = "password";
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- _database = new PlainPasswordFilePrincipalDatabase();
- _amqumMBean = new AMQUserManagementMBean();
- loadFreshTestPasswordFile();
- }
-
- @Override
- public void tearDown() throws Exception
- {
- //clean up test password/access files
- File _oldPasswordFile = new File(_passwordFile.getAbsolutePath() + ".old");
- _oldPasswordFile.delete();
- _passwordFile.delete();
-
- super.tearDown();
- }
-
- public void testDeleteUser()
- {
- assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size());
- assertTrue("Delete should return true to flag successful delete", _amqumMBean.deleteUser(TEST_USERNAME));
- assertEquals("Unexpected number of users after test", 0,_amqumMBean.viewUsers().size());
- }
-
- public void testDeleteUserWhereUserDoesNotExist()
- {
- assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size());
- assertFalse("Delete should return false to flag unsuccessful delete", _amqumMBean.deleteUser("made.up.username"));
- assertEquals("Unexpected number of users after test", 1,_amqumMBean.viewUsers().size());
-
- }
-
- public void testCreateUser()
- {
- assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size());
- assertTrue("Create should return true to flag successful create", _amqumMBean.createUser("newuser", "mypass"));
- assertEquals("Unexpected number of users before test", 2,_amqumMBean.viewUsers().size());
- }
-
- public void testCreateUserWhereUserAlreadyExists()
- {
- assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size());
- assertFalse("Create should return false to flag unsuccessful create", _amqumMBean.createUser(TEST_USERNAME, "mypass"));
- assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size());
- }
-
- public void testSetPassword()
- {
- assertTrue("Set password should return true to flag successful change", _amqumMBean.setPassword(TEST_USERNAME, "newpassword"));
- }
-
- public void testSetPasswordWhereUserDoesNotExist()
- {
- assertFalse("Set password should return false to flag successful change", _amqumMBean.setPassword("made.up.username", "newpassword"));
- }
-
- public void testViewUsers()
- {
- TabularData userList = _amqumMBean.viewUsers();
-
- assertNotNull(userList);
- assertEquals("Unexpected number of users in user list", 1, userList.size());
- assertTrue(userList.containsKey(new Object[]{TEST_USERNAME}));
-
- // Check the deprecated read, write and admin items continue to exist but return false.
- CompositeData userRec = userList.get(new Object[]{TEST_USERNAME});
- assertTrue(userRec.containsKey(UserManagement.RIGHTS_READ_ONLY));
- assertEquals(false, userRec.get(UserManagement.RIGHTS_READ_ONLY));
- assertEquals(false, userRec.get(UserManagement.RIGHTS_READ_WRITE));
- assertTrue(userRec.containsKey(UserManagement.RIGHTS_READ_WRITE));
- assertTrue(userRec.containsKey(UserManagement.RIGHTS_ADMIN));
- assertEquals(false, userRec.get(UserManagement.RIGHTS_ADMIN));
- }
-
- // ============================ Utility methods =========================
-
- private void loadFreshTestPasswordFile()
- {
- try
- {
- if(_passwordFile == null)
- {
- _passwordFile = File.createTempFile(this.getClass().getName(),".password");
- }
-
- BufferedWriter passwordWriter = new BufferedWriter(new FileWriter(_passwordFile, false));
- passwordWriter.write(TEST_USERNAME + ":" + TEST_PASSWORD);
- passwordWriter.newLine();
- passwordWriter.flush();
- passwordWriter.close();
- _database.setPasswordFile(_passwordFile.toString());
- _amqumMBean.setPrincipalDatabase(_database);
- }
- catch (IOException e)
- {
- fail("Unable to create test password file: " + e.getMessage());
- }
- }
-}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/impl/AbstractConfiguredObjectImplTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/impl/AbstractConfiguredObjectImplTest.java
new file mode 100644
index 0000000000..62c8225049
--- /dev/null
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/impl/AbstractConfiguredObjectImplTest.java
@@ -0,0 +1,188 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.impl;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+
+public class AbstractConfiguredObjectImplTest extends TestCase
+{
+
+ private ConfiguredObject _concreteObject;
+ private UUID _uuid = UUID.randomUUID();
+ private ConfigurationChangeListener _configurationStateChangeListener = mock(ConfigurationChangeListener.class);
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ _concreteObject = createParentConfiguredObject();
+ }
+
+ public void testInitialState()
+ {
+ assertEquals(State.INITIALISING, _concreteObject.getDesiredState());
+ }
+
+ public void testStateNotifications()
+ {
+ _concreteObject.addChangeListener(_configurationStateChangeListener);
+
+ _concreteObject.setDesiredState(State.INITIALISING, State.ACTIVE);
+
+ verify(_configurationStateChangeListener, times(1)).stateChanged(_concreteObject, State.INITIALISING, State.ACTIVE);
+
+ _concreteObject.setDesiredState(State.ACTIVE, State.ACTIVE);
+
+ verify(_configurationStateChangeListener, times(0)).stateChanged(_concreteObject, State.ACTIVE, State.ACTIVE);
+
+ verifyNoMoreInteractions(_configurationStateChangeListener);
+ }
+
+ public void testSetGetAttribute()
+ {
+ assertNull(_concreteObject.getAttribute("test-attribute"));
+
+ assertEquals(Integer.valueOf(1), _concreteObject.setAttribute("test-attribute", null, Integer.valueOf(1)));
+ assertEquals(Integer.valueOf(1), _concreteObject.getAttribute("test-attribute"));
+
+ assertNull(_concreteObject.setAttribute("test-attribute", Integer.valueOf(1), null));
+ assertNull(_concreteObject.getAttribute("test-attribute"));
+ }
+
+ public void testSetAttributeWhenCurrentNotMatched()
+ {
+ assertEquals(Integer.valueOf(1), _concreteObject.setAttribute("test-attribute", null, Integer.valueOf(1)));
+ assertEquals(Integer.valueOf(1), _concreteObject.getAttribute("test-attribute"));
+
+ assertEquals(Integer.valueOf(1), _concreteObject.setAttribute("test-attribute", Integer.valueOf(2), Integer.valueOf(3)));
+ assertEquals("Expected no change", Integer.valueOf(1), _concreteObject.getAttribute("test-attribute"));
+ }
+
+ public void testParentage()
+ {
+ TestParentCO parentCO = createParentConfiguredObject();
+ assertNull("Parent should have no parent", parentCO.getParent(TestParentCO.class));
+
+ Map<Class<? extends ConfiguredObject>, ConfiguredObject> parent = new HashMap<Class<? extends ConfiguredObject>, ConfiguredObject>();
+ parent.put(TestParentCO.class, parentCO);
+ TestChildCO childCO = createChildConfiguredObject(parent);
+
+ assertEquals("Child should have its parent", parentCO, childCO.getParent(TestParentCO.class));
+
+ TestParentCO stranger = createParentConfiguredObject();
+ assertNotSame("Child should not have stranger as its parent", stranger, childCO.getParent(TestParentCO.class));
+
+ }
+
+ private TestParentCO createParentConfiguredObject()
+ {
+ return new TestParentCO(_uuid, "parent1", State.INITIALISING, true, LifetimePolicy.PERMANENT, 0l, AbstractConfiguredObject.EMPTY_ATTRIBUTE_MAP);
+ }
+
+ private TestChildCO createChildConfiguredObject(Map<Class<? extends ConfiguredObject>, ConfiguredObject> parents)
+ {
+ return new TestChildCO(_uuid, "parent1", State.INITIALISING, true, LifetimePolicy.PERMANENT, 0l, AbstractConfiguredObject.EMPTY_ATTRIBUTE_MAP, parents);
+ }
+
+ private final class TestParentCO extends AbstractConfiguredObject
+ {
+ private TestParentCO(UUID id, String name, State state, boolean durable, LifetimePolicy lifetimePolicy,
+ long timeToLive, Map<String, Object> attributes)
+ {
+ super(id, name, state, durable, lifetimePolicy, timeToLive, attributes, EMPTY_PARENT_MAP);
+ }
+
+ @Override
+ public State getActualState()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected Object getLock()
+ {
+ return this;
+ }
+
+ @Override
+ public Statistics getStatistics()
+ {
+ return null;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ return null;
+ }
+ }
+
+ private final class TestChildCO extends AbstractConfiguredObject
+ {
+ private TestChildCO(UUID id, String name, State state, boolean durable, LifetimePolicy lifetimePolicy,
+ long timeToLive, Map<String, Object> attributes,
+ Map<Class<? extends ConfiguredObject>, ConfiguredObject> parents)
+ {
+ super(id, name, state, durable, lifetimePolicy, timeToLive, attributes, parents);
+ }
+
+ @Override
+ public State getActualState()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected Object getLock()
+ {
+ return this;
+ }
+
+ @Override
+ public Statistics getStatistics()
+ {
+ return null;
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
+ {
+ return null;
+ }
+ }
+
+}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/impl/BrokerImplTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/impl/BrokerImplTest.java
new file mode 100644
index 0000000000..0ffb6627ff
--- /dev/null
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/impl/BrokerImplTest.java
@@ -0,0 +1,106 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.impl;
+
+import static org.apache.qpid.server.model.impl.AbstractConfiguredObject.EMPTY_ATTRIBUTE_MAP;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import java.util.UUID;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+
+public class BrokerImplTest extends TestCase
+{
+ private Broker _broker;
+ private UUID _brokerUuid = UUID.randomUUID();
+ private ConfigurationChangeListener _childAddedRemovedListener = mock(ConfigurationChangeListener.class);
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ createBroker();
+ }
+
+ public void testVirtualHostChildAddedAndDeletedNotifications()
+ {
+ _broker.addChangeListener(_childAddedRemovedListener);
+
+ VirtualHost createdVirtualHost = _broker.createVirtualHost("vhost", State.INITIALISING, true, LifetimePolicy.PERMANENT, 0, EMPTY_ATTRIBUTE_MAP);
+
+ verify(_childAddedRemovedListener).childAdded(_broker, createdVirtualHost);
+ verifyNoMoreInteractions(_childAddedRemovedListener);
+
+ _broker.deleteVirtualHost(createdVirtualHost);
+ verify(_childAddedRemovedListener).childRemoved(_broker, createdVirtualHost);
+
+ verifyNoMoreInteractions(_childAddedRemovedListener);
+ }
+
+ public void testVirtualHostDeleteUnknownDisallowed()
+ {
+ try
+ {
+ _broker.deleteVirtualHost(mock(VirtualHost.class));
+ fail("Exception not thrown");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ // PASS
+ }
+ }
+
+ public void testVirtualHostDeletedTwiceDisallowed()
+ {
+ VirtualHost createdVirtualHost = _broker.createVirtualHost("vhost", State.INITIALISING, true, LifetimePolicy.PERMANENT, 0, EMPTY_ATTRIBUTE_MAP);
+ _broker.deleteVirtualHost(createdVirtualHost);
+
+ try
+ {
+ _broker.deleteVirtualHost(createdVirtualHost);
+ fail("Exception not thrown");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ // PASS
+ }
+ }
+
+ private void createBroker()
+ {
+ _broker = new BrokerImpl(_brokerUuid,
+ "broker1",
+ State.INITIALISING,
+ true,
+ LifetimePolicy.PERMANENT,
+ 0l,
+ EMPTY_ATTRIBUTE_MAP);
+ }
+}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/impl/VirtualHostImplTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/impl/VirtualHostImplTest.java
new file mode 100644
index 0000000000..0cf70859e2
--- /dev/null
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/impl/VirtualHostImplTest.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.model.impl;
+
+import static org.apache.qpid.server.model.impl.AbstractConfiguredObject.EMPTY_ATTRIBUTE_MAP;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import java.util.UUID;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+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.State;
+import org.apache.qpid.server.model.VirtualHost;
+
+public class VirtualHostImplTest extends TestCase
+{
+ private VirtualHost _virtualHost;
+ private UUID _brokerUuid = UUID.randomUUID();
+ private ConfigurationChangeListener _childAddedRemovedListener = mock(ConfigurationChangeListener.class);
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ createVirtualHost();
+ }
+
+ public void testQueueChildAddedAndDeletedNotifications()
+ {
+ _virtualHost.addChangeListener(_childAddedRemovedListener);
+
+ Queue queue = _virtualHost.createQueue("queue", State.INITIALISING, true, false, LifetimePolicy.PERMANENT, 0, EMPTY_ATTRIBUTE_MAP);
+
+ verify(_childAddedRemovedListener).childAdded(_virtualHost, queue);
+ verifyNoMoreInteractions(_childAddedRemovedListener);
+
+ _virtualHost.deleteQueue(queue);
+
+ verify(_childAddedRemovedListener).childRemoved(_virtualHost, queue);
+ verifyNoMoreInteractions(_childAddedRemovedListener);
+ }
+
+ public void testExchangeChildAddedNotifications()
+ {
+ _virtualHost.addChangeListener(_childAddedRemovedListener);
+
+ Exchange exchange = _virtualHost.createExchange("exchange", State.INITIALISING, true, LifetimePolicy.PERMANENT, 0L, "direct", EMPTY_ATTRIBUTE_MAP);
+
+ verify(_childAddedRemovedListener).childAdded(_virtualHost, exchange);
+ verifyNoMoreInteractions(_childAddedRemovedListener);
+ }
+
+ public void testQueueDeletedTwiceDisallowed()
+ {
+ Queue queue = _virtualHost.createQueue("queue", State.INITIALISING, true, false, LifetimePolicy.PERMANENT, 0, EMPTY_ATTRIBUTE_MAP);
+
+ _virtualHost.deleteQueue(queue);
+
+ try
+ {
+ _virtualHost.deleteQueue(queue);
+ fail("Exception not thrown");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ // PASS
+ }
+ }
+
+ private void createVirtualHost()
+ {
+ Broker broker = new BrokerImpl(_brokerUuid,
+ "broker1",
+ State.INITIALISING,
+ true,
+ LifetimePolicy.PERMANENT,
+ 0l,
+ EMPTY_ATTRIBUTE_MAP);
+
+ _virtualHost = broker.createVirtualHost("vhost1", State.INITIALISING, true, LifetimePolicy.PERMANENT, 0, EMPTY_ATTRIBUTE_MAP);
+ }
+}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java
deleted file mode 100644
index fe9bcc57a6..0000000000
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.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.protocol;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-import org.apache.qpid.server.AMQChannel;
-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.store.MessageStore;
-import org.apache.qpid.server.store.TestableMemoryMessageStore;
-import org.apache.qpid.server.util.InternalBrokerBaseCase;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularData;
-
-
-/** Test class to test MBean operations for AMQMinaProtocolSession. */
-public class AMQProtocolSessionMBeanTest extends InternalBrokerBaseCase
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(AMQProtocolSessionMBeanTest.class);
-
- private MessageStore _messageStore = new TestableMemoryMessageStore();
- private AMQProtocolEngine _protocolSession;
- private AMQChannel _channel;
- private AMQProtocolSessionMBean _mbean;
-
- public void testChannels() throws Exception
- {
- // check the channel count is correct
- int channelCount = _mbean.channels().size();
- assertTrue(channelCount == 1);
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue_" + System.currentTimeMillis()),
- false,
- new AMQShortString("test"),
- true,
- false, _protocolSession.getVirtualHost(), null);
- AMQChannel channel = new AMQChannel(_protocolSession, 2, _messageStore);
- channel.setDefaultQueue(queue);
- _protocolSession.addChannel(channel);
- channelCount = _mbean.channels().size();
- assertTrue(channelCount == 2);
-
- // general properties test
- _protocolSession.setMaximumNumberOfChannels(1000L);
- assertTrue(_mbean.getMaximumNumberOfChannels() == 1000L);
-
- // check APIs
- AMQChannel channel3 = new AMQChannel(_protocolSession, 3, _messageStore);
- channel3.setLocalTransactional();
- _protocolSession.addChannel(channel3);
- _mbean.rollbackTransactions(2);
- _mbean.rollbackTransactions(3);
- _mbean.commitTransactions(2);
- _mbean.commitTransactions(3);
-
- // This should throw exception, because the channel does't exist
- try
- {
- _mbean.commitTransactions(4);
- fail();
- }
- catch (JMException ex)
- {
- log.debug("expected exception is thrown :" + ex.getMessage());
- }
-
- // check channels() return type conveys flow control blocking status correctly
- AMQChannel channel4 = new AMQChannel(_protocolSession, 4, _messageStore);
- _protocolSession.addChannel(channel4);
- channel4.setDefaultQueue(queue);
-
- final String blocking = ManagedConnection.FLOW_BLOCKED;
- TabularData channels = _mbean.channels();
- CompositeData chan4result = channels.get(new Integer[]{4});
- assertNotNull(chan4result);
- assertEquals("Flow should not have been blocked", false, chan4result.get(blocking));
-
- channel4.block(queue);
- channels = _mbean.channels();
- chan4result = channels.get(new Integer[]{4});
- assertNotNull(chan4result);
- assertEquals("Flow should have been blocked", true, chan4result.get(blocking));
-
- channel4.unblock(queue);
- channels = _mbean.channels();
- chan4result = channels.get(new Integer[]{4});
- assertNotNull(chan4result);
- assertEquals("Flow should have been unblocked", false, chan4result.get(blocking));
-
- // check if closing of session works
- _protocolSession.addChannel(new AMQChannel(_protocolSession, 5, _messageStore));
- _mbean.closeConnection();
- try
- {
- channelCount = _mbean.channels().size();
- assertTrue(channelCount == 0);
- // session is now closed so adding another channel should throw an exception
- _protocolSession.addChannel(new AMQChannel(_protocolSession, 6, _messageStore));
- fail();
- }
- catch (AMQException ex)
- {
- log.debug("expected exception is thrown :" + ex.getMessage());
- }
- }
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- VirtualHost vhost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test");
- _protocolSession = new InternalTestProtocolSession(vhost);
-
- _channel = new AMQChannel(_protocolSession, 1, _messageStore);
- _protocolSession.addChannel(_channel);
- _mbean = (AMQProtocolSessionMBean) _protocolSession.getManagedObject();
- }
-
-}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
deleted file mode 100644
index 25d35aab16..0000000000
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.message.AMQMessage;
-import org.apache.qpid.server.message.MessageMetaData;
-import org.apache.qpid.server.protocol.InternalTestProtocolSession;
-import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
-import org.apache.qpid.server.util.InternalBrokerBaseCase;
-
-import javax.management.Notification;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-
-/** This class tests all the alerts an AMQQueue can throw based on threshold values of different parameters */
-public class AMQQueueAlertTest extends InternalBrokerBaseCase
-{
- private final static long MAX_MESSAGE_COUNT = 50;
- private final static long MAX_MESSAGE_AGE = 250; // 0.25 sec
- private final static long MAX_MESSAGE_SIZE = 2000; // 2 KB
- private final static long MAX_QUEUE_DEPTH = 10000; // 10 KB
- private AMQQueueMBean _queueMBean;
- private static final SubscriptionFactoryImpl SUBSCRIPTION_FACTORY = SubscriptionFactoryImpl.INSTANCE;
-
- /**
- * Tests if the alert gets thrown when message count increases the threshold limit
- *
- * @throws Exception
- */
- public void testMessageCountAlert() throws Exception
- {
- setSession(new InternalTestProtocolSession(getVirtualHost()));
- AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore());
- getSession().addChannel(channel);
-
- setQueue(AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue1"), false, new AMQShortString("AMQueueAlertTest"),
- false, false,
- getVirtualHost(), null));
- _queueMBean = (AMQQueueMBean) getQueue().getManagedObject();
-
- _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
-
- sendMessages(channel, MAX_MESSAGE_COUNT, 256l);
- assertTrue(_queueMBean.getMessageCount() == MAX_MESSAGE_COUNT);
-
- Notification lastNotification = _queueMBean.getLastNotification();
- assertNotNull(lastNotification);
-
- String notificationMsg = lastNotification.getMessage();
- assertTrue(notificationMsg.startsWith(NotificationCheck.MESSAGE_COUNT_ALERT.name()));
- }
-
- /**
- * Tests if the Message Size alert gets thrown when message of higher than threshold limit is sent
- *
- * @throws Exception
- */
- public void testMessageSizeAlert() throws Exception
- {
- setSession(new InternalTestProtocolSession(getVirtualHost()));
- AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore());
- getSession().addChannel(channel);
-
- setQueue(AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue2"), false, new AMQShortString("AMQueueAlertTest"),
- false, false,
- getVirtualHost(), null));
- _queueMBean = (AMQQueueMBean) getQueue().getManagedObject();
- _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
- _queueMBean.setMaximumMessageSize(MAX_MESSAGE_SIZE);
-
- sendMessages(channel, 1, MAX_MESSAGE_SIZE * 2);
- assertTrue(_queueMBean.getMessageCount() == 1);
-
- Notification lastNotification = _queueMBean.getLastNotification();
- assertNotNull(lastNotification);
-
- String notificationMsg = lastNotification.getMessage();
- assertTrue(notificationMsg.startsWith(NotificationCheck.MESSAGE_SIZE_ALERT.name()));
- }
-
- /**
- * Tests if Queue Depth alert is thrown when queue depth reaches the threshold value
- *
- * Based on FT-402 subbmitted by client
- *
- * @throws Exception
- */
- public void testQueueDepthAlertNoSubscriber() throws Exception
- {
- setSession(new InternalTestProtocolSession(getVirtualHost()));
- AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore());
- getSession().addChannel(channel);
-
- setQueue(AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue3"), false, new AMQShortString("AMQueueAlertTest"),
- false, false,
- getVirtualHost(), null));
- _queueMBean = (AMQQueueMBean) getQueue().getManagedObject();
- _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
- _queueMBean.setMaximumQueueDepth(MAX_QUEUE_DEPTH);
-
- while (getQueue().getQueueDepth() < MAX_QUEUE_DEPTH)
- {
- sendMessages(channel, 1, MAX_MESSAGE_SIZE);
- }
-
- Notification lastNotification = _queueMBean.getLastNotification();
- assertNotNull(lastNotification);
-
- String notificationMsg = lastNotification.getMessage();
- assertTrue(notificationMsg.startsWith(NotificationCheck.QUEUE_DEPTH_ALERT.name()));
- }
-
- /**
- * Tests if MESSAGE AGE alert is thrown, when a message is in the queue for time higher than threshold value of
- * message age
- *
- * Alternative test to FT-401 provided by client
- *
- * @throws Exception
- */
- public void testMessageAgeAlert() throws Exception
- {
- setSession(new InternalTestProtocolSession(getVirtualHost()));
- AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore());
- getSession().addChannel(channel);
-
- setQueue(AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue4"), false, new AMQShortString("AMQueueAlertTest"),
- false, false,
- getVirtualHost(), null));
- _queueMBean = (AMQQueueMBean) getQueue().getManagedObject();
- _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
- _queueMBean.setMaximumMessageAge(MAX_MESSAGE_AGE);
-
- sendMessages(channel, 1, MAX_MESSAGE_SIZE);
-
- // Ensure message sits on queue long enough to age.
- Thread.sleep(MAX_MESSAGE_AGE * 2);
-
- Notification lastNotification = _queueMBean.getLastNotification();
- assertNotNull("Last notification was null", lastNotification);
-
- String notificationMsg = lastNotification.getMessage();
- assertTrue(notificationMsg.startsWith(NotificationCheck.MESSAGE_AGE_ALERT.name()));
- }
-
- /*
- This test sends some messages to the queue with subscribers needing message to be acknowledged.
- The messages will not be acknowledged and will be required twice. Why we are checking this is because
- the bug reported said that the queueDepth keeps increasing when messages are requeued.
- // TODO - queue depth now includes unacknowledged messages so does not go down when messages are delivered
-
- The QueueDepth should decrease when messages are delivered from the queue (QPID-408)
- */
- public void testQueueDepthAlertWithSubscribers() throws Exception
- {
- AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore());
- getSession().addChannel(channel);
-
- // Create queue
- setQueue(getNewQueue());
- Subscription subscription =
- SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), getSession(), new AMQShortString("consumer_tag"), true, null, false, channel.getCreditManager());
-
- getQueue().registerSubscription(
- subscription, false);
-
- _queueMBean = (AMQQueueMBean) getQueue().getManagedObject();
- _queueMBean.setMaximumMessageCount(9999l); // Set a high value, because this is not being tested
- _queueMBean.setMaximumQueueDepth(MAX_QUEUE_DEPTH);
-
- // Send messages(no of message to be little more than what can cause a Queue_Depth alert)
- int messageCount = Math.round(MAX_QUEUE_DEPTH / MAX_MESSAGE_SIZE) + 10;
- long totalSize = (messageCount * MAX_MESSAGE_SIZE);
- sendMessages(channel, messageCount, MAX_MESSAGE_SIZE);
-
- // Check queueDepth. There should be no messages on the queue and as the subscriber is listening
- // so there should be no Queue_Deoth alert raised
- assertEquals(new Long(totalSize), new Long(_queueMBean.getQueueDepth()));
- Notification lastNotification = _queueMBean.getLastNotification();
-// assertNull(lastNotification);
-
- // Kill the subscriber and check for the queue depth values.
- // Messages are unacknowledged, so those should get requeued. All messages should be on the Queue
- getQueue().unregisterSubscription(subscription);
- channel.requeue();
-
- assertEquals(new Long(totalSize), new Long(_queueMBean.getQueueDepth()));
-
- lastNotification = _queueMBean.getLastNotification();
- assertNotNull(lastNotification);
- String notificationMsg = lastNotification.getMessage();
- assertTrue(notificationMsg.startsWith(NotificationCheck.QUEUE_DEPTH_ALERT.name()));
-
- // Connect a consumer again and check QueueDepth values. The queue should get emptied.
- // Messages will get delivered but still are unacknowledged.
- Subscription subscription2 =
- SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), getSession(), new AMQShortString("consumer_tag"), true, null, false, channel.getCreditManager());
-
- getQueue().registerSubscription(
- subscription2, false);
-
- while (getQueue().getUndeliveredMessageCount()!= 0)
- {
- Thread.sleep(100);
- }
-// assertEquals(new Long(0), new Long(_queueMBean.getQueueDepth()));
-
- // Kill the subscriber again. Now those messages should get requeued again. Check if the queue depth
- // value is correct.
- getQueue().unregisterSubscription(subscription2);
- channel.requeue();
-
- assertEquals(new Long(totalSize), new Long(_queueMBean.getQueueDepth()));
- getSession().closeSession();
-
- // Check the clear queue
- _queueMBean.clearQueue();
- assertEquals(new Long(0), new Long(_queueMBean.getQueueDepth()));
- }
-
- protected IncomingMessage message(final boolean immediate, long size) throws AMQException
- {
- MessagePublishInfo publish = new MessagePublishInfo()
- {
-
- public AMQShortString getExchange()
- {
- return null;
- }
-
- public void setExchange(AMQShortString exchange)
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public boolean isImmediate()
- {
- return immediate;
- }
-
- public boolean isMandatory()
- {
- return false;
- }
-
- public AMQShortString getRoutingKey()
- {
- return null;
- }
- };
-
- ContentHeaderBody contentHeaderBody = new ContentHeaderBody();
- BasicContentHeaderProperties props = new BasicContentHeaderProperties();
- contentHeaderBody.setProperties(props);
- contentHeaderBody.setBodySize(size); // in bytes
- IncomingMessage message = new IncomingMessage(publish);
- message.setContentHeaderBody(contentHeaderBody);
-
- return message;
- }
-
- @Override
- protected void configure()
- {
- // Increase Alert Check period
- getConfiguration().setHousekeepingCheckPeriod(200);
- }
-
- private void sendMessages(AMQChannel channel, long messageCount, final long size) throws AMQException
- {
- IncomingMessage[] messages = new IncomingMessage[(int) messageCount];
- MessageMetaData[] metaData = new MessageMetaData[(int) messageCount];
- for (int i = 0; i < messages.length; i++)
- {
- messages[i] = message(false, size);
- ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
- qs.add(getQueue());
- metaData[i] = messages[i].headersReceived(System.currentTimeMillis());
- messages[i].setStoredMessage(getMessageStore().addMessage(metaData[i]));
-
- messages[i].enqueue(qs);
-
- }
-
- for (int i = 0; i < messageCount; i++)
- {
- ContentChunk contentChunk = new ContentChunk()
- {
- private byte[] _data = new byte[(int)size];
-
- public int getSize()
- {
- return (int) size;
- }
-
- public byte[] getData()
- {
- return _data;
- }
-
- public void reduceToFit()
- {
- }
- };
-
- messages[i].addContentBodyFrame(contentChunk);
- messages[i].getStoredMessage().addContent(0, ByteBuffer.wrap(contentChunk.getData()));
-
- getQueue().enqueue(new AMQMessage(messages[i].getStoredMessage()));
- }
- }
-
- private AMQQueue getNewQueue() throws AMQException
- {
- return AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue" + Math.random()),
- false,
- new AMQShortString("AMQueueAlertTest"),
- false,
- false, getVirtualHost(), null);
- }
-}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
deleted file mode 100644
index 89c14c40a0..0000000000
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
-import java.util.*;
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularData;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentBody;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.message.AMQMessage;
-import org.apache.qpid.server.message.MessageMetaData;
-import org.apache.qpid.server.protocol.InternalTestProtocolSession;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.store.TestableMemoryMessageStore;
-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.InternalBrokerBaseCase;
-
-/**
- * Test class to test AMQQueueMBean attributes and operations
- */
-public class AMQQueueMBeanTest extends InternalBrokerBaseCase
-{
- private static long MESSAGE_SIZE = 1000;
- private AMQQueueMBean _queueMBean;
- private static final SubscriptionFactoryImpl SUBSCRIPTION_FACTORY = SubscriptionFactoryImpl.INSTANCE;
-
- public void testMessageCountTransient() throws Exception
- {
- int messageCount = 10;
- sendMessages(messageCount, false);
- assertTrue(_queueMBean.getMessageCount() == messageCount);
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
- long queueDepth = (messageCount * MESSAGE_SIZE);
- assertTrue(_queueMBean.getQueueDepth() == queueDepth);
-
- _queueMBean.deleteMessageFromTop();
- assertTrue(_queueMBean.getMessageCount() == (messageCount - 1));
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
-
- _queueMBean.clearQueue();
- assertEquals(0,(int)_queueMBean.getMessageCount());
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
-
- //Ensure that the data has been removed from the Store
- verifyBrokerState();
- }
-
- public void testMessageCountPersistent() throws Exception
- {
- int messageCount = 10;
- sendMessages(messageCount, true);
- assertEquals("", messageCount, _queueMBean.getMessageCount().intValue());
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
- long queueDepth = (messageCount * MESSAGE_SIZE);
- assertTrue(_queueMBean.getQueueDepth() == queueDepth);
-
- _queueMBean.deleteMessageFromTop();
- assertTrue(_queueMBean.getMessageCount() == (messageCount - 1));
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
-
- _queueMBean.clearQueue();
- assertTrue(_queueMBean.getMessageCount() == 0);
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
-
- //Ensure that the data has been removed from the Store
- verifyBrokerState();
- }
-
- public void testDeleteMessages() throws Exception
- {
- int messageCount = 10;
- sendMessages(messageCount, true);
- assertEquals("", messageCount, _queueMBean.getMessageCount().intValue());
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
- long queueDepth = (messageCount * MESSAGE_SIZE);
- assertTrue(_queueMBean.getQueueDepth() == queueDepth);
-
- //delete first message
- _queueMBean.deleteMessages(1L,1L);
- assertTrue(_queueMBean.getMessageCount() == (messageCount - 1));
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
- try
- {
- _queueMBean.viewMessageContent(1L);
- fail("Message should no longer be on the queue");
- }
- catch(Exception e)
- {
-
- }
-
- //delete last message, leaving 2nd to 9th
- _queueMBean.deleteMessages(10L,10L);
- assertTrue(_queueMBean.getMessageCount() == (messageCount - 2));
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
- try
- {
- _queueMBean.viewMessageContent(10L);
- fail("Message should no longer be on the queue");
- }
- catch(Exception e)
- {
-
- }
-
- //delete remaining messages, leaving none
- _queueMBean.deleteMessages(2L,9L);
- assertTrue(_queueMBean.getMessageCount() == (0));
- assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
-
- //Ensure that the data has been removed from the Store
- verifyBrokerState();
- }
-
-
- // todo: collect to a general testing class -duplicated from Systest/MessageReturntest
- private void verifyBrokerState()
- {
-
- TestableMemoryMessageStore store = (TestableMemoryMessageStore) getVirtualHost().getMessageStore();
-
- // Unlike MessageReturnTest there is no need for a delay as there this thread does the clean up.
-
- assertEquals("Store should have no messages:" + store.getMessageCount(), 0, store.getMessageCount());
- }
-
- public void testConsumerCount() throws AMQException
- {
-
- assertTrue(getQueue().getActiveConsumerCount() == 0);
- assertTrue(_queueMBean.getActiveConsumerCount() == 0);
-
-
- InternalTestProtocolSession protocolSession = new InternalTestProtocolSession(getVirtualHost());
-
- AMQChannel channel = new AMQChannel(protocolSession, 1, getMessageStore());
- protocolSession.addChannel(channel);
-
- Subscription subscription =
- SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), protocolSession, new AMQShortString("test"), false, null, false, channel.getCreditManager());
-
- getQueue().registerSubscription(subscription, false);
- assertEquals(1,(int)_queueMBean.getActiveConsumerCount());
-
-
- SubscriptionFactory subscriptionFactory = SUBSCRIPTION_FACTORY;
- Subscription s1 = subscriptionFactory.createSubscription(channel.getChannelId(),
- protocolSession,
- new AMQShortString("S1"),
- false,
- null,
- true,
- channel.getCreditManager());
-
- Subscription s2 = subscriptionFactory.createSubscription(channel.getChannelId(),
- protocolSession,
- new AMQShortString("S2"),
- false,
- null,
- true,
- channel.getCreditManager());
- getQueue().registerSubscription(s1,false);
- getQueue().registerSubscription(s2,false);
- assertTrue(_queueMBean.getActiveConsumerCount() == 3);
- assertTrue(_queueMBean.getConsumerCount() == 3);
-
- s1.close();
- assertEquals(2, (int) _queueMBean.getActiveConsumerCount());
- assertTrue(_queueMBean.getConsumerCount() == 3);
- }
-
- public void testGeneralProperties() throws Exception
- {
- long maxQueueDepth = 1000; // in bytes
- _queueMBean.setMaximumMessageCount(50000l);
- _queueMBean.setMaximumMessageSize(2000l);
- _queueMBean.setMaximumQueueDepth(maxQueueDepth);
-
- assertEquals("Max MessageCount not set",50000,_queueMBean.getMaximumMessageCount().longValue());
- assertEquals("Max MessageSize not set",2000, _queueMBean.getMaximumMessageSize().longValue());
- assertEquals("Max QueueDepth not set",maxQueueDepth, _queueMBean.getMaximumQueueDepth().longValue());
-
- assertEquals("Queue Name does not match", new AMQShortString(getName()), _queueMBean.getName());
- assertFalse("AutoDelete should not be set.",_queueMBean.isAutoDelete());
- assertFalse("Queue should not be durable.",_queueMBean.isDurable());
-
- //set+get exclusivity using the mbean, and also verify it is actually updated in the queue
- _queueMBean.setExclusive(true);
- assertTrue("Exclusive property should be true.",_queueMBean.isExclusive());
- assertTrue("Exclusive property should be true.", getQueue().isExclusive());
- _queueMBean.setExclusive(false);
- assertFalse("Exclusive property should be false.",_queueMBean.isExclusive());
- assertFalse("Exclusive property should be false.", getQueue().isExclusive());
- }
-
- /**
- * Tests view messages with two test messages. The first message is non-persistent, the second persistent
- * and has timestamp/expiration.
- *
- */
- public void testViewMessages() throws Exception
- {
- sendMessages(1, false);
- final Date msg2Timestamp = new Date();
- final Date msg2Expiration = new Date(msg2Timestamp.getTime() + 1000);
- sendMessages(1, true, msg2Timestamp.getTime(), msg2Expiration.getTime());
-
- final TabularData tab = _queueMBean.viewMessages(1l, 2l);
- assertEquals("Unexpected number of rows in table", 2, tab.size());
- final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) tab.values().iterator();
-
- // Check row1
- final CompositeDataSupport row1 = rowItr.next();
- assertEquals("Message should have AMQ message id", 1l, row1.get(ManagedQueue.MSG_AMQ_ID));
- assertNotNull("Expected message header array", row1.get(ManagedQueue.MSG_HEADER));
- final Map<String, String> row1Headers = headerArrayToMap((String[])row1.get(ManagedQueue.MSG_HEADER));
- assertEquals("Unexpected JMSPriority within header", "Non_Persistent", row1Headers.get("JMSDeliveryMode"));
- assertEquals("Unexpected JMSTimestamp within header", "null", row1Headers.get("JMSTimestamp"));
- assertEquals("Unexpected JMSExpiration within header", "null", row1Headers.get("JMSExpiration"));
-
- final CompositeDataSupport row2 = rowItr.next();
- assertEquals("Message should have AMQ message id", 2l, row2.get(ManagedQueue.MSG_AMQ_ID));
- assertNotNull("Expected message header array", row2.get(ManagedQueue.MSG_HEADER));
- final Map<String, String> row2Headers = headerArrayToMap((String[])row2.get(ManagedQueue.MSG_HEADER));
- assertEquals("Unexpected JMSPriority within header", "Persistent", row2Headers.get("JMSDeliveryMode"));
- final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(AMQQueueMBean.JMSTIMESTAMP_DATETIME_FORMAT);
- assertEquals("Unexpected JMSTimestamp within header", msg2Timestamp,
- simpleDateFormat.parse(row2Headers.get("JMSTimestamp")));
- assertEquals("Unexpected JMSExpiration within header", msg2Expiration,
- simpleDateFormat.parse(row2Headers.get("JMSExpiration")));
- }
-
- public void testViewMessageWithIllegalStartEndRanges() throws Exception
- {
- try
- {
- _queueMBean.viewMessages(0L, 3L);
- fail();
- }
- catch (JMException ex)
- {
- // PASS
- }
-
- try
- {
- _queueMBean.viewMessages(2L, 1L);
- fail();
- }
- catch (JMException ex)
- {
- // PASS
- }
-
- try
- {
- _queueMBean.viewMessages(-1L, 1L);
- fail();
- }
- catch (JMException ex)
- {
- // PASS
- }
-
- try
- {
- long end = Integer.MAX_VALUE;
- end+=2;
- _queueMBean.viewMessages(1L, end);
- fail("Expected Exception due to oversized(> 2^31) message range");
- }
- catch (JMException ex)
- {
- // PASS
- }
- }
-
- public void testViewMessageContent() throws Exception
- {
- final List<AMQMessage> sentMessages = sendMessages(1, true);
- final Long id = sentMessages.get(0).getMessageId();
-
- final CompositeData messageData = _queueMBean.viewMessageContent(id);
- assertNotNull(messageData);
- }
-
- public void testViewMessageContentWithUnknownMessageId() throws Exception
- {
- final List<AMQMessage> sentMessages = sendMessages(1, true);
- final Long id = sentMessages.get(0).getMessageId();
-
- try
- {
- _queueMBean.viewMessageContent(id + 1);
- fail();
- }
- catch (JMException ex)
- {
- // PASS
- }
- }
-
- public void testFlowControlProperties() throws Exception
- {
- assertTrue(_queueMBean.getCapacity() == 0);
- assertTrue(_queueMBean.getFlowResumeCapacity() == 0);
- assertFalse(_queueMBean.isFlowOverfull());
-
- //capacity currently 0, try setting FlowResumeCapacity above this
- try
- {
- _queueMBean.setFlowResumeCapacity(1L);
- fail("Should have failed to allow setting FlowResumeCapacity above Capacity");
- }
- catch (IllegalArgumentException ex)
- {
- //expected exception
- assertTrue(_queueMBean.getFlowResumeCapacity() == 0);
- }
-
- //add a message to the queue
- sendMessages(1, true);
-
- //(FlowResume)Capacity currently 0, set both to 2
- _queueMBean.setCapacity(2L);
- assertTrue(_queueMBean.getCapacity() == 2L);
- _queueMBean.setFlowResumeCapacity(2L);
- assertTrue(_queueMBean.getFlowResumeCapacity() == 2L);
-
- //Try setting Capacity below FlowResumeCapacity
- try
- {
- _queueMBean.setCapacity(1L);
- fail("Should have failed to allow setting Capacity below FlowResumeCapacity");
- }
- catch (IllegalArgumentException ex)
- {
- //expected exception
- assertTrue(_queueMBean.getCapacity() == 2);
- }
-
- //create a channel and use it to exercise the capacity check mechanism
- AMQChannel channel = new AMQChannel(getSession(), 1, getMessageStore());
- getQueue().checkCapacity(channel);
-
- assertTrue(_queueMBean.isFlowOverfull());
- assertTrue(channel.getBlocking());
-
- //set FlowResumeCapacity to MESSAGE_SIZE and check queue is now underfull and channel unblocked
- _queueMBean.setCapacity(MESSAGE_SIZE);//must increase capacity too
- _queueMBean.setFlowResumeCapacity(MESSAGE_SIZE);
-
- assertFalse(_queueMBean.isFlowOverfull());
- assertFalse(channel.getBlocking());
- }
-
- public void testMaximumDeliveryCount() throws IOException
- {
- assertEquals("Unexpected default maximum delivery count", Integer.valueOf(0), _queueMBean.getMaximumDeliveryCount());
- }
-
- public void testViewAllMessages() throws Exception
- {
- final int messageCount = 5;
- sendPersistentMessages(messageCount);
-
-
- final TabularData messageTable = _queueMBean.viewMessages(1L, 5L);
- assertNotNull("Message table should not be null", messageTable);
- assertEquals("Unexpected number of rows", messageCount, messageTable.size());
-
-
- final Iterator rowIterator = messageTable.values().iterator();
- // Get its message ID
- final CompositeDataSupport row1 = (CompositeDataSupport) rowIterator.next();
- final Long msgId = (Long) row1.get("AMQ MessageId");
- final Long queuePosition = (Long) row1.get("Queue Position");
- final Integer deliveryCount = (Integer) row1.get("Delivery Count");
-
- assertNotNull("Row should have value for queue position", queuePosition);
- assertNotNull("Row should have value for msgid", msgId);
- assertNotNull("Row should have value for deliveryCount", deliveryCount);
- }
-
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- _queueMBean = new AMQQueueMBean(getQueue());
- }
-
- public void tearDown()
- {
- ApplicationRegistry.remove();
- }
-
- private void sendPersistentMessages(int messageCount) throws AMQException
- {
- sendMessages(messageCount, true);
- assertEquals("Expected " + messageCount + " messages in the queue", messageCount, _queueMBean
- .getMessageCount().intValue());
- }
-
- private List<AMQMessage> sendMessages(int messageCount, boolean persistent) throws AMQException
- {
- return sendMessages(messageCount, persistent, 0l, 0l);
- }
-
- private List<AMQMessage> sendMessages(int messageCount, boolean persistent, long timestamp, long expiration) throws AMQException
- {
- final List<AMQMessage> sentMessages = new ArrayList<AMQMessage>();
-
- for (int i = 0; i < messageCount; i++)
- {
- IncomingMessage currentMessage = createIncomingMessage(false, persistent, timestamp, expiration);
- ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
- qs.add(getQueue());
- currentMessage.enqueue(qs);
-
- // route header
- MessageMetaData mmd = currentMessage.headersReceived(System.currentTimeMillis());
-
- // Add the message to the store so we have something to test later
- currentMessage.setStoredMessage(getMessageStore().addMessage(mmd));
- ContentChunk chunk = getSession().getMethodRegistry()
- .getProtocolVersionMethodConverter()
- .convertToContentChunk(
- new ContentBody(new byte[(int) MESSAGE_SIZE]));
- currentMessage.addContentBodyFrame(chunk);
- currentMessage.getStoredMessage().addContent(0, ByteBuffer.wrap(chunk.getData()));
-
- AMQMessage m = new AMQMessage(currentMessage.getStoredMessage());
- for(BaseQueue q : currentMessage.getDestinationQueues())
- {
- q.enqueue(m);
- }
-
- sentMessages.add(m);
- }
-
- return sentMessages;
- }
-
- private IncomingMessage createIncomingMessage(final boolean immediate, boolean persistent, long timestamp, long expiration) throws AMQException
- {
- MessagePublishInfo publish = new MessagePublishInfo()
- {
-
- public AMQShortString getExchange()
- {
- return null;
- }
-
- public void setExchange(AMQShortString exchange)
- {
- }
-
- public boolean isImmediate()
- {
- return immediate;
- }
-
- public boolean isMandatory()
- {
- return false;
- }
-
- public AMQShortString getRoutingKey()
- {
- return null;
- }
- };
-
- ContentHeaderBody contentHeaderBody = new ContentHeaderBody();
- contentHeaderBody.setBodySize(MESSAGE_SIZE); // in bytes
- final BasicContentHeaderProperties props = new BasicContentHeaderProperties();
- contentHeaderBody.setProperties(props);
- props.setDeliveryMode((byte) (persistent ? 2 : 1));
- if (timestamp > 0)
- {
- props.setTimestamp(timestamp);
- }
- if (expiration > 0)
- {
- props.setExpiration(expiration);
- }
- IncomingMessage msg = new IncomingMessage(publish);
- msg.setContentHeaderBody(contentHeaderBody);
- return msg;
- }
-
- /**
- *
- * Utility method to convert array of Strings in the form x = y into a
- * map with key/value x =&gt; y.
- *
- */
- private Map<String,String> headerArrayToMap(final String[] headerArray)
- {
- final Map<String, String> headerMap = new HashMap<String, String>();
- final List<String> headerList = Arrays.asList(headerArray);
- for (Iterator<String> iterator = headerList.iterator(); iterator.hasNext();)
- {
- final String nameValuePair = iterator.next();
- final String[] nameValue = nameValuePair.split(" *= *", 2);
- headerMap.put(nameValue[0], nameValue[1]);
- }
- return headerMap;
- }
-
-
-}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
index afaa417415..c1c200c43e 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
@@ -29,13 +29,14 @@ import org.apache.qpid.server.configuration.QueueConfigType;
import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.security.AuthorizationHolder;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -51,7 +52,6 @@ public class MockAMQQueue implements AMQQueue
private AuthorizationHolder _authorizationHolder;
private AMQSessionModel _exclusiveOwner;
- private AMQShortString _owner;
private List<Binding> _bindings = new CopyOnWriteArrayList<Binding>();
private boolean _autoDelete;
@@ -98,7 +98,12 @@ public class MockAMQQueue implements AMQQueue
return "[MockAMQQueue]";
}
- };
+ };
+ }
+
+ public long getUnackedMessageBytes()
+ {
+ return 0;
}
public ConfigStore getConfigStore()
@@ -121,6 +126,16 @@ public class MockAMQQueue implements AMQQueue
return 0;
}
+ public long getTotalDequeueCount()
+ {
+ return 0;
+ }
+
+ public long getTotalEnqueueCount()
+ {
+ return 0;
+ }
+
public int getBindingCountHigh()
{
return 0;
@@ -219,12 +234,27 @@ public class MockAMQQueue implements AMQQueue
public void registerSubscription(Subscription subscription, boolean exclusive) throws AMQException
{
-
+
}
public void unregisterSubscription(Subscription subscription) throws AMQException
{
-
+
+ }
+
+ public Collection<Subscription> getConsumers()
+ {
+ return Collections.emptyList();
+ }
+
+ public void addSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener)
+ {
+
+ }
+
+ public void removeSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener)
+ {
+
}
public int getConsumerCount()
@@ -283,7 +313,7 @@ public class MockAMQQueue implements AMQQueue
}
public int delete() throws AMQException
- {
+ {
_deleted = true;
return getMessageCount();
}
@@ -358,17 +388,17 @@ public class MockAMQQueue implements AMQQueue
public void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName)
{
-
+
}
public void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName)
{
-
+
}
public void removeMessagesFromQueue(long fromMessageId, long toMessageId)
{
-
+
}
public long getMaximumMessageSize()
@@ -378,7 +408,7 @@ public class MockAMQQueue implements AMQQueue
public void setMaximumMessageSize(long value)
{
-
+
}
public long getMaximumMessageCount()
@@ -388,7 +418,7 @@ public class MockAMQQueue implements AMQQueue
public void setMaximumMessageCount(long value)
{
-
+
}
public long getMaximumQueueDepth()
@@ -398,7 +428,7 @@ public class MockAMQQueue implements AMQQueue
public void setMaximumQueueDepth(long value)
{
-
+
}
public long getMaximumMessageAge()
@@ -408,7 +438,7 @@ public class MockAMQQueue implements AMQQueue
public void setMaximumMessageAge(long maximumMessageAge)
{
-
+
}
public long getMinimumAlertRepeatGap()
@@ -418,7 +448,7 @@ public class MockAMQQueue implements AMQQueue
public void deleteMessageFromTop()
{
-
+
}
public long clearQueue()
@@ -429,7 +459,7 @@ public class MockAMQQueue implements AMQQueue
public void checkMessageStatus() throws AMQException
{
-
+
}
public Set<NotificationCheck> getNotificationChecks()
@@ -439,22 +469,22 @@ public class MockAMQQueue implements AMQQueue
public void flushSubscription(Subscription sub) throws AMQException
{
-
+
}
public void deliverAsync(Subscription sub)
{
-
+
}
public void deliverAsync()
{
-
+
}
public void stop()
{
-
+
}
public boolean isExclusive()
@@ -469,7 +499,7 @@ public class MockAMQQueue implements AMQQueue
public void setAlternateExchange(Exchange exchange)
{
-
+
}
public Map<String, Object> getArguments()
@@ -481,11 +511,6 @@ public class MockAMQQueue implements AMQQueue
{
}
- public ManagedObject getManagedObject()
- {
- return null;
- }
-
public int compareTo(AMQQueue o)
{
return 0;
@@ -503,7 +528,7 @@ public class MockAMQQueue implements AMQQueue
public void setCapacity(long capacity)
{
-
+
}
public long getFlowResumeCapacity()
@@ -513,7 +538,7 @@ public class MockAMQQueue implements AMQQueue
public void setFlowResumeCapacity(long flowResumeCapacity)
{
-
+
}
public void configure(ConfigurationPlugin config)
@@ -546,12 +571,6 @@ public class MockAMQQueue implements AMQQueue
_exclusiveOwner = exclusiveOwner;
}
-
- public String getResourceName()
- {
- return _name.toString();
- }
-
public boolean isOverfull()
{
return false;
@@ -582,7 +601,7 @@ public class MockAMQQueue implements AMQQueue
return 0;
}
- public void decrementUnackedMsgCount()
+ public void decrementUnackedMsgCount(QueueEntry queueEntry)
{
}
@@ -599,7 +618,6 @@ public class MockAMQQueue implements AMQQueue
public void setExclusive(boolean exclusive)
{
-
}
public int getMaximumDeliveryCount()
@@ -611,11 +629,23 @@ public class MockAMQQueue implements AMQQueue
{
}
- public void setAlternateExchange(String exchangeName)
+ public void visit(final QueueEntryVisitor visitor)
{
}
- public void visit(final Visitor visitor)
+ @Override
+ public void setNotificationListener(NotificationListener listener)
{
}
+
+ @Override
+ public void setDescription(String description)
+ {
+ }
+
+ @Override
+ public String getDescription()
+ {
+ return null;
+ }
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/NotificationCheckTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/NotificationCheckTest.java
new file mode 100644
index 0000000000..df2de7f0e0
--- /dev/null
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/NotificationCheckTest.java
@@ -0,0 +1,106 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.Matchers.contains;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import static org.apache.qpid.server.queue.NotificationCheck.MESSAGE_AGE_ALERT;
+import static org.apache.qpid.server.queue.NotificationCheck.MESSAGE_COUNT_ALERT;
+import static org.apache.qpid.server.queue.NotificationCheck.MESSAGE_SIZE_ALERT;
+import static org.apache.qpid.server.queue.NotificationCheck.QUEUE_DEPTH_ALERT;
+
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.queue.AMQQueue.NotificationListener;
+
+public class NotificationCheckTest extends TestCase
+{
+
+ private ServerMessage<?> _message = mock(ServerMessage.class);
+ private AMQQueue _queue = mock(AMQQueue.class);
+ private NotificationListener _listener = mock(NotificationListener.class);
+
+ public void testMessageCountAlertFires() throws Exception
+ {
+ when(_queue.getMaximumMessageCount()).thenReturn(1000l);
+ when(_queue.getMessageCount()).thenReturn(999, 1000, 1001);
+
+ MESSAGE_COUNT_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verifyZeroInteractions(_listener);
+
+ MESSAGE_COUNT_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verify(_listener).notifyClients(eq(MESSAGE_COUNT_ALERT), eq(_queue), eq("1000: Maximum count on queue threshold (1000) breached."));
+
+ MESSAGE_COUNT_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verify(_listener).notifyClients(eq(MESSAGE_COUNT_ALERT), eq(_queue), eq("1001: Maximum count on queue threshold (1000) breached."));
+ }
+
+ public void testMessageSizeAlertFires() throws Exception
+ {
+ when(_queue.getMaximumMessageSize()).thenReturn(1024l);
+ when(_message.getSize()).thenReturn(1023l, 1024l, 1025l);
+
+ MESSAGE_SIZE_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verifyZeroInteractions(_listener);
+
+ MESSAGE_SIZE_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verify(_listener).notifyClients(eq(MESSAGE_SIZE_ALERT), eq(_queue), contains("1024b : Maximum message size threshold (1024) breached."));
+
+ MESSAGE_SIZE_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verify(_listener).notifyClients(eq(MESSAGE_SIZE_ALERT), eq(_queue), contains("1025b : Maximum message size threshold (1024) breached."));
+ }
+
+ public void testMessageAgeAlertFires() throws Exception
+ {
+ long now = System.currentTimeMillis();
+ when(_queue.getMaximumMessageAge()).thenReturn(1000l);
+ when(_queue.getOldestMessageArrivalTime()).thenReturn(now, now - 15000);
+
+ MESSAGE_AGE_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verifyZeroInteractions(_listener);
+
+ MESSAGE_AGE_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ // Uses contains as first part of message is nondeterministic
+ verify(_listener).notifyClients(eq(MESSAGE_AGE_ALERT), eq(_queue), contains("s : Maximum age on queue threshold (1s) breached."));
+ }
+
+ public void testQueueDepthAlertFires() throws Exception
+ {
+ when(_queue.getMaximumQueueDepth()).thenReturn(1024l);
+ when(_queue.getQueueDepth()).thenReturn(1023l, 1024l, 2048l);
+
+ QUEUE_DEPTH_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verifyZeroInteractions(_listener);
+
+ QUEUE_DEPTH_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verify(_listener).notifyClients(eq(QUEUE_DEPTH_ALERT), eq(_queue), eq("1Kb : Maximum queue depth threshold (1Kb) breached."));
+
+ QUEUE_DEPTH_ALERT.notifyIfNecessary(_message, _queue, _listener);
+ verify(_listener).notifyClients(eq(QUEUE_DEPTH_ALERT), eq(_queue), eq("2Kb : Maximum queue depth threshold (1Kb) breached."));
+ }
+}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
index a8fad96063..3048ca3803 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
@@ -21,6 +21,13 @@
package org.apache.qpid.server.queue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+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;
@@ -79,7 +86,6 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
public void setExchange(AMQShortString exchange)
{
- //To change body of implemented methods use File | Settings | File Templates.
}
public boolean isImmediate()
@@ -1096,7 +1102,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
/**
* Tests that entry in dequeued state are not enqueued and not delivered to subscription
*/
- public void testEqueueDequeuedEntry()
+ public void testEnqueueDequeuedEntry()
{
// create a queue where each even entry is considered a dequeued
SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), new AMQShortString("test"), false,
@@ -1231,6 +1237,39 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount());
}
+ public void testNotificationFiredOnEnqueue() throws Exception
+ {
+ AMQQueue.NotificationListener listener = mock(AMQQueue.NotificationListener.class);
+
+ _queue.setNotificationListener(listener);
+ _queue.setMaximumMessageCount(2);
+
+ _queue.enqueue(createMessage(new Long(24)));
+ verifyZeroInteractions(listener);
+
+ _queue.enqueue(createMessage(new Long(25)));
+
+ verify(listener, atLeastOnce()).notifyClients(eq(NotificationCheck.MESSAGE_COUNT_ALERT), eq(_queue), contains("Maximum count on queue threshold"));
+ }
+
+ public void testNotificationFiredAsync() throws Exception
+ {
+ AMQQueue.NotificationListener listener = mock(AMQQueue.NotificationListener.class);
+
+ _queue.enqueue(createMessage(new Long(24)));
+ _queue.enqueue(createMessage(new Long(25)));
+ _queue.enqueue(createMessage(new Long(26)));
+
+ _queue.setNotificationListener(listener);
+ _queue.setMaximumMessageCount(2);
+
+ verifyZeroInteractions(listener);
+
+ _queue.checkMessageStatus();
+
+ verify(listener, atLeastOnce()).notifyClients(eq(NotificationCheck.MESSAGE_COUNT_ALERT), eq(_queue), contains("Maximum count on queue threshold"));
+ }
+
/**
* A helper method to create a queue with given name
*
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
index f6675e917e..c0c55de92a 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
@@ -32,6 +32,7 @@ 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;
/**
@@ -47,7 +48,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
protected void setUp() throws Exception
{
- _rmipa = new RMIPasswordAuthenticator();
+ _rmipa = new RMIPasswordAuthenticator(new InetSocketAddress(5672));
_credentials = new String[] {USERNAME, PASSWORD};
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java
index 48e631a0f4..8ab32d9710 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java
@@ -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.
+ *
+ */
package org.apache.qpid.server.store;
import static org.mockito.Matchers.any;
@@ -78,7 +98,7 @@ public class DurableConfigurationStoreTest extends QpidTestCase
_exchangeId = UUIDGenerator.generateUUID();
_storeName = getName();
- _storePath = TMP_FOLDER + "/" + _storeName;
+ _storePath = TMP_FOLDER + File.separator + _storeName;
FileUtils.delete(new File(_storePath), true);
setTestSystemProperty("QPID_WORK", TMP_FOLDER);
_configuration = mock(Configuration.class);
@@ -172,7 +192,7 @@ public class DurableConfigurationStoreTest extends QpidTestCase
_store.createQueue(queue);
reopenStore();
- verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, null);
+ verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, null, null);
}
public void testCreateQueueAMQQueueFieldTable() throws Exception
@@ -186,10 +206,29 @@ public class DurableConfigurationStoreTest extends QpidTestCase
_store.createQueue(queue, arguments);
reopenStore();
- verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, arguments);
+ verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, arguments, null);
}
- public void testUpdateQueue() throws Exception
+ public void testCreateQueueAMQQueueWithAlternateExchange() throws Exception
+ {
+ Exchange alternateExchange = createTestAlternateExchange();
+
+ AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true, alternateExchange);
+ _store.createQueue(queue);
+
+ reopenStore();
+ verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, null, alternateExchange.getId());
+ }
+
+ private Exchange createTestAlternateExchange()
+ {
+ UUID exchUuid = UUID.randomUUID();
+ Exchange alternateExchange = mock(Exchange.class);
+ when(alternateExchange.getId()).thenReturn(exchUuid);
+ return alternateExchange;
+ }
+
+ public void testUpdateQueueExclusivity() throws Exception
{
// create queue
AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true);
@@ -204,7 +243,26 @@ public class DurableConfigurationStoreTest extends QpidTestCase
_store.updateQueue(queue);
reopenStore();
- verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", false, arguments);
+ verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", false, arguments, null);
+ }
+
+ public void testUpdateQueueAlternateExchange() throws Exception
+ {
+ // create queue
+ AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true);
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put("x-qpid-dlq-enabled", Boolean.TRUE);
+ attributes.put("x-qpid-maximum-delivery-count", new Integer(10));
+ FieldTable arguments = FieldTable.convertToFieldTable(attributes);
+ _store.createQueue(queue, arguments);
+
+ // update the queue to have exclusive=false
+ Exchange alternateExchange = createTestAlternateExchange();
+ queue = createTestQueue(getName(), getName() + "Owner", false, alternateExchange);
+ _store.updateQueue(queue);
+
+ reopenStore();
+ verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", false, arguments, alternateExchange.getId());
}
public void testRemoveQueue() throws Exception
@@ -221,17 +279,23 @@ public class DurableConfigurationStoreTest extends QpidTestCase
_store.removeQueue(queue);
reopenStore();
verify(_queueRecoveryHandler, never()).queue(any(UUID.class), anyString(), anyString(), anyBoolean(),
- any(FieldTable.class));
+ any(FieldTable.class), any(UUID.class));
}
private AMQQueue createTestQueue(String queueName, String queueOwner, boolean exclusive) throws AMQStoreException
{
+ return createTestQueue(queueName, queueOwner, exclusive, null);
+ }
+
+ private AMQQueue createTestQueue(String queueName, String queueOwner, boolean exclusive, Exchange alternateExchange) throws AMQStoreException
+ {
AMQQueue queue = mock(AMQQueue.class);
when(queue.getName()).thenReturn(queueName);
when(queue.getNameShortString()).thenReturn(AMQShortString.valueOf(queueName));
when(queue.getOwner()).thenReturn(AMQShortString.valueOf(queueOwner));
when(queue.isExclusive()).thenReturn(exclusive);
when(queue.getId()).thenReturn(_queueId);
+ when(queue.getAlternateExchange()).thenReturn(alternateExchange);
return queue;
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
index 64048d294b..93f3701c85 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
@@ -99,7 +99,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase
{
super.setUp();
- String storePath = System.getProperty("QPID_WORK") + "/" + getName();
+ String storePath = System.getProperty("QPID_WORK") + File.separator + getName();
_config = new PropertiesConfiguration();
_config.addProperty("store.class", getTestProfileMessageStoreClassName());
@@ -267,15 +267,9 @@ public class MessageStoreTest extends InternalBrokerBaseCase
//Validate normally expected properties of Queues/Topics
validateDurableQueueProperties();
- //Update the durable exclusive queue's exclusivity and verify it is persisted and recovered correctly
+ //Update the durable exclusive queue's exclusivity
setQueueExclusivity(false);
validateQueueExclusivityProperty(false);
-
- //Reload the Virtualhost to recover the queues again
- reloadVirtualHost();
-
- //verify the change was persisted and recovered correctly
- validateQueueExclusivityProperty(false);
}
/**
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java
index c6ef35d255..24e8b591e0 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java
@@ -147,6 +147,12 @@ public class OperationalLoggingListenerTest extends TestCase
{
_eventManager.addEventListener(eventListener, events);
}
+
+ @Override
+ public String getStoreType()
+ {
+ return "TEST";
+ }
}
private static class TestActor implements LogActor
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java
index 5ba9c0c015..0aa0569b07 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java
@@ -1,5 +1,3 @@
-package org.apache.qpid.server.subscription;
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,16 +19,24 @@ package org.apache.qpid.server.subscription;
*
*/
+package org.apache.qpid.server.subscription;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.message.InboundMessage;
+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.QueueEntry;
import org.apache.qpid.server.queue.QueueEntry.SubscriptionAcquiredState;
+import org.apache.qpid.server.stats.StatisticsCounter;
import java.util.ArrayList;
import java.util.List;
+import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -76,19 +82,9 @@ public class MockSubscription implements Subscription
_state = State.CLOSED;
}
- public boolean filtersMessages()
- {
- return false;
- }
-
- public AMQChannel getChannel()
- {
- return null;
- }
-
- public AMQShortString getConsumerTag()
+ public String getConsumerName()
{
- return tag;
+ return tag == null ? null : tag.asString();
}
public long getSubscriptionID()
@@ -121,11 +117,36 @@ public class MockSubscription implements Subscription
return false;
}
+ public long getBytesOut()
+ {
+ return 0; // TODO - Implement
+ }
+
+ public long getMessagesOut()
+ {
+ return 0; // TODO - Implement
+ }
+
+ public long getUnacknowledgedBytes()
+ {
+ return 0; // TODO - Implement
+ }
+
+ public long getUnacknowledgedMessages()
+ {
+ return 0; // TODO - Implement
+ }
+
public AMQQueue getQueue()
{
return queue;
}
+ public AMQSessionModel getSessionModel()
+ {
+ return new MockSessionModel();
+ }
+
public boolean trySendLock()
{
return _stateChangeLock.tryLock();
@@ -154,11 +175,6 @@ public class MockSubscription implements Subscription
return _isActive ;
}
- public void confirmAutoClose()
- {
-
- }
-
public void set(String key, Object value)
{
}
@@ -173,11 +189,6 @@ public class MockSubscription implements Subscription
return false;
}
- public boolean isBrowser()
- {
- return false;
- }
-
public boolean isClosed()
{
return _closed;
@@ -207,10 +218,6 @@ public class MockSubscription implements Subscription
_stateChangeLock.unlock();
}
- public void resend(QueueEntry entry) throws AMQException
- {
- }
-
public void onDequeue(QueueEntry queueEntry)
{
}
@@ -232,7 +239,6 @@ public class MockSubscription implements Subscription
messages.add(entry);
}
- @Override
public void flushBatched()
{
@@ -249,7 +255,7 @@ public class MockSubscription implements Subscription
}
public void setNoLocal(boolean noLocal)
- {
+ {
}
public void setStateListener(StateListener listener)
@@ -285,4 +291,259 @@ public class MockSubscription implements Subscription
{
_isActive = isActive;
}
+
+ private static class MockSessionModel implements AMQSessionModel
+ {
+
+ @Override
+ public int compareTo(AMQSessionModel o)
+ {
+ return 0;
+ }
+
+ @Override
+ public UUID getId()
+ {
+ return null;
+ }
+
+ @Override
+ public AMQConnectionModel getConnectionModel()
+ {
+ return new MockConnectionModel();
+ }
+
+ @Override
+ public String getClientID()
+ {
+ return null;
+ }
+
+ @Override
+ public void close() throws AMQException
+ {
+ }
+
+ @Override
+ public LogSubject getLogSubject()
+ {
+ return null;
+ }
+
+ @Override
+ public void checkTransactionStatus(long openWarn, long openClose,
+ long idleWarn, long idleClose) throws AMQException
+ {
+ }
+
+ @Override
+ public void block(AMQQueue queue)
+ {
+ }
+
+ @Override
+ public void unblock(AMQQueue queue)
+ {
+ }
+
+ @Override
+ public void block()
+ {
+ }
+
+ @Override
+ public void unblock()
+ {
+ }
+
+ @Override
+ public boolean getBlocking()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean onSameConnection(InboundMessage inbound)
+ {
+ return false;
+ }
+
+ @Override
+ public int getUnacknowledgedMessageCount()
+ {
+ return 0;
+ }
+
+ @Override
+ public Long getTxnCount()
+ {
+ return null;
+ }
+
+ @Override
+ public Long getTxnStart()
+ {
+ return null;
+ }
+
+ @Override
+ public Long getTxnCommits()
+ {
+ return null;
+ }
+
+ @Override
+ public Long getTxnRejects()
+ {
+ return null;
+ }
+
+ @Override
+ public int getChannelId()
+ {
+ return 0;
+ }
+ }
+
+ private static class MockConnectionModel implements AMQConnectionModel
+ {
+ @Override
+ public void initialiseStatistics()
+ {
+ }
+
+ @Override
+ public void registerMessageReceived(long messageSize, long timestamp)
+ {
+ }
+
+ @Override
+ public void registerMessageDelivered(long messageSize)
+ {
+ }
+
+ @Override
+ public StatisticsCounter getMessageDeliveryStatistics()
+ {
+ return null;
+ }
+
+ @Override
+ public StatisticsCounter getMessageReceiptStatistics()
+ {
+ return null;
+ }
+
+ @Override
+ public StatisticsCounter getDataDeliveryStatistics()
+ {
+ return null;
+ }
+
+ @Override
+ public StatisticsCounter getDataReceiptStatistics()
+ {
+ return null;
+ }
+
+ @Override
+ public void resetStatistics()
+ {
+
+ }
+
+ @Override
+ public UUID getId()
+ {
+ return null;
+ }
+
+ @Override
+ public void close(AMQConstant cause, String message)
+ throws AMQException
+ {
+ }
+
+ @Override
+ public void closeSession(AMQSessionModel session, AMQConstant cause,
+ String message) throws AMQException
+ {
+ }
+
+ @Override
+ public long getConnectionId()
+ {
+ return 0;
+ }
+
+ @Override
+ public List<AMQSessionModel> getSessionModels()
+ {
+ return null;
+ }
+
+ @Override
+ public void block()
+ {
+ }
+
+ @Override
+ public void unblock()
+ {
+ }
+
+ @Override
+ public LogSubject getLogSubject()
+ {
+ return null;
+ }
+
+ @Override
+ public String getUserName()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isSessionNameUnique(byte[] name)
+ {
+ return false;
+ }
+
+ @Override
+ public String getRemoteAddressString()
+ {
+ return "remoteAddress:1234";
+ }
+
+ @Override
+ public String getClientId()
+ {
+ return null;
+ }
+
+ @Override
+ public String getClientVersion()
+ {
+ return null;
+ }
+
+ @Override
+ public String getPrincipalAsString()
+ {
+ return null;
+ }
+
+ @Override
+ public long getSessionCountLimit()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getLastIoTime()
+ {
+ return 0;
+ }
+ }
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/transport/ServerConnectionMBeanTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/transport/ServerConnectionMBeanTest.java
deleted file mode 100644
index b0b81355ac..0000000000
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/transport/ServerConnectionMBeanTest.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * 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.management.common.mbeans.ManagedConnection;
-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.virtualhost.VirtualHost;
-import org.apache.qpid.transport.Binary;
-import org.apache.qpid.transport.Connection;
-import org.apache.qpid.transport.Session;
-
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularData;
-import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicLong;
-
-public class ServerConnectionMBeanTest extends InternalBrokerBaseCase
-{
- private ServerConnection _serverConnection;
- private ServerSessionMock _serverSession;
- private ServerConnectionMBean _mbean;
- private List<Session> _sessions = new ArrayList<Session>();
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- final VirtualHost vhost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test");
- _serverConnection = new ServerConnection(1)
- {
- protected Collection<Session> getChannels()
- {
- return _sessions;
- }
- public Session getSession(int channelId)
- {
- for(Session session : _sessions)
- {
- if (session.getChannel() == channelId)
- {
- return session;
- }
- }
- return null;
- }
- @Override
- public AtomicLong getLastIoTime()
- {
- return new AtomicLong(1);
- }
- };
- final MockConnectionConfig config = new MockConnectionConfig(UUID.randomUUID(), null, null,
- false, 1, vhost, "address", Boolean.TRUE, Boolean.TRUE, Boolean.TRUE,
- "authid", "remoteProcessName", new Integer(1967), new Integer(1970), vhost.getConfigStore(), Boolean.FALSE);
- _serverConnection.setConnectionConfig(config);
- _serverConnection.setVirtualHost(vhost);
- _serverConnection.setConnectionDelegate(new ServerConnectionDelegate(getRegistry(), "", getRegistry().getAuthenticationManager(new InetSocketAddress(5672))));
- _serverSession = new ServerSessionMock(_serverConnection, 1);
- _mbean = (ServerConnectionMBean) _serverConnection.getManagedObject();
- }
-
- public void testChannels() throws Exception
- {
- // check the channel count is correct
- TabularData tabularData = _mbean.channels();
-
- int channelCount = tabularData.size();
- assertEquals("Unexpected number of channels",1,channelCount);
- _sessions.add(new ServerSession(_serverConnection, new ServerSessionDelegate(),
- new Binary(getName().getBytes()), 2 , _serverConnection.getConfig()));
-
- channelCount = _mbean.channels().size();
- assertEquals("Unexpected number of channels",2,channelCount);
-
- final CompositeData chanresult = tabularData.get(new Integer[]{1});
- assertNotNull(chanresult);
- assertEquals("Unexpected channel id", new Integer(1),(Integer)chanresult.get(ManagedConnection.CHAN_ID));
- assertNull("Unexpected default queue", chanresult.get(ManagedConnection.DEFAULT_QUEUE));
- assertFalse("Unexpected transactional flag", (Boolean)chanresult.get(ManagedConnection.TRANSACTIONAL));
- assertFalse("Flow should have been blocked", (Boolean)chanresult.get(ManagedConnection.FLOW_BLOCKED));
- assertEquals("Unexpected unack'd count", new Integer(1967), (Integer)chanresult.get(ManagedConnection.UNACKED_COUNT));
- }
-
- public void testMaxChannels() throws Exception
- {
- _serverConnection.getConnectionDelegate().setChannelMax(10001);
- assertEquals("Max channels not got correctly", new Long(10001), _mbean.getMaximumNumberOfChannels());
- }
-
- public void testRollback() throws Exception
- {
- _mbean.rollbackTransactions(1);
- assertFalse("Rollback performed despite not being transacted", _serverSession.isRolledback());
-
- _serverSession.setTransactional(true);
- _mbean.rollbackTransactions(1);
- assertTrue("Rollback not performed", _serverSession.isRolledback());
-
- try
- {
- _mbean.rollbackTransactions(2);
- fail("Exception expected");
- }
- catch (JMException jme)
- {
- //pass
- }
- }
-
- public void testCommit() throws Exception
- {
- _mbean.commitTransactions(1);
- assertFalse("Commit performed despite not being transacted", _serverSession.isCommitted());
-
- _serverSession.setTransactional(true);
- _mbean.commitTransactions(1);
- assertTrue("Commit not performed", _serverSession.isCommitted());
-
- try
- {
- _mbean.commitTransactions(2);
- fail("Exception expected");
- }
- catch (JMException jme)
- {
- //pass
- }
- }
-
- public void testGetName()
- {
- assertEquals("Unexpected Object Instance Name", "\"address\"", _mbean.getObjectInstanceName());
- }
-
- public void testEnableStatistics()
- {
- assertFalse("Unexpected statistics enable flag", _mbean.isStatisticsEnabled());
- _mbean.setStatisticsEnabled(true);
- assertTrue("Unexpected statistics enable flag", _mbean.isStatisticsEnabled());
- }
-
- public void testLastIOTime()
- {
- assertEquals("Unexpected last IO time", new Date(1), _mbean.getLastIoTime());
- }
-
- private class ServerSessionMock extends ServerSession
- {
- private int _channelId = 0;
- private boolean _committed = false;
- private boolean _rolledback = false;
- private boolean _transacted = false;
-
- ServerSessionMock(Connection connection, int channelId)
- {
- super(connection, new ServerSessionDelegate(), new Binary(String.valueOf(channelId).getBytes()), 1 , _serverConnection.getConfig());
- _channelId = channelId;
- _sessions.add(this);
- }
-
- public int getChannel()
- {
- return _channelId;
- }
-
- @Override
- public void commit()
- {
- _committed = true;
- }
-
- @Override
- public void rollback()
- {
- _rolledback = true;
- }
-
- public boolean isCommitted()
- {
- return _committed;
- }
-
- public boolean isRolledback()
- {
- return _rolledback;
- }
-
- @Override
- public int getUnacknowledgedMessageCount()
- {
- return 1967;
- }
-
- public boolean isTransactional()
- {
- return _transacted;
- }
-
- public void setTransactional(boolean transacted)
- {
- _transacted = transacted;
- }
- }
-}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
index af49238998..0221f3d509 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
@@ -124,6 +124,12 @@ class MockStoreTransaction implements Transaction
storeTransaction.setState(TransactionState.STARTED);
return storeTransaction;
}
+
+ @Override
+ public String getStoreType()
+ {
+ return "TEST";
+ }
};
}
} \ No newline at end of file
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java
index 9bd69e3889..a64ab620ab 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java
@@ -21,6 +21,8 @@
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;
@@ -101,6 +103,17 @@ public class TestApplicationRegistry extends ApplicationRegistry
{
return pdam;
}
+
+ @Override
+ public Map<String, AuthenticationManager> getAvailableAuthenticationManagers()
+ {
+ return Collections.singletonMap(pdam.getClass().getName(), pdam);
+ }
+
+ @Override
+ public void addRegistryChangeListener(RegistryChangeListener listener)
+ {
+ }
};
}
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
index 58c7625ad6..df31845798 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
@@ -32,7 +32,6 @@ 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.management.ManagedObject;
import org.apache.qpid.server.protocol.v1_0.LinkRegistry;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
@@ -141,11 +140,6 @@ public class MockVirtualHost implements VirtualHost
return 0;
}
- public ManagedObject getManagedObject()
- {
- return null;
- }
-
public MessageStore getMessageStore()
{
return null;
@@ -257,11 +251,6 @@ public class MockVirtualHost implements VirtualHost
}
- public boolean isStatisticsEnabled()
- {
- return false;
- }
-
public void registerMessageDelivered(long messageSize)
{
@@ -277,11 +266,6 @@ public class MockVirtualHost implements VirtualHost
}
- public void setStatisticsEnabled(boolean enabled)
- {
-
- }
-
public State getState()
{
return State.ACTIVE;
diff --git a/qpid/java/build.deps b/qpid/java/build.deps
index 5b0d23f8cc..45e1f80ef8 100644
--- a/qpid/java/build.deps
+++ b/qpid/java/build.deps
@@ -34,6 +34,7 @@ geronimo-jta=lib/required/geronimo-jta_1.1_spec-1.1.1.jar
geronimo-kernel=lib/required/geronimo-kernel-2.2.1.jar
geronimo-openejb=lib/required/geronimo-ejb_3.0_spec-1.0.1.jar
geronimo-servlet=lib/required/geronimo-servlet_2.5_spec-1.2.jar
+#servlet-api=lib/required/geronimo-servlet_3.0_spec-1.0.jar
junit=lib/required/junit-3.8.1.jar
mockito-all=lib/required/mockito-all-1.9.0.jar
@@ -47,6 +48,18 @@ slf4j-log4j=lib/required/slf4j-log4j12-1.6.4.jar
xalan=lib/required/xalan-2.7.0.jar
+jetty=lib/required/jetty-server-7.6.3.v20120416.jar
+jetty-continuation=lib/required/jetty-continuation-7.6.3.v20120416.jar
+jetty-security=lib/required/jetty-security-7.6.3.v20120416.jar
+jetty-util=lib/required/jetty-util-7.6.3.v20120416.jar
+jetty-io=lib/required/jetty-io-7.6.3.v20120416.jar
+jetty-http=lib/required/jetty-http-7.6.3.v20120416.jar
+jetty-servlet=lib/required/jetty-servlet-7.6.3.v20120416.jar
+jetty-websocket=lib/required/jetty-websocket-7.6.3.v20120416.jar
+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}
@@ -65,8 +78,9 @@ 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} \
- ${jackson-core} ${jackson-mapper}
+ ${jackson-core} ${jackson-mapper} ${jetty} ${jetty-continuation} ${jetty-security} ${jetty-http} ${jetty-io} ${jetty-servlet} ${jetty-util} ${servlet-api} ${jetty-websocket}
+broker-plugins-management.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}
test.libs=${slf4j-log4j} ${log4j} ${junit} ${slf4j-api} ${mockito-all}
@@ -154,6 +168,9 @@ bdb-je=lib/bdbstore/je-5.0.55.jar
bdbstore.libs=${bdb-je}
bdbstore.test.libs=${test.libs}
+bdbstore-jmx.libs=${bdb-je}
+bdbstore-jmx.test.libs=${test.libs}
+
# optional perftests-visualisation-jfc module deps
jfreechart.jar=lib/jfree/jfreechart-1.0.13.jar
jcommon.jar=lib/jfree/jcommon-1.0.16.jar
@@ -161,6 +178,9 @@ csvjdbc.jar=lib/csvjdbc/csvjdbc-1.0.8.jar
perftests-visualisation-jfc.libs=${jfreechart.jar} ${jcommon.jar} ${csvjdbc.jar}
perftests-visualisation-jfc.test.libs=${test.libs}
+#optional qpid-web module deps
+broker-web.libs=${servlet-api}
+
# Libraries used only within the build
bnd=lib/required/bnd-0.0.384.jar
jython=lib/required/jython-standalone-2.5.2.jar
diff --git a/qpid/java/build.xml b/qpid/java/build.xml
index 5ac4b03a03..789d61d3fb 100644
--- a/qpid/java/build.xml
+++ b/qpid/java/build.xml
@@ -27,7 +27,7 @@
<findSubProjects name="management" dir="management" excludes="common,example"/>
<property name="optional" value="false"/>
- <property name="modules.opt.default" value="bdbstore perftests/visualisation-jfc"/>
+ <property name="modules.opt.default" value="bdbstore bdbstore/jmx perftests/visualisation-jfc broker-web"/>
<condition property="modules.opt" value="" else="${modules.opt.default}">
<isfalse value="${optional}"/>
</condition>
diff --git a/qpid/java/common.xml b/qpid/java/common.xml
index ab71642053..b5ae5679d0 100644
--- a/qpid/java/common.xml
+++ b/qpid/java/common.xml
@@ -277,8 +277,8 @@
<!-- targets for downloading ivy and retrieving dependencies -->
<target name="retrieve-dependencies" depends="load-ivy, configure-ivy, retrieve-optional-dependencies" unless="${ivy.dont.retrieve}">
<echo message="Resolving and retrieving dependencies..."/>
- <ivy:resolve type="jar,bundle" file="${project.root}/ivy.retrieve.xml" conf="required"/>
- <ivy:retrieve type="jar,bundle" conf="required" sync="true"
+ <ivy:resolve type="jar,bundle,war" file="${project.root}/ivy.retrieve.xml" conf="required"/>
+ <ivy:retrieve type="jar,bundle,war" conf="required" sync="true"
pattern="${project.root}/lib/required/[artifact]-[revision].[ext]" />
</target>
diff --git a/qpid/java/ivy.retrieve.xml b/qpid/java/ivy.retrieve.xml
index 8e2806a509..161c134c38 100644
--- a/qpid/java/ivy.retrieve.xml
+++ b/qpid/java/ivy.retrieve.xml
@@ -48,6 +48,7 @@
<dependency org="org.apache.geronimo.specs" name="geronimo-jms_1.1_spec" rev="1.0" transitive="false"/>
<dependency org="org.apache.geronimo.specs" name="geronimo-jta_1.1_spec" rev="1.1.1" transitive="false"/>
<dependency org="org.apache.geronimo.specs" name="geronimo-servlet_2.5_spec" rev="1.2" transitive="false"/>
+ <dependency org="org.apache.geronimo.specs" name="geronimo-servlet_3.0_spec" rev="1.0" transitive="false"/>
<dependency org="com.google.code.gson" name="gson" rev="2.0" transitive="false"/>
<dependency org="org.codehaus.jackson" name="jackson-core-asl" rev="1.9.0" transitive="false"/>
<dependency org="org.codehaus.jackson" name="jackson-mapper-asl" rev="1.9.0" transitive="false"/>
@@ -60,6 +61,15 @@
<dependency org="org.apache.felix" name="org.apache.felix.main" rev="2.0.5" transitive="false"/>
<dependency org="org.slf4j" name="slf4j-api" rev="1.6.4" transitive="false"/>
<dependency org="org.slf4j" name="slf4j-log4j12" rev="1.6.4" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-server" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-websocket" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-continuation" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-io" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-http" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-security" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-servlet" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-util" rev="7.6.3.v20120416" transitive="false"/>
+ <dependency org="org.dojotoolkit" name="dojo-war" rev="1.7.2" transitive="false"/>
<dependency org="xalan" name="xalan" rev="2.7.0" transitive="false"/>
<!-- The following are optional dependencies, for modules providing optional functionlity or
diff --git a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedQueue.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedQueue.java
index 254ec01519..b00b28b2a9 100644
--- a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedQueue.java
+++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedQueue.java
@@ -63,9 +63,14 @@ public interface ManagedQueue
String ENCODING = "Encoding";
String CONTENT = "Content";
List<String> VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC = Collections.unmodifiableList(Arrays.asList(MSG_AMQ_ID, MIME, ENCODING, CONTENT));
-
+
+ /** Date/time format used for message expiration and message timestamp formatting */
+ String JMSTIMESTAMP_DATETIME_FORMAT = "MM-dd-yy HH:mm:ss.SSS z";
+
//Individual attribute name constants
static final String ATTR_NAME = "Name";
+ static final String ATTR_DESCRIPTION = "Description";
+ static final String ATTR_QUEUE_TYPE = "QueueType";
static final String ATTR_OWNER = "Owner";
static final String ATTR_MAX_MSG_AGE = "MaximumMessageAge";
static final String ATTR_MAX_MSG_COUNT = "MaximumMessageCount";
@@ -92,6 +97,8 @@ public interface ManagedQueue
new HashSet<String>(
Arrays.asList(
ATTR_NAME,
+ ATTR_QUEUE_TYPE,
+ ATTR_DESCRIPTION,
ATTR_OWNER,
ATTR_MAX_MSG_AGE,
ATTR_MAX_MSG_COUNT,
@@ -235,7 +242,7 @@ public interface ManagedQueue
* Tells the maximum number of messages that can be stored in the queue.
* This is useful in setting the notifications or taking required
* action is the number of message increase this limit.
- * @return maximum muber of message allowed to be stored in the queue.
+ * @return maximum nuumber of message allowed to be stored in the queue.
* @throws IOException
*/
Long getMaximumMessageCount() throws IOException;
@@ -287,13 +294,33 @@ public interface ManagedQueue
*/
@MBeanAttribute(name="Capacity", description="The flow control Capacity (Bytes) of the queue")
void setCapacity(Long value) throws IOException, IllegalArgumentException;
+
+ /**
+ * Gets the free text queue description.
+ * @since Qpid JMX API 2.5
+ */
+ String getDescription();
+
+ /**
+ * Sets the free text queue description.
+ * @since Qpid JMX API 2.5
+ */
+ @MBeanAttribute(name="Description", description="Free text description of the queue")
+ void setDescription(String string);
+
+ /**
+ * Gets the queue type
+ * @since Qpid JMX API 2.5
+ */
+ @MBeanAttribute(name="QueueType", description="Type of the queue e.g. standard, priority, etc")
+ String getQueueType();
/**
* Returns the current flow control FlowResumeCapacity of the queue in bytes.
*
* @since Qpid JMX API 1.6
* @return Capacity below which flow resumes in bytes
- * @throws IOException
+ * @throws IOExceptionm
*/
Long getFlowResumeCapacity() throws IOException;
@@ -332,7 +359,7 @@ public interface ManagedQueue
* @since Qpid JMX API 2.0
* @param exclusive the capacity in bytes
* @throws IOException
- * @throws JMException
+ * @throws JMException
*/
@MBeanAttribute(name="Exclusive", description="Whether the queue is Exclusive or not")
void setExclusive(boolean exclusive) throws IOException, JMException;
@@ -341,10 +368,13 @@ public interface ManagedQueue
* Sets the Alternate Exchange for the queue, for use in dead letter queue functionality.
*
* @since Qpid JMX API 2.4
- * @param the name of the exchange to use. Specifying null or the empty string will clear the alternate exchange.
+ * @param exchangeName the name of the exchange to use. Specifying null or the empty string will clear the
+ * alternate exchange.
* @throws IOException
+ * @throws JMException
*/
- void setAlternateExchange(String exchangeName) throws IOException;
+ @MBeanAttribute(name="AlternateExchange", description="Alternate exchange for the queue")
+ void setAlternateExchange(String exchangeName) throws IOException, JMException;
/**
* Returns the name of the Alternate Exchange for the queue, or null if there isn't one.
@@ -353,7 +383,6 @@ public interface ManagedQueue
* @return the name of the Alternate Exchange for the queue, or null if there isn't one
* @throws IOException
*/
- @MBeanAttribute(name="AlternateExchange", description="Alternate exchange for the queue")
String getAlternateExchange() throws IOException;
//********** Operations *****************//
@@ -473,4 +502,5 @@ public interface ManagedQueue
@MBeanOperationParameter(name="to MessageId", description="to MessageId")long toMessageId,
@MBeanOperationParameter(name= ManagedQueue.TYPE, description="to Queue Name")String toQueue)
throws IOException, JMException;
+
}
diff --git a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java
index 38b89b58c5..1a4715224f 100644
--- a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java
+++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java
@@ -46,7 +46,7 @@ public interface ServerInformation
* Qpid JMX API 1.1 can be assumed.
*/
int QPID_JMX_API_MAJOR_VERSION = 2;
- int QPID_JMX_API_MINOR_VERSION = 4;
+ int QPID_JMX_API_MINOR_VERSION = 5;
/**
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
index 963a821864..64a9068357 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
@@ -47,7 +47,7 @@ public abstract class ApplicationRegistry
//max supported broker management interface supported by this release of the management console
public static final int SUPPORTED_QPID_JMX_API_MAJOR_VERSION = 2;
- public static final int SUPPORTED_QPID_JMX_API_MINOR_VERSION = 4;
+ public static final int SUPPORTED_QPID_JMX_API_MINOR_VERSION = 5;
public static final String DATA_DIR = System.getProperty("user.home") + File.separator + ".qpidmc";
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java
index ba4e091b73..737895958f 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java
@@ -404,13 +404,8 @@ public class ViewUtility
private static void convertByteArray(FormToolkit toolkit, Composite compositeHolder, CompositeData data, String itemName, String encoding)
{
- Byte[] arrayItems = (Byte[])data.get(itemName);
- byte[] byteArray = new byte[arrayItems.length];
+ byte[] byteArray = getByteArray(data, itemName);
- for (int i = 0; i < arrayItems.length; i++)
- {
- byteArray[i] = arrayItems[i];
- }
try
{
String textMessage = new String(byteArray, encoding);
@@ -427,6 +422,27 @@ public class ViewUtility
}
}
+ private static byte[] getByteArray(CompositeData data, String itemName)
+ {
+ byte[] byteArray;
+ Object binaryData = data.get(itemName);
+
+ if(binaryData instanceof byte[])
+ {
+ byteArray = (byte[]) binaryData;
+ }
+ else
+ {
+ Byte[] objectArray = (Byte[]) binaryData;
+ byteArray = new byte[objectArray.length];
+ for(int i = 0; i < objectArray.length; i++)
+ {
+ byteArray[i] = objectArray[i];
+ }
+ }
+ return byteArray;
+ }
+
private static Shell getShell()
{
Shell shell = Display.getCurrent().getActiveShell();
@@ -462,13 +478,8 @@ public class ViewUtility
private static void handleBinaryMessageContent(FormToolkit toolkit, Composite compositeHolder, CompositeData data, String itemName, String encoding)
{
final String thisEncoding = encoding;
- final Byte[] arrayItems = (Byte[]) data.get(itemName);
- final byte[] byteArray = new byte[arrayItems.length];
- for (int i = 0; i < arrayItems.length; i++)
- {
- byteArray[i] = arrayItems[i];
- }
+ final byte[] byteArray = getByteArray(data, itemName);
try
{
diff --git a/qpid/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ManagementConsoleTest.java b/qpid/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ManagementConsoleTest.java
deleted file mode 100644
index eef6356642..0000000000
--- a/qpid/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ManagementConsoleTest.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.management.ui;
-
-import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.exchange.DirectExchange;
-import org.apache.qpid.server.management.AMQManagedObject;
-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.queue.AMQQueueMBean;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.util.InternalBrokerBaseCase;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.management.MBeanFeatureInfo;
-import javax.management.MBeanInfo;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-
-/**
- * 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 ManagementConsoleTest extends InternalBrokerBaseCase
-{
- private VirtualHost _virtualHost;
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
- IApplicationRegistry applicationRegistry = ApplicationRegistry.getInstance();
- _virtualHost = applicationRegistry.getVirtualHostRegistry().getVirtualHost("test");
- }
-
-
- /**
- * Test for AMQQueueMBean attribute and operation names, which are used in the management console
- * @throws Exception
- */
- public void testAMQQueueMBeanInfo() throws Exception
- {
- // If this test fails due to changes in the broker code,
- // then the constants in the Constants.java shoule be updated accordingly
- AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueueForManagement"), false, null, false, false,
- _virtualHost, null);
- AMQManagedObject mbean = new AMQQueueMBean(queue);
- MBeanInfo mbeanInfo = mbean.getMBeanInfo();
-
- List<String> operationNames = getNamesList(mbeanInfo.getOperations());
- assertTrue(operationNames.contains(Constants.OPERATION_MOVE_MESSAGES));
-
- List<String> attributesList = getNamesList(mbeanInfo.getAttributes());
- assertTrue(attributesList.contains(Constants.ATTRIBUTE_QUEUE_CONSUMERCOUNT));
- assertTrue(attributesList.contains(Constants.ATTRIBUTE_QUEUE_DEPTH));
- }
-
- /**
- * Test for Exchange MBean attribute and operation names, which are used in the management console
- * @throws Exception
- */
- public void testExchangeMBeanInfo() throws Exception
- {
- // If this test fails due to changes in the broker code,
- // then the constants in the Constants.java shoule be updated accordingly
- DirectExchange exchange = new DirectExchange();
- exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true);
- AMQManagedObject mbean = (AMQManagedObject)exchange.getManagedObject();
- MBeanInfo mbeanInfo = mbean.getMBeanInfo();
-
- // Check for the Exchange Type property in the ObjectName
- assertNotNull(mbean.getObjectName().getKeyProperty(Constants.EXCHANGE_TYPE));
-
- // Check for operation names
- List<String> operationNames = getNamesList(mbeanInfo.getOperations());
- assertTrue(operationNames.contains(Constants.OPERATION_CREATE_BINDING));
- }
-
- /**
- * Test for VirtualHostManagerMBean features used in Management console for customizing the GUI
- * @throws Exception
- */
- public void testVirtualHostManagerMBeanInfo() throws Exception
- {
- AMQManagedObject mbean = (AMQManagedObject)_virtualHost.getManagedObject();
- assertTrue(mbean.getType().equals(Constants.VIRTUAL_HOST));
- }
-
- private List<String> getNamesList(MBeanFeatureInfo[] features)
- {
- List<String> names = new ArrayList<String>();
- for (MBeanFeatureInfo feature : features)
- {
- names.add(feature.getName());
- }
-
- return names;
- }
-}
diff --git a/qpid/java/module.xml b/qpid/java/module.xml
index 8c6d815fee..87df541275 100644
--- a/qpid/java/module.xml
+++ b/qpid/java/module.xml
@@ -52,6 +52,7 @@
<property name="module.results" location="${build.results}/${module}"/>
<property name="module.failed" location="${module.results}/FAILED"/>
<property name="module.src" location="src/main/java"/>
+ <property name="module.src.resources" location="src/main/resources"/>
<property name="module.test.src" location="src/test/java"/>
<property name="module.bin" location="bin"/>
<property name="module.etc" location="etc"/>
@@ -443,12 +444,17 @@
<target name="build" depends="jar,jar-tests,jar-sources,libs,copy-bin,copy-etc,postbuild" description="compile and copy resources into build tree"/>
<target name="jar.manifest" depends="compile" if="module.manifest">
- <jar destfile="${module.jar}" basedir="${module.classes}" manifest="${module.manifest}"/>
+ <jar destfile="${module.jar}" basedir="${module.classes}" manifest="${module.manifest}">
+ <metainf dir="${project.root}/resources/" />
+ <metainf dir="${module.src.resources}" erroronmissingdir="false"/>
+ </jar>
</target>
<target name="jar.nomanifest" depends="compile" unless="module.manifest">
+
<jar destfile="${module.jar}" basedir="${module.classes}">
<metainf dir="${project.root}/resources/" />
+ <metainf dir="${module.src.resources}" erroronmissingdir="false"/>
</jar>
</target>
diff --git a/qpid/java/systests/build.xml b/qpid/java/systests/build.xml
index 57337bdc55..d8ca018ca0 100644
--- a/qpid/java/systests/build.xml
+++ b/qpid/java/systests/build.xml
@@ -32,7 +32,7 @@ nn - or more contributor license agreements. See the NOTICE file
</or>
</condition>
- <property name="module.depends" value="client management/common broker broker/test common amqp-1-0-common common/test jca ${systests.optional.depends}"/>
+ <property name="module.depends" value="client management/common broker broker/test common amqp-1-0-common common/test jca broker-plugins/management ${systests.optional.depends}"/>
<property name="module.test.src" location="src/main/java"/>
<property name="module.test.excludes"
value="**/DropInTest.java,**/TestClientControlledTest.java"/>
diff --git a/qpid/java/systests/etc/config-systests-settings.xml b/qpid/java/systests/etc/config-systests-settings.xml
index 8fad3b8a68..0b65ad83c3 100644
--- a/qpid/java/systests/etc/config-systests-settings.xml
+++ b/qpid/java/systests/etc/config-systests-settings.xml
@@ -56,6 +56,9 @@
<keyStorePath>${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_keystore.jks</keyStorePath>
<keyStorePassword>password</keyStorePassword>
</ssl>
+ <http>
+ <enabled>false</enabled>
+ </http>
</management>
<advanced>
<framesize>65535</framesize>
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedConnectionMBeanTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedConnectionMBeanTest.java
deleted file mode 100644
index 3fc370dc68..0000000000
--- a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagedConnectionMBeanTest.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.jmx;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.common.QpidProperties;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-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.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-import javax.management.JMException;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularData;
-import java.io.IOException;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-
-public class ManagedConnectionMBeanTest extends QpidBrokerTestCase
-{
- private static final Logger LOGGER = LoggerFactory.getLogger(ManagedConnectionMBeanTest.class);
-
- /**
- * JMX helper.
- */
- private JMXTestUtils _jmxUtils;
- private Connection _connection;
-
- public void setUp() throws Exception
- {
- _jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
- super.setUp();
- _jmxUtils.open();
- _connection = getConnection();
- }
-
- public void tearDown() throws Exception
- {
- if (_jmxUtils != null)
- {
- _jmxUtils.close();
- }
- super.tearDown();
- }
-
- public void testChannels() throws Exception
- {
- final String queueName = getTestQueueName();
-
- final Session session = _connection.createSession(true, Session.SESSION_TRANSACTED);
- final Destination destination = session.createQueue(queueName);
- final MessageConsumer consumer = session.createConsumer(destination);
-
- final int numberOfMessages = 2;
- sendMessage(session, destination, numberOfMessages);
- _connection.start();
-
- for (int i = 0; i < numberOfMessages; i++)
- {
- final Message m = consumer.receive(1000l);
- assertNotNull("Message " + i + " is not received", m);
- }
-
- List<ManagedConnection> connections = _jmxUtils.getManagedConnections("test");
- 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);
-
- TabularData channelsData = mBean.channels();
- assertNotNull("Channels data are null", channelsData);
- assertEquals("Unexpected number of rows in channel table", 1, channelsData.size());
-
- final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) channelsData.values().iterator();
- final CompositeDataSupport row = rowItr.next();
- Number unackCount = (Number) row.get(ManagedConnection.UNACKED_COUNT);
- final Boolean transactional = (Boolean) row.get(ManagedConnection.TRANSACTIONAL);
- final Boolean flowBlocked = (Boolean) row.get(ManagedConnection.FLOW_BLOCKED);
- assertNotNull("Channel should have unacknowledged messages", unackCount);
- assertEquals("Unexpected number of unacknowledged messages", 2, unackCount.intValue());
- assertNotNull("Channel should have transaction flag", transactional);
- assertTrue("Unexpected transaction flag", transactional);
- assertNotNull("Channel should have flow blocked flag", flowBlocked);
- assertFalse("Unexpected value of flow blocked flag", flowBlocked);
-
- final Date initialLastIOTime = mBean.getLastIoTime();
- session.commit();
- assertTrue("Last IO time should have been updated", mBean.getLastIoTime().after(initialLastIOTime));
-
- channelsData = mBean.channels();
- assertNotNull("Channels data are null", channelsData);
- assertEquals("Unexpected number of rows in channel table", 1, channelsData.size());
-
- final Iterator<CompositeDataSupport> rowItr2 = (Iterator<CompositeDataSupport>) channelsData.values().iterator();
- final CompositeDataSupport row2 = rowItr2.next();
- unackCount = (Number) row2.get(ManagedConnection.UNACKED_COUNT);
- assertNotNull("Channel should have unacknowledged messages", unackCount);
- assertEquals("Unexpected number of anacknowledged messages", 0, unackCount.intValue());
-
- _connection.close();
-
- LOGGER.debug("Querying JMX for number of open connections");
- connections = _jmxUtils.getManagedConnections("test");
- assertNotNull("Connection MBean is not found", connections);
- assertEquals("Unexpected number of connection mbeans after connection closed", 0, connections.size());
- }
-
- public void testCommit() throws Exception
- {
- final String queueName = getTestQueueName();
-
- final Session consumerSession = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final Session producerSession = _connection.createSession(true, Session.SESSION_TRANSACTED);
- final Destination destination = producerSession.createQueue(queueName);
- final MessageConsumer consumer = consumerSession.createConsumer(destination);
- final MessageProducer producer = producerSession.createProducer(destination);
-
- _connection.start();
-
- List<ManagedConnection> connections = _jmxUtils.getManagedConnections("test");
- 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);
-
- final int numberOfMessages = 2;
- for (int i = 0; i < numberOfMessages; i++)
- {
- producer.send(producerSession.createTextMessage("Test " + i));
- }
-
- // sync to make sure that messages are received on the broker
- // before we commit via JMX
- ((AMQSession<?, ?>) producerSession).sync();
-
- Message m = consumer.receive(500l);
- assertNull("Unexpected message received", m);
-
- Number channelId = getFirstTransactedChannelId(mBean, 2);
- mBean.commitTransactions(channelId.intValue());
-
- for (int i = 0; i < numberOfMessages; i++)
- {
- m = consumer.receive(1000l);
- assertNotNull("Message " + i + " is not received", m);
- assertEquals("Unexpected message received at " + i, "Test " + i, ((TextMessage) m).getText());
- }
- producerSession.commit();
- m = consumer.receive(500l);
- assertNull("Unexpected message received", m);
- }
-
- protected Number getFirstTransactedChannelId(final ManagedConnection mBean, int channelNumber) throws IOException, JMException
- {
- TabularData channelsData = mBean.channels();
- assertNotNull("Channels data are null", channelsData);
- assertEquals("Unexpected number of rows in channel table", channelNumber, channelsData.size());
- final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) channelsData.values().iterator();
- while (rowItr.hasNext())
- {
- final CompositeDataSupport row = rowItr.next();
- Boolean transacted = (Boolean) row.get(ManagedConnection.TRANSACTIONAL);
- if (transacted.booleanValue())
- {
- return (Number) row.get(ManagedConnection.CHAN_ID);
- }
- }
- return null;
- }
-
- public void testRollback() throws Exception
- {
- final String queueName = getTestQueueName();
-
- final Session consumerSession = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final Session producerSession = _connection.createSession(true, Session.SESSION_TRANSACTED);
- final Destination destination = producerSession.createQueue(queueName);
- final MessageConsumer consumer = consumerSession.createConsumer(destination);
- final MessageProducer producer = producerSession.createProducer(destination);
-
- List<ManagedConnection> connections = _jmxUtils.getManagedConnections("test");
- 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);
-
- final int numberOfMessages = 2;
- for (int i = 0; i < numberOfMessages; i++)
- {
- producer.send(producerSession.createTextMessage("Test " + i));
- }
-
- // sync to make sure that messages are received on the broker
- // before we rollback via JMX
- ((AMQSession<?, ?>) producerSession).sync();
-
- Number channelId = getFirstTransactedChannelId(mBean, 2);
- mBean.rollbackTransactions(channelId.intValue());
-
- Message m = consumer.receive(1000l);
- assertNull("Unexpected message received: " + String.valueOf(m), m);
-
- producerSession.commit();
-
- _connection.start();
- m = consumer.receive(1000l);
- assertNull("Unexpected message received after commit " + String.valueOf(m), m);
- }
-
- public void testAuthorisedId() throws Exception
- {
- List<ManagedConnection> connections = _jmxUtils.getManagedConnections("test");
- 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);
- assertEquals("Unexpected authorized id", "guest", mBean.getAuthorizedId());
- }
-
- public void testClientVersion() throws Exception
- {
- List<ManagedConnection> connections = _jmxUtils.getManagedConnections("test");
- 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);
-
- String expectedVersion = QpidProperties.getReleaseVersion();
- assertNotNull("version should not be null", expectedVersion);
- assertFalse("version should not be the empty string", expectedVersion.equals(""));
- assertFalse("version should not be the string 'null'", expectedVersion.equals("null"));
-
- assertEquals("Unexpected version", expectedVersion, mBean.getVersion());
- }
-
- public void testClientId() throws Exception
- {
- List<ManagedConnection> connections = _jmxUtils.getManagedConnections("test");
- 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);
-
- String expectedClientId = _connection.getClientID();
- assertNotNull("ClientId should not be null", expectedClientId);
- assertFalse("ClientId should not be the empty string", expectedClientId.equals(""));
- assertFalse("ClientId should not be the string 'null'", expectedClientId.equals("null"));
-
- assertEquals("Unexpected ClientId", expectedClientId, mBean.getClientId());
- }
-}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageConnectionStatisticsTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageConnectionStatisticsTest.java
deleted file mode 100644
index 9465749226..0000000000
--- a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageConnectionStatisticsTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.jmx;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-
-import javax.jms.Connection;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Test enabling generation of message statistics on a per-connection basis.
- */
-public class MessageConnectionStatisticsTest extends MessageStatisticsTestCase
-{
- public void configureStatistics() throws Exception
- {
- // no statistics generation configured
- }
-
- /**
- * Test statistics on a single connection
- */
- public void testEnablingStatisticsPerConnection() throws Exception
- {
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
-
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- List<String> addresses = new ArrayList<String>();
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived());
- assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled());
-
- addresses.add(mc.getRemoteAddress());
- }
- assertEquals("Incorrect vhost total", 0, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 0, vhost.getTotalDataReceived());
-
- Connection test = new AMQConnection(_brokerUrl, USER, USER, "clientid", "test");
- test.start();
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- if (addresses.contains(mc.getRemoteAddress()))
- {
- continue;
- }
- mc.setStatisticsEnabled(true);
- assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived());
- }
-
- sendUsing(test, 5, 200);
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- if (addresses.contains(mc.getRemoteAddress()))
- {
- assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived());
- assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled());
- }
- else
- {
- assertEquals("Incorrect connection total", 5, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 1000, mc.getTotalDataReceived());
- assertTrue("Connection statistics should be enabled", mc.isStatisticsEnabled());
- }
- }
- assertEquals("Incorrect vhost total", 0, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 0, vhost.getTotalDataReceived());
- assertFalse("Vhost statistics should not be enabled", vhost.isStatisticsEnabled());
-
- test.close();
- }
-}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsConfigurationTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsConfigurationTest.java
deleted file mode 100644
index 383c4c00a8..0000000000
--- a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsConfigurationTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.management.jmx;
-
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-
-/**
- * Test enabling generation of message statistics on a per-connection basis.
- */
-public class MessageStatisticsConfigurationTest extends MessageStatisticsTestCase
-{
- public void configureStatistics() throws Exception
- {
- setConfigurationProperty("statistics.generation.broker", Boolean.toString(getName().contains("Broker")));
- setConfigurationProperty("statistics.generation.virtualhosts", Boolean.toString(getName().contains("Virtualhost")));
- setConfigurationProperty("statistics.generation.connections", Boolean.toString(getName().contains("Connection")));
- }
-
- /**
- * Just broker statistics.
- */
- public void testGenerateBrokerStatistics() throws Exception
- {
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived());
- assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled());
- }
-
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
- assertEquals("Incorrect vhost data", 0, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 0, vhost.getTotalDataReceived());
- assertFalse("Vhost statistics should not be enabled", vhost.isStatisticsEnabled());
-
- assertEquals("Incorrect server total messages", 5, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 1000, _jmxUtils.getServerInformation().getTotalDataReceived());
- assertTrue("Server statistics should be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled());
- }
-
- /**
- * Just virtualhost statistics.
- */
- public void testGenerateVirtualhostStatistics() throws Exception
- {
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived());
- assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled());
- }
-
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
- assertEquals("Incorrect vhost data", 5, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 1000, vhost.getTotalDataReceived());
- assertTrue("Vhost statistics should be enabled", vhost.isStatisticsEnabled());
-
- assertEquals("Incorrect server total messages", 0, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 0, _jmxUtils.getServerInformation().getTotalDataReceived());
- assertFalse("Server statistics should not be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled());
- }
-
- /**
- * Just connection statistics.
- */
- public void testGenerateConnectionStatistics() throws Exception
- {
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection total", 5, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 1000, mc.getTotalDataReceived());
- assertTrue("Connection statistics should be enabled", mc.isStatisticsEnabled());
- }
-
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
- assertEquals("Incorrect vhost data", 0, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 0, vhost.getTotalDataReceived());
- assertFalse("Vhost statistics should not be enabled", vhost.isStatisticsEnabled());
-
- assertEquals("Incorrect server total messages", 0, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 0, _jmxUtils.getServerInformation().getTotalDataReceived());
- assertFalse("Server statistics should not be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled());
- }
-
- /**
- * Both broker and virtualhost statistics.
- */
- public void testGenerateBrokerAndVirtualhostStatistics() throws Exception
- {
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived());
- assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled());
- }
-
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
- assertEquals("Incorrect vhost data", 5, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 1000, vhost.getTotalDataReceived());
- assertTrue("Vhost statistics should be enabled", vhost.isStatisticsEnabled());
-
- assertEquals("Incorrect server total messages", 5, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 1000, _jmxUtils.getServerInformation().getTotalDataReceived());
- assertTrue("Server statistics should be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled());
- }
-
- /**
- * Broker, virtualhost and connection statistics.
- */
- public void testGenerateBrokerVirtualhostAndConnectionStatistics() throws Exception
- {
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection total", 5, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 1000, mc.getTotalDataReceived());
- assertTrue("Connection statistics should be enabled", mc.isStatisticsEnabled());
- }
-
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
- assertEquals("Incorrect vhost data", 5, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 1000, vhost.getTotalDataReceived());
- assertTrue("Vhost statistics should be enabled", vhost.isStatisticsEnabled());
-
- assertEquals("Incorrect server total messages", 5, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 1000, _jmxUtils.getServerInformation().getTotalDataReceived());
- assertTrue("Server statistics should be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled());
- }
-}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsDeliveryTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsDeliveryTest.java
deleted file mode 100644
index bdfd1e2c14..0000000000
--- a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsDeliveryTest.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.management.jmx;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-
-import javax.jms.Connection;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.Session;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Test statistics for delivery and receipt.
- */
-public class MessageStatisticsDeliveryTest extends MessageStatisticsTestCase
-{
- public void configureStatistics() throws Exception
- {
- setConfigurationProperty("statistics.generation.broker", "true");
- setConfigurationProperty("statistics.generation.virtualhosts", "true");
- setConfigurationProperty("statistics.generation.connections", "true");
- }
-
- public void testDeliveryAndReceiptStatistics() throws Exception
- {
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
-
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- List<String> addresses = new ArrayList<String>();
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection delivery total", 0, mc.getTotalMessagesDelivered());
- assertEquals("Incorrect connection delivery data", 0, mc.getTotalDataDelivered());
- assertEquals("Incorrect connection receipt total", 5, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection receipt data", 1000, mc.getTotalDataReceived());
-
- addresses.add(mc.getRemoteAddress());
- }
-
- assertEquals("Incorrect vhost delivery total", 0, vhost.getTotalMessagesDelivered());
- assertEquals("Incorrect vhost delivery data", 0, vhost.getTotalDataDelivered());
- assertEquals("Incorrect vhost receipt total", 5, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost receipt data", 1000, vhost.getTotalDataReceived());
-
- Connection test = new AMQConnection(_brokerUrl, USER, USER, "clientid", "test");
- test.start();
- receiveUsing(test, 5);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- if (addresses.contains(mc.getRemoteAddress()))
- {
- assertEquals("Incorrect connection delivery total", 0, mc.getTotalMessagesDelivered());
- assertEquals("Incorrect connection delivery data", 0, mc.getTotalDataDelivered());
- assertEquals("Incorrect connection receipt total", 5, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection receipt data", 1000, mc.getTotalDataReceived());
- }
- else
- {
- assertEquals("Incorrect connection delivery total", 5, mc.getTotalMessagesDelivered());
- assertEquals("Incorrect connection delivery data", 1000, mc.getTotalDataDelivered());
- assertEquals("Incorrect connection receipt total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection receipt data", 0, mc.getTotalDataReceived());
- }
- }
- assertEquals("Incorrect vhost delivery total", 5, vhost.getTotalMessagesDelivered());
- assertEquals("Incorrect vhost delivery data", 1000, vhost.getTotalDataDelivered());
- assertEquals("Incorrect vhost receipt total", 5, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost receipt data", 1000, vhost.getTotalDataReceived());
-
- test.close();
- }
-
- protected void receiveUsing(Connection con, int number) throws Exception
- {
- Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
- createQueue(session);
- MessageConsumer consumer = session.createConsumer(_queue);
- for (int i = 0; i < number; i++)
- {
- Message msg = consumer.receive(1000);
- assertNotNull("Message " + i + " was not received", msg);
- }
- }
-}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java
deleted file mode 100644
index de4567624d..0000000000
--- a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.jmx;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-
-import javax.jms.Connection;
-
-/**
- * Test generation of message statistics.
- */
-public class MessageStatisticsTest extends MessageStatisticsTestCase
-{
- public void configureStatistics() throws Exception
- {
- setConfigurationProperty("statistics.generation.broker", "true");
- setConfigurationProperty("statistics.generation.virtualhosts", "true");
- setConfigurationProperty("statistics.generation.connections", "true");
- }
-
- /**
- * Test message totals.
- */
- public void testMessageTotals() throws Exception
- {
- sendUsing(_test, 10, 100);
- sendUsing(_dev, 20, 100);
- sendUsing(_local, 5, 100);
- sendUsing(_local, 5, 100);
- sendUsing(_local, 5, 100);
- Thread.sleep(2000);
-
- ManagedBroker test = _jmxUtils.getManagedBroker("test");
- ManagedBroker dev = _jmxUtils.getManagedBroker("development");
- ManagedBroker local = _jmxUtils.getManagedBroker("localhost");
-
- if (!isBroker010())
- {
- long total = 0;
- long data = 0;
- for (ManagedConnection mc : _jmxUtils.getAllManagedConnections())
- {
- total += mc.getTotalMessagesReceived();
- data += mc.getTotalDataReceived();
- }
- assertEquals("Incorrect connection total", 45, total);
- assertEquals("Incorrect connection data", 4500, data);
- }
- assertEquals("Incorrect server total", 45, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server data", 4500, _jmxUtils.getServerInformation().getTotalDataReceived());
-
- if (!isBroker010())
- {
- long testTotal = 0;
- long testData = 0;
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- testTotal += mc.getTotalMessagesReceived();
- testData += mc.getTotalDataReceived();
- }
- assertEquals("Incorrect test connection total", 10, testTotal);
- assertEquals("Incorrect test connection data", 1000, testData);
- }
- assertEquals("Incorrect test vhost total", 10, test.getTotalMessagesReceived());
- assertEquals("Incorrect test vhost data", 1000, test.getTotalDataReceived());
-
- if (!isBroker010())
- {
- long devTotal = 0;
- long devData = 0;
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("development"))
- {
- devTotal += mc.getTotalMessagesReceived();
- devData += mc.getTotalDataReceived();
- }
- assertEquals("Incorrect test connection total", 20, devTotal);
- assertEquals("Incorrect test connection data", 2000, devData);
- }
- assertEquals("Incorrect development total", 20, dev.getTotalMessagesReceived());
- assertEquals("Incorrect development data", 2000, dev.getTotalDataReceived());
-
- if (!isBroker010())
- {
- long localTotal = 0;
- long localData = 0;
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("localhost"))
- {
- localTotal += mc.getTotalMessagesReceived();
- localData += mc.getTotalDataReceived();
- }
- assertEquals("Incorrect test connection total", 15, localTotal);
- assertEquals("Incorrect test connection data", 1500, localData);
- }
- assertEquals("Incorrect localhost total", 15, local.getTotalMessagesReceived());
- assertEquals("Incorrect localhost data", 1500, local.getTotalDataReceived());
- }
-
- /**
- * Test message totals when a connection is closed.
- */
- public void testMessageTotalsWithClosedConnections() throws Exception
- {
- Connection temp = new AMQConnection(_brokerUrl, USER, USER, "clientid", "test");
- temp.start();
-
- sendUsing(_test, 10, 100);
- sendUsing(temp, 10, 100);
- sendUsing(_test, 10, 100);
- Thread.sleep(2000);
-
- temp.close();
-
- ManagedBroker test = _jmxUtils.getManagedBroker("test");
-
- if (!isBroker010())
- {
- long total = 0;
- long data = 0;
- for (ManagedConnection mc : _jmxUtils.getAllManagedConnections())
- {
- total += mc.getTotalMessagesReceived();
- data += mc.getTotalDataReceived();
- }
- assertEquals("Incorrect active connection total", 20, total);
- assertEquals("Incorrect active connection data", 2000, data);
- }
- assertEquals("Incorrect server total", 30, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server data", 3000, _jmxUtils.getServerInformation().getTotalDataReceived());
-
- if (!isBroker010())
- {
- long testTotal = 0;
- long testData = 0;
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- testTotal += mc.getTotalMessagesReceived();
- testData += mc.getTotalDataReceived();
- }
- assertEquals("Incorrect test active connection total", 20, testTotal);
- assertEquals("Incorrect test active connection data", 20 * 100, testData);
- }
- assertEquals("Incorrect test vhost total", 30, test.getTotalMessagesReceived());
- assertEquals("Incorrect test vhost data", 30 * 100, test.getTotalDataReceived());
- }
-
- /**
- * Test message totals when a vhost has its statistics reset
- */
- public void testMessageTotalVhostReset() throws Exception
- {
- sendUsing(_test, 10, 10);
- sendUsing(_dev, 10, 10);
- Thread.sleep(2000);
-
- ManagedBroker test = _jmxUtils.getManagedBroker("test");
- ManagedBroker dev = _jmxUtils.getManagedBroker("development");
-
- assertEquals("Incorrect test vhost total messages", 10, test.getTotalMessagesReceived());
- assertEquals("Incorrect test vhost total data", 100, test.getTotalDataReceived());
- assertEquals("Incorrect dev vhost total messages", 10, dev.getTotalMessagesReceived());
- assertEquals("Incorrect dev vhost total data", 100, dev.getTotalDataReceived());
-
- assertEquals("Incorrect server total messages", 20, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 200, _jmxUtils.getServerInformation().getTotalDataReceived());
-
- test.resetStatistics();
-
- assertEquals("Incorrect test vhost total messages", 0, test.getTotalMessagesReceived());
- assertEquals("Incorrect test vhost total data", 0, test.getTotalDataReceived());
- assertEquals("Incorrect dev vhost total messages", 10, dev.getTotalMessagesReceived());
- assertEquals("Incorrect dev vhost total data", 100, dev.getTotalDataReceived());
-
- assertEquals("Incorrect server total messages", 20, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 200, _jmxUtils.getServerInformation().getTotalDataReceived());
- }
-}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTestCase.java
deleted file mode 100644
index 45200ba476..0000000000
--- a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTestCase.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.management.jmx;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQDestination;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.framing.AMQShortString;
-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.MessageProducer;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-
-/**
- * Test generation of message statistics.
- */
-public abstract class MessageStatisticsTestCase extends QpidBrokerTestCase
-{
- protected static final String USER = "admin";
-
- protected JMXTestUtils _jmxUtils;
- protected Connection _test, _dev, _local;
- protected String _queueName = "statistics";
- protected Destination _queue;
- protected String _brokerUrl;
-
- @Override
- public void setUp() throws Exception
- {
- _jmxUtils = new JMXTestUtils(this, USER, USER);
- _jmxUtils.setUp();
-
- configureStatistics();
-
- 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();
-
- _jmxUtils.open();
- }
-
- protected void createQueue(Session session) throws AMQException, JMSException
- {
- _queue = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, _queueName);
- if (!((AMQSession<?,?>) session).isQueueBound((AMQDestination) _queue))
- {
- ((AMQSession<?,?>) session).createQueue(new AMQShortString(_queueName), false, true, false, null);
- ((AMQSession<?,?>) session).declareAndBind((AMQDestination) new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, _queueName));
- }
- }
-
-
- @Override
- public void tearDown() throws Exception
- {
- _jmxUtils.close();
-
- _test.close();
- _dev.close();
- _local.close();
-
- super.tearDown();
- }
-
- /**
- * Configure statistics generation properties on the broker.
- */
- public abstract void configureStatistics() throws Exception;
-
- protected void sendUsing(Connection con, int number, int size) throws Exception
- {
- Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
- createQueue(session);
- MessageProducer producer = session.createProducer(_queue);
- String content = new String(new byte[size]);
- TextMessage msg = session.createTextMessage(content);
- for (int i = 0; i < number; i++)
- {
- producer.send(msg);
- }
- }
-
- /**
- * Asserts that the actual value is within the expected value plus or
- * minus the given error.
- */
- public void assertApprox(String message, double error, double expected, double actual)
- {
- double min = expected * (1.0d - error);
- double max = expected * (1.0d + error);
- String assertion = String.format("%s: expected %f +/- %d%%, actual %f",
- message, expected, (int) (error * 100.0d), actual);
- assertTrue(assertion, actual > min && actual < max);
- }
-}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java
index ab0d88c737..782709b24f 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java
@@ -333,7 +333,7 @@ public class ModelTest extends QpidBrokerTestCase
queueName));
assertEquals(queueName, managedQueue.getName());
- assertEquals(String.valueOf(owner), managedQueue.getOwner());
+ assertEquals(owner, managedQueue.getOwner());
assertEquals(durable, managedQueue.isDurable());
assertEquals(autoDelete, managedQueue.isAutoDelete());
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
index 6e4f12b9f3..ceff2b998a 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
@@ -19,7 +19,6 @@
package org.apache.qpid.server.security.acl;
import org.apache.qpid.management.common.mbeans.ServerInformation;
-import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.security.access.ObjectType;
import org.apache.qpid.test.utils.JMXTestUtils;
@@ -30,7 +29,7 @@ import java.lang.management.RuntimeMXBean;
* Tests that access to the JMX interface is governed only by {@link ObjectType#METHOD}/{@link ObjectType#ALL}
* rules and AMQP rights have no effect.
*
- * Ensures that objects outside the Qpid domain ({@link ManagedObject#DOMAIN}) are not governed by the ACL model.
+ * Ensures that objects outside the Qpid domain are not governed by the ACL model.
*/
public class ExternalACLJMXTest extends AbstractACLTestCase
{
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsReportingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java
index 786ef11956..c38fcd9199 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsReportingTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java
@@ -18,30 +18,75 @@
* under the License.
*
*/
-package org.apache.qpid.management.jmx;
+package org.apache.qpid.server.stats;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
import org.apache.qpid.util.LogMonitor;
import java.util.List;
+import javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
/**
- * Test generation of message statistics reporting.
+ * Test generation of message/data statistics reporting and the ability
+ * to control from the configuration file.
*/
-public class MessageStatisticsReportingTest extends MessageStatisticsTestCase
+public class StatisticsReportingTest extends QpidBrokerTestCase
{
protected LogMonitor _monitor;
-
- public void configureStatistics() throws Exception
+ protected static final String USER = "admin";
+
+ protected Connection _test, _dev, _local;
+ protected String _queueName = "statistics";
+ protected Destination _queue;
+ protected String _brokerUrl;
+
+ @Override
+ public void setUp() throws Exception
{
setConfigurationProperty("statistics.generation.broker", "true");
setConfigurationProperty("statistics.generation.virtualhosts", "true");
-
+
if (getName().equals("testEnabledStatisticsReporting"))
{
setConfigurationProperty("statistics.reporting.period", "10");
}
-
+
_monitor = new LogMonitor(_outputFile);
+
+ 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();
+
+ }
+
+ @Override
+ public void tearDown() throws Exception
+ {
+ _test.close();
+ _dev.close();
+ _local.close();
+
+ super.tearDown();
}
/**
@@ -52,14 +97,14 @@ public class MessageStatisticsReportingTest extends MessageStatisticsTestCase
sendUsing(_test, 10, 100);
sendUsing(_dev, 20, 100);
sendUsing(_local, 15, 100);
-
+
Thread.sleep(10 * 1000); // 15s
-
+
List<String> brokerStatsData = _monitor.findMatches("BRK-1008");
List<String> brokerStatsMessages = _monitor.findMatches("BRK-1009");
List<String> vhostStatsData = _monitor.findMatches("VHT-1003");
List<String> 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());
@@ -74,17 +119,40 @@ public class MessageStatisticsReportingTest extends MessageStatisticsTestCase
sendUsing(_test, 10, 100);
sendUsing(_dev, 20, 100);
sendUsing(_local, 15, 100);
-
+
Thread.sleep(10 * 1000); // 15s
-
+
List<String> brokerStatsData = _monitor.findMatches("BRK-1008");
List<String> brokerStatsMessages = _monitor.findMatches("BRK-1009");
List<String> vhostStatsData = _monitor.findMatches("VHT-1003");
List<String> vhostStatsMessages = _monitor.findMatches("VHT-1004");
-
+
assertEquals("Incorrect number of broker data stats log messages", 0, brokerStatsData.size());
assertEquals("Incorrect number of broker message stats log messages", 0, brokerStatsMessages.size());
assertEquals("Incorrect number of virtualhost data stats log messages", 0, vhostStatsData.size());
assertEquals("Incorrect number of virtualhost message stats log messages", 0, vhostStatsMessages.size());
}
+
+ private void sendUsing(Connection con, int number, int size) throws Exception
+ {
+ Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ createQueue(session);
+ MessageProducer producer = session.createProducer(_queue);
+ String content = new String(new byte[size]);
+ TextMessage msg = session.createTextMessage(content);
+ for (int i = 0; i < number; i++)
+ {
+ producer.send(msg);
+ }
+ }
+
+ private void createQueue(Session session) throws AMQException, JMSException
+ {
+ _queue = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, _queueName);
+ if (!((AMQSession<?,?>) session).isQueueBound((AMQDestination) _queue))
+ {
+ ((AMQSession<?,?>) session).createQueue(new AMQShortString(_queueName), false, true, false, null);
+ ((AMQSession<?,?>) session).declareAndBind((AMQDestination) new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, _queueName));
+ }
+ }
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java
index 2c029b4bf3..07965cfa95 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java
@@ -171,4 +171,10 @@ public class QuotaMessageStore extends NullMessageStore
}
}
}
+
+ @Override
+ public String getStoreType()
+ {
+ return "QUOTA";
+ }
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
index f2d4a513be..9db04b64b3 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
@@ -24,7 +24,6 @@ import org.apache.commons.configuration.Configuration;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQStoreException;
-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;
@@ -370,4 +369,10 @@ public class SlowMessageStore implements MessageStore
return _realStore.getStoreLocation();
}
+ @Override
+ public String getStoreType()
+ {
+ return "SLOW";
+ }
+
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java
index 5b3bca7033..2cd7520ae4 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/BrokerClosesClientConnectionTest.java
@@ -26,7 +26,6 @@ import java.util.concurrent.TimeUnit;
import org.apache.qpid.AMQConnectionClosedException;
import org.apache.qpid.AMQDisconnectedException;
import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.management.jmx.ManagedConnectionMBeanTest;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import org.apache.qpid.transport.ConnectionException;
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java
index 1ef6164db6..43b80b45fb 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java
@@ -33,11 +33,15 @@ 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 javax.management.InstanceNotFoundException;
import javax.management.JMException;
+import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.MalformedObjectNameException;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import java.io.IOException;
@@ -50,8 +54,8 @@ import java.util.Set;
*/
public class JMXTestUtils
{
- private static final String DEFAULT_PASSWORD = "admin";
- private static final String DEFAULT_USERID = "admin";
+ public static final String DEFAULT_PASSWORD = "admin";
+ public static final String DEFAULT_USERID = "admin";
private MBeanServerConnection _mbsc;
private JMXConnector _jmxc;
@@ -101,6 +105,18 @@ public class JMXTestUtils
}
}
+ public void addNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback)
+ throws InstanceNotFoundException, IOException
+ {
+ _mbsc.addNotificationListener(name, listener, filter, handback);
+ }
+
+ public void removeNotificationListener(ObjectName name, NotificationListener listener)
+ throws InstanceNotFoundException, IOException, ListenerNotFoundException
+ {
+ _mbsc.removeNotificationListener(name, listener);
+ }
+
/**
* Create a non-durable exchange with the requested name
*
@@ -144,7 +160,6 @@ public class JMXTestUtils
throws IOException, JMException, MBeanException
{
ManagedBroker managedBroker = getManagedBroker(virtualHostName);
-
managedBroker.unregisterExchange(exchange);
}
@@ -160,87 +175,81 @@ public class JMXTestUtils
throws IOException, JMException, MBeanException
{
ManagedBroker managedBroker = getManagedBroker(virtualHostName);
-
managedBroker.deleteQueue(queueName);
}
-
+
/**
- * Sets the logging level.
+ * Sets the logging level.
*
* @throws JMException
* @throws IOException if there is a problem with the JMX Connection
* @throws MBeanException
*/
public void setRuntimeLoggerLevel(String logger, String level)
- throws IOException, JMException, MBeanException
+ throws IOException, JMException, MBeanException
{
LoggingManagement loggingManagement = getLoggingManagement();
-
loggingManagement.setRuntimeLoggerLevel(logger, level);
}
-
+
/**
- * Reload logging config file.
+ * Reload logging config file.
*
* @throws JMException
* @throws IOException if there is a problem with the JMX Connection
* @throws MBeanException
*/
public void reloadConfigFile()
- throws IOException, JMException, MBeanException
+ throws IOException, JMException, MBeanException
{
LoggingManagement loggingManagement = getLoggingManagement();
-
loggingManagement.reloadConfigFile();
}
/**
- * Get list of available logger levels.
+ * Get list of available logger levels.
*
* @throws JMException
* @throws IOException if there is a problem with the JMX Connection
* @throws MBeanException
*/
public String[] getAvailableLoggerLevels()
- throws IOException, JMException, MBeanException
+ throws IOException, JMException, MBeanException
{
LoggingManagement loggingManagement = getLoggingManagement();
-
return loggingManagement.getAvailableLoggerLevels();
}
-
+
/**
- * Set root logger level.
+ * Set root logger level.
*
* @throws JMException
* @throws IOException if there is a problem with the JMX Connection
* @throws MBeanException
*/
public void setRuntimeRootLoggerLevel(String level)
- throws IOException, JMException, MBeanException
+ throws IOException, JMException, MBeanException
{
LoggingManagement loggingManagement = getLoggingManagement();
-
loggingManagement.setRuntimeRootLoggerLevel(level);
}
-
+
/**
- * Get root logger level.
+ * Get root logger level.
*
* @throws JMException
* @throws IOException if there is a problem with the JMX Connection
* @throws MBeanException
*/
public String getRuntimeRootLoggerLevel()
- throws IOException, JMException, MBeanException
+ throws IOException, JMException, MBeanException
{
LoggingManagement loggingManagement = getLoggingManagement();
-
return loggingManagement.getRuntimeRootLoggerLevel();
}
/**
- * Retrive the ObjectName for a Virtualhost.
+ * Retrieve the ObjectName for a Virtualhost.
*
* This is then used to create a proxy to the ManagedBroker MBean.
*
@@ -261,12 +270,12 @@ public class JMXTestUtils
// We have verified we have only one value in objectNames so return it
ObjectName objectName = objectNames.iterator().next();
- _test.getLogger().info("Loading: " + objectName);
+ _test.getLogger().info("Loading: " + objectName);
return objectName;
}
/**
- * Retrive the ObjectName for the given Queue on a Virtualhost.
+ * Retrieve the ObjectName for the given Queue on a Virtualhost.
*
* This is then used to create a proxy to the ManagedQueue MBean.
*
@@ -289,7 +298,7 @@ public class JMXTestUtils
// We have verified we have only one value in objectNames so return it
ObjectName objectName = objectNames.iterator().next();
- _test.getLogger().info("Loading: " + objectName);
+ _test.getLogger().info("Loading: " + objectName);
return objectName;
}
@@ -317,7 +326,7 @@ public class JMXTestUtils
// We have verified we have only one value in objectNames so return it
ObjectName objectName = objectNames.iterator().next();
- _test.getLogger().info("Loading: " + objectName);
+ _test.getLogger().info("Loading: " + objectName);
return objectName;
}
@@ -330,7 +339,7 @@ public class JMXTestUtils
_test.assertEquals("Unexpected number of objects matching " + managedClass + " returned", 1, objectNames.size());
ObjectName objectName = objectNames.iterator().next();
- _test.getLogger().info("Loading: " + objectName);
+ _test.getLogger().info("Loading: " + objectName);
return getManagedObject(managedClass, objectName);
}
@@ -363,34 +372,34 @@ public class JMXTestUtils
{
return getManagedObject(ManagedBroker.class, getVirtualHostManagerObjectName(virtualHost));
}
-
+
public ManagedExchange getManagedExchange(String exchangeName)
{
- ObjectName objectName = getExchangeObjectName("test", exchangeName);
+ ObjectName objectName = getExchangeObjectName("test", exchangeName);
return MBeanServerInvocationHandler.newProxyInstance(_mbsc, objectName, ManagedExchange.class, false);
}
-
+
public ManagedQueue getManagedQueue(String queueName)
{
ObjectName objectName = getQueueObjectName("test", queueName);
return getManagedObject(ManagedQueue.class, objectName);
}
- public LoggingManagement getLoggingManagement() throws MalformedObjectNameException
+ public LoggingManagement getLoggingManagement() throws MalformedObjectNameException
{
- ObjectName objectName = new ObjectName("org.apache.qpid:type=LoggingManagement,name=LoggingManagement");
+ ObjectName objectName = new ObjectName("org.apache.qpid:type=LoggingManagement,name=LoggingManagement");
return getManagedObject(LoggingManagement.class, objectName);
}
-
- public ConfigurationManagement getConfigurationManagement() throws MalformedObjectNameException
+
+ public ConfigurationManagement getConfigurationManagement() throws MalformedObjectNameException
{
- ObjectName objectName = new ObjectName("org.apache.qpid:type=ConfigurationManagement,name=ConfigurationManagement");
+ ObjectName objectName = new ObjectName("org.apache.qpid:type=ConfigurationManagement,name=ConfigurationManagement");
return getManagedObject(ConfigurationManagement.class, objectName);
}
-
- public UserManagement getUserManagement() throws MalformedObjectNameException
+
+ public UserManagement getUserManagement() throws MalformedObjectNameException
{
- ObjectName objectName = new ObjectName("org.apache.qpid:type=UserManagement,name=UserManagement");
+ ObjectName objectName = new ObjectName("org.apache.qpid:type=UserManagement,name=UserManagement");
return getManagedObject(UserManagement.class, objectName);
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
index c5077ccb64..056356cad7 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
@@ -83,6 +83,10 @@ public class QpidBrokerTestCase extends QpidTestCase
INTERNAL /** Test case starts an embedded broker within this JVM */,
SPAWNED /** Test case spawns a new broker as a separate process */
}
+
+ public static final String GUEST_USERNAME = "guest";
+ 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"));
@@ -1095,7 +1099,7 @@ public class QpidBrokerTestCase extends QpidTestCase
public Connection getConnection() throws JMSException, NamingException
{
- return getConnection("guest", "guest");
+ return getConnection(GUEST_USERNAME, GUEST_PASSWORD);
}
public Connection getConnection(ConnectionURL url) throws JMSException
diff --git a/qpid/java/test-profiles/CPPExcludes b/qpid/java/test-profiles/CPPExcludes
index 23722ae5cd..7c653c73f1 100755
--- a/qpid/java/test-profiles/CPPExcludes
+++ b/qpid/java/test-profiles/CPPExcludes
@@ -101,11 +101,8 @@ org.apache.qpid.server.logging.subjects.*
org.apache.qpid.server.logging.actors.*
// CPP Broker does not have a JMX interface to test
-org.apache.qpid.management.jmx.*
-org.apache.qpid.server.queue.AMQQueueMBeanTest#*
-org.apache.qpid.server.exchange.ExchangeMBeanTest#*
-org.apache.qpid.server.AMQBrokerManagerMBeanTest#*
-org.apache.qpid.server.protocol.AMQProtocolSessionMBeanTest#*
+org.apache.qpid.server.jmx.mbeans.*
+org.apache.qpid.systest.management.jmx.*
// JMX is used in this test for validation
org.apache.qpid.server.queue.ModelTest#*
@@ -159,8 +156,6 @@ org.apache.qpid.test.unit.transacted.TransactionTimeoutConfigurationTest#*
org.apache.qpid.test.unit.transacted.TransactionTimeoutTest#*
// Java broker only
-org.apache.qpid.server.logging.management.LoggingManagementMBeanTest#*
-org.apache.qpid.server.management.AMQUserManagementMBeanTest#*
org.apache.qpid.server.SupportedProtocolVersionsTest#*
diff --git a/qpid/java/test-profiles/Excludes b/qpid/java/test-profiles/Excludes
index c0532e0b97..bff362b07e 100644
--- a/qpid/java/test-profiles/Excludes
+++ b/qpid/java/test-profiles/Excludes
@@ -31,3 +31,10 @@ org.apache.qpid.server.logging.DerbyMessageStoreLoggingTest#*
org.apache.qpid.client.ssl.SSLTest#testVerifyLocalHostLocalDomain
+// QPID-3936: disable the systests temporarily
+org.apache.qpid.systest.disttest.*
+org.apache.qpid.systest.disttest.clientonly.*
+org.apache.qpid.systest.disttest.controlleronly.*
+org.apache.qpid.systest.disttest.controllerandclient.*
+org.apache.qpid.systest.disttest.endtoend.*
+
diff --git a/qpid/java/test-profiles/Java010Excludes b/qpid/java/test-profiles/Java010Excludes
index e34cd6b694..f9ba753a5f 100755
--- a/qpid/java/test-profiles/Java010Excludes
+++ b/qpid/java/test-profiles/Java010Excludes
@@ -65,3 +65,8 @@ org.apache.qpid.client.failover.AddressBasedFailoverBehaviourTest#testFlowContro
// QPID-3604: Immediate Prefetch no longer supported by 0-10
org.apache.qpid.client.AsynchMessageListenerTest#testImmediatePrefetchWithMessageListener
+// QPID-4090: Can't connect from Java Client to Java Broker when Broker uses Base64MD5PasswordFilePrincipalDatabase principal database (0-10 protocol only)
+org.apache.qpid.systest.management.jmx.UserManagementWithBase64MD5PasswordsTest#testJmsLoginForNewUser
+org.apache.qpid.systest.management.jmx.UserManagementWithBase64MD5PasswordsTest#testJmsLoginNotPossibleForDeletedUser
+org.apache.qpid.systest.management.jmx.UserManagementWithBase64MD5PasswordsTest#testJmsLoginForPasswordChangedUser
+org.apache.qpid.systest.management.jmx.UserManagementWithBase64MD5PasswordsTest#testReload
diff --git a/qpid/java/test-profiles/JavaPre010Excludes b/qpid/java/test-profiles/JavaPre010Excludes
index 3f29dee203..422764bad0 100644
--- a/qpid/java/test-profiles/JavaPre010Excludes
+++ b/qpid/java/test-profiles/JavaPre010Excludes
@@ -70,3 +70,8 @@ org.apache.qpid.test.unit.ct.DurableSubscriberTest#testResubscribeWithChangedSel
org.apache.qpid.ra.QpidRAConnectionTest#*
org.apache.qpid.ra.QpidRAXAResourceTest#*
+// These tests rely on new address syntax
+org.apache.qpid.systest.management.jmx.QueueManagementTest#testGetSetAlternateExchange
+org.apache.qpid.systest.management.jmx.QueueManagementTest#testRemoveAlternateExchange
+org.apache.qpid.systest.management.jmx.QueueManagementTest#testAlternateExchangeSurvivesRestart
+
diff --git a/qpid/java/test-profiles/JavaTransientExcludes b/qpid/java/test-profiles/JavaTransientExcludes
index 3469e35d02..3e42b79d99 100644
--- a/qpid/java/test-profiles/JavaTransientExcludes
+++ b/qpid/java/test-profiles/JavaTransientExcludes
@@ -42,3 +42,6 @@ org.apache.qpid.server.store.MessageStoreTest#testDurableExchangeRemoval
org.apache.qpid.server.store.berkeleydb.*
org.apache.qpid.server.store.DurableConfigurationStoreTest#*
+
+org.apache.qpid.systest.management.jmx.QueueManagementTest#testAlternateExchangeSurvivesRestart
+org.apache.qpid.systest.management.jmx.QueueManagementTest#testQueueDescriptionSurvivesRestart