From 30bb491015bc7d8a5ab423c8843eac831b823809 Mon Sep 17 00:00:00 2001 From: Robert Gemmell Date: Sun, 8 Jul 2012 15:28:32 +0000 Subject: QPID-3998, QPID-3999, QPID-4093: rename new plugins git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1358757 13f79535-47bb-0310-9956-ffa450edef68 --- java/bdbstore/jmx/MANIFEST.MF | 2 +- java/bdbstore/jmx/build.xml | 4 +- .../jmx/BDBHAMessageStoreManagerMBean.java | 2 +- java/broker-plugins/jmx/MANIFEST.MF | 66 -- java/broker-plugins/jmx/build.xml | 47 -- .../apache/qpid/server/jmx/AMQManagedObject.java | 84 --- .../qpid/server/jmx/DefaultManagedObject.java | 189 ------ .../org/apache/qpid/server/jmx/JMXActivator.java | 136 ----- .../apache/qpid/server/jmx/JMXConfiguration.java | 76 --- .../qpid/server/jmx/JMXManagedObjectRegistry.java | 499 ---------------- .../org/apache/qpid/server/jmx/JMXService.java | 193 ------ .../apache/qpid/server/jmx/MBeanIntrospector.java | 400 ------------- .../server/jmx/MBeanInvocationHandlerImpl.java | 382 ------------ .../org/apache/qpid/server/jmx/MBeanProvider.java | 52 -- .../org/apache/qpid/server/jmx/ManagedObject.java | 57 -- .../qpid/server/jmx/ManagedObjectRegistry.java | 48 -- .../mbeans/AbstractStatisticsGatheringMBean.java | 200 ------- .../jmx/mbeans/ConfigurationManagementMBean.java | 56 -- .../qpid/server/jmx/mbeans/ConnectionMBean.java | 182 ------ .../qpid/server/jmx/mbeans/ExchangeMBean.java | 313 ---------- .../server/jmx/mbeans/LoggingManagementMBean.java | 324 ---------- .../apache/qpid/server/jmx/mbeans/MBeanUtils.java | 57 -- .../apache/qpid/server/jmx/mbeans/QueueMBean.java | 663 --------------------- .../server/jmx/mbeans/ServerInformationMBean.java | 89 --- .../apache/qpid/server/jmx/mbeans/Shutdown.java | 137 ----- .../qpid/server/jmx/mbeans/ShutdownMBean.java | 58 -- .../server/jmx/mbeans/UserManagementMBean.java | 179 ------ .../qpid/server/jmx/mbeans/VirtualHostMBean.java | 211 ------- .../server/jmx/mbeans/VirtualHostManagerMBean.java | 238 -------- .../qpid/server/jmx/NoopManagedObjectRegistry.java | 46 -- .../server/jmx/mbeans/ConnectionMBeanTest.java | 237 -------- .../qpid/server/jmx/mbeans/ExchangeMBeanTest.java | 234 -------- .../jmx/mbeans/LoggingManagementMBeanTest.java | 245 -------- .../qpid/server/jmx/mbeans/MBeanTestUtils.java | 40 -- .../qpid/server/jmx/mbeans/QueueMBeanTest.java | 368 ------------ .../jmx/mbeans/ServerInformationMBeanTest.java | 94 --- .../server/jmx/mbeans/UserManagementMBeanTest.java | 157 ----- .../jmx/mbeans/VirtualHostManagerMBeanTest.java | 174 ------ .../management/jmx/BrokerManagementTest.java | 128 ---- .../management/jmx/ConnectionManagementTest.java | 283 --------- .../management/jmx/LoggingManagementTest.java | 149 ----- .../management/jmx/ManagementActorLoggingTest.java | 480 --------------- .../management/jmx/ManagementLoggingTest.java | 317 ---------- .../management/jmx/QueueManagementTest.java | 614 ------------------- .../systest/management/jmx/StatisticsTest.java | 204 ------- .../systest/management/jmx/UserManagementTest.java | 251 -------- .../UserManagementWithBase64MD5PasswordsTest.java | 39 -- java/broker-plugins/management-http/MANIFEST.MF | 66 ++ java/broker-plugins/management-http/build.xml | 43 ++ .../qpid/server/management/plugin/Management.java | 155 +++++ .../management/plugin/ManagementActivator.java | 72 +++ .../management/plugin/ManagementConfiguration.java | 77 +++ .../plugin/servlet/DefinedFileServlet.java | 79 +++ .../management/plugin/servlet/FileServlet.java | 109 ++++ .../plugin/servlet/api/ExchangesServlet.java | 208 +++++++ .../plugin/servlet/api/VhostsServlet.java | 118 ++++ .../plugin/servlet/rest/AbstractServlet.java | 215 +++++++ .../plugin/servlet/rest/KeyComparator.java | 53 ++ .../plugin/servlet/rest/LogRecordsServlet.java | 86 +++ .../plugin/servlet/rest/MapComparator.java | 74 +++ .../plugin/servlet/rest/MessageContentServlet.java | 177 ++++++ .../plugin/servlet/rest/MessageServlet.java | 503 ++++++++++++++++ .../plugin/servlet/rest/RestServlet.java | 577 ++++++++++++++++++ .../plugin/servlet/rest/SaslServlet.java | 253 ++++++++ .../plugin/servlet/rest/StructureServlet.java | 104 ++++ .../src/main/java/resources/addBinding.html | 42 ++ .../src/main/java/resources/addExchange.html | 53 ++ .../src/main/java/resources/addQueue.html | 174 ++++++ .../resources/authenticationprovider/addUser.html | 42 ++ .../authenticationprovider/setPassword.html | 42 ++ ...showPrincipalDatabaseAuthenticationManager.html | 29 + .../src/main/java/resources/css/common.css | 92 +++ .../src/main/java/resources/footer.html | 28 + .../src/main/java/resources/images/qpid-logo.png | Bin 0 -> 6600 bytes .../java/resources/js/qpid/authorization/sasl.js | 213 +++++++ .../resources/js/qpid/common/UpdatableStore.js | 110 ++++ .../main/java/resources/js/qpid/common/footer.js | 30 + .../java/resources/js/qpid/common/formatter.js | 99 +++ .../java/resources/js/qpid/common/properties.js | 26 + .../main/java/resources/js/qpid/common/updater.js | 45 ++ .../src/main/java/resources/js/qpid/common/util.js | 56 ++ .../js/qpid/management/AuthenticationProvider.js | 122 ++++ .../java/resources/js/qpid/management/Broker.js | 205 +++++++ .../resources/js/qpid/management/Connection.js | 213 +++++++ .../java/resources/js/qpid/management/Exchange.js | 229 +++++++ .../java/resources/js/qpid/management/Queue.js | 438 ++++++++++++++ .../resources/js/qpid/management/VirtualHost.js | 327 ++++++++++ .../resources/js/qpid/management/addBinding.js | 223 +++++++ .../resources/js/qpid/management/addExchange.js | 147 +++++ .../java/resources/js/qpid/management/addQueue.js | 158 +++++ .../PrincipalDatabaseAuthenticationManager.js | 327 ++++++++++ .../resources/js/qpid/management/controller.js | 104 ++++ .../js/qpid/management/moveCopyMessages.js | 137 +++++ .../resources/js/qpid/management/showMessage.js | 142 +++++ .../java/resources/js/qpid/management/treeView.js | 313 ++++++++++ .../src/main/java/resources/management.html | 92 +++ .../src/main/java/resources/moveCopyMessages.html | 36 ++ .../src/main/java/resources/showAuthProvider.html | 25 + .../src/main/java/resources/showBroker.html | 25 + .../src/main/java/resources/showConnection.html | 47 ++ .../src/main/java/resources/showExchange.html | 46 ++ .../src/main/java/resources/showMessage.html | 73 +++ .../src/main/java/resources/showQueue.html | 97 +++ .../src/main/java/resources/showVirtualHost.html | 84 +++ java/broker-plugins/management-jmx/MANIFEST.MF | 66 ++ java/broker-plugins/management-jmx/build.xml | 47 ++ .../apache/qpid/server/jmx/AMQManagedObject.java | 84 +++ .../qpid/server/jmx/DefaultManagedObject.java | 189 ++++++ .../org/apache/qpid/server/jmx/JMXActivator.java | 136 +++++ .../apache/qpid/server/jmx/JMXConfiguration.java | 76 +++ .../qpid/server/jmx/JMXManagedObjectRegistry.java | 499 ++++++++++++++++ .../org/apache/qpid/server/jmx/JMXService.java | 193 ++++++ .../apache/qpid/server/jmx/MBeanIntrospector.java | 400 +++++++++++++ .../server/jmx/MBeanInvocationHandlerImpl.java | 382 ++++++++++++ .../org/apache/qpid/server/jmx/MBeanProvider.java | 52 ++ .../org/apache/qpid/server/jmx/ManagedObject.java | 57 ++ .../qpid/server/jmx/ManagedObjectRegistry.java | 48 ++ .../mbeans/AbstractStatisticsGatheringMBean.java | 200 +++++++ .../jmx/mbeans/ConfigurationManagementMBean.java | 56 ++ .../qpid/server/jmx/mbeans/ConnectionMBean.java | 182 ++++++ .../qpid/server/jmx/mbeans/ExchangeMBean.java | 313 ++++++++++ .../server/jmx/mbeans/LoggingManagementMBean.java | 324 ++++++++++ .../apache/qpid/server/jmx/mbeans/MBeanUtils.java | 57 ++ .../apache/qpid/server/jmx/mbeans/QueueMBean.java | 663 +++++++++++++++++++++ .../server/jmx/mbeans/ServerInformationMBean.java | 89 +++ .../apache/qpid/server/jmx/mbeans/Shutdown.java | 137 +++++ .../qpid/server/jmx/mbeans/ShutdownMBean.java | 58 ++ .../server/jmx/mbeans/UserManagementMBean.java | 179 ++++++ .../qpid/server/jmx/mbeans/VirtualHostMBean.java | 211 +++++++ .../server/jmx/mbeans/VirtualHostManagerMBean.java | 238 ++++++++ .../qpid/server/jmx/NoopManagedObjectRegistry.java | 46 ++ .../server/jmx/mbeans/ConnectionMBeanTest.java | 237 ++++++++ .../qpid/server/jmx/mbeans/ExchangeMBeanTest.java | 234 ++++++++ .../jmx/mbeans/LoggingManagementMBeanTest.java | 245 ++++++++ .../qpid/server/jmx/mbeans/MBeanTestUtils.java | 40 ++ .../qpid/server/jmx/mbeans/QueueMBeanTest.java | 368 ++++++++++++ .../jmx/mbeans/ServerInformationMBeanTest.java | 94 +++ .../server/jmx/mbeans/UserManagementMBeanTest.java | 157 +++++ .../jmx/mbeans/VirtualHostManagerMBeanTest.java | 174 ++++++ .../management/jmx/BrokerManagementTest.java | 128 ++++ .../management/jmx/ConnectionManagementTest.java | 283 +++++++++ .../management/jmx/LoggingManagementTest.java | 149 +++++ .../management/jmx/ManagementActorLoggingTest.java | 480 +++++++++++++++ .../management/jmx/ManagementLoggingTest.java | 317 ++++++++++ .../management/jmx/QueueManagementTest.java | 614 +++++++++++++++++++ .../systest/management/jmx/StatisticsTest.java | 204 +++++++ .../systest/management/jmx/UserManagementTest.java | 251 ++++++++ .../UserManagementWithBase64MD5PasswordsTest.java | 39 ++ java/broker-plugins/management/MANIFEST.MF | 66 -- java/broker-plugins/management/build.xml | 43 -- .../qpid/server/management/plugin/Management.java | 155 ----- .../management/plugin/ManagementActivator.java | 72 --- .../management/plugin/ManagementConfiguration.java | 77 --- .../plugin/servlet/DefinedFileServlet.java | 79 --- .../management/plugin/servlet/FileServlet.java | 109 ---- .../plugin/servlet/api/ExchangesServlet.java | 208 ------- .../plugin/servlet/api/VhostsServlet.java | 118 ---- .../plugin/servlet/rest/AbstractServlet.java | 215 ------- .../plugin/servlet/rest/KeyComparator.java | 53 -- .../plugin/servlet/rest/LogRecordsServlet.java | 86 --- .../plugin/servlet/rest/MapComparator.java | 74 --- .../plugin/servlet/rest/MessageContentServlet.java | 177 ------ .../plugin/servlet/rest/MessageServlet.java | 503 ---------------- .../plugin/servlet/rest/RestServlet.java | 577 ------------------ .../plugin/servlet/rest/SaslServlet.java | 253 -------- .../plugin/servlet/rest/StructureServlet.java | 104 ---- .../src/main/java/resources/addBinding.html | 42 -- .../src/main/java/resources/addExchange.html | 53 -- .../src/main/java/resources/addQueue.html | 174 ------ .../resources/authenticationprovider/addUser.html | 42 -- .../authenticationprovider/setPassword.html | 42 -- ...showPrincipalDatabaseAuthenticationManager.html | 29 - .../src/main/java/resources/css/common.css | 92 --- .../management/src/main/java/resources/footer.html | 28 - .../src/main/java/resources/images/qpid-logo.png | Bin 6600 -> 0 bytes .../java/resources/js/qpid/authorization/sasl.js | 213 ------- .../resources/js/qpid/common/UpdatableStore.js | 110 ---- .../main/java/resources/js/qpid/common/footer.js | 30 - .../java/resources/js/qpid/common/formatter.js | 99 --- .../java/resources/js/qpid/common/properties.js | 26 - .../main/java/resources/js/qpid/common/updater.js | 45 -- .../src/main/java/resources/js/qpid/common/util.js | 56 -- .../js/qpid/management/AuthenticationProvider.js | 122 ---- .../java/resources/js/qpid/management/Broker.js | 205 ------- .../resources/js/qpid/management/Connection.js | 213 ------- .../java/resources/js/qpid/management/Exchange.js | 229 ------- .../java/resources/js/qpid/management/Queue.js | 438 -------------- .../resources/js/qpid/management/VirtualHost.js | 327 ---------- .../resources/js/qpid/management/addBinding.js | 223 ------- .../resources/js/qpid/management/addExchange.js | 147 ----- .../java/resources/js/qpid/management/addQueue.js | 158 ----- .../PrincipalDatabaseAuthenticationManager.js | 327 ---------- .../resources/js/qpid/management/controller.js | 104 ---- .../js/qpid/management/moveCopyMessages.js | 137 ----- .../resources/js/qpid/management/showMessage.js | 142 ----- .../java/resources/js/qpid/management/treeView.js | 313 ---------- .../src/main/java/resources/management.html | 92 --- .../src/main/java/resources/moveCopyMessages.html | 36 -- .../src/main/java/resources/showAuthProvider.html | 25 - .../src/main/java/resources/showBroker.html | 25 - .../src/main/java/resources/showConnection.html | 47 -- .../src/main/java/resources/showExchange.html | 46 -- .../src/main/java/resources/showMessage.html | 73 --- .../src/main/java/resources/showQueue.html | 97 --- .../src/main/java/resources/showVirtualHost.html | 84 --- java/build.deps | 2 +- java/systests/build.xml | 2 +- 207 files changed, 16662 insertions(+), 16662 deletions(-) delete mode 100644 java/broker-plugins/jmx/MANIFEST.MF delete mode 100644 java/broker-plugins/jmx/build.xml delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/MBeanUtils.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java delete mode 100644 java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBeanTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/MBeanTestUtils.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBeanTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java delete mode 100644 java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java create mode 100644 java/broker-plugins/management-http/MANIFEST.MF create mode 100644 java/broker-plugins/management-http/build.xml create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java create mode 100644 java/broker-plugins/management-http/src/main/java/resources/addBinding.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/addExchange.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/addQueue.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/addUser.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/setPassword.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/css/common.css create mode 100644 java/broker-plugins/management-http/src/main/java/resources/footer.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/images/qpid-logo.png create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/UpdatableStore.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/footer.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/formatter.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/properties.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/updater.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Connection.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addBinding.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addExchange.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/moveCopyMessages.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/showMessage.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/management.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/moveCopyMessages.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/showAuthProvider.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/showBroker.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/showConnection.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/showExchange.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/showMessage.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/showQueue.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html create mode 100644 java/broker-plugins/management-jmx/MANIFEST.MF create mode 100644 java/broker-plugins/management-jmx/build.xml create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/MBeanUtils.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBeanTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/MBeanTestUtils.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBeanTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java delete mode 100644 java/broker-plugins/management/MANIFEST.MF delete mode 100644 java/broker-plugins/management/build.xml delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/Management.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java delete mode 100644 java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java delete mode 100644 java/broker-plugins/management/src/main/java/resources/addBinding.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/addExchange.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/addQueue.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/authenticationprovider/addUser.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/authenticationprovider/setPassword.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/css/common.css delete mode 100644 java/broker-plugins/management/src/main/java/resources/footer.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/images/qpid-logo.png delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/authorization/sasl.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/common/UpdatableStore.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/common/footer.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/common/formatter.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/common/properties.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/common/updater.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/common/util.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/AuthenticationProvider.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/Broker.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/Connection.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/Exchange.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/Queue.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/VirtualHost.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/addBinding.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/addExchange.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/addQueue.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/controller.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/moveCopyMessages.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/showMessage.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/js/qpid/management/treeView.js delete mode 100644 java/broker-plugins/management/src/main/java/resources/management.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/moveCopyMessages.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/showAuthProvider.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/showBroker.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/showConnection.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/showExchange.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/showMessage.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/showQueue.html delete mode 100644 java/broker-plugins/management/src/main/java/resources/showVirtualHost.html (limited to 'java') diff --git a/java/bdbstore/jmx/MANIFEST.MF b/java/bdbstore/jmx/MANIFEST.MF index 7046c4326d..ee59bc3ad8 100644 --- a/java/bdbstore/jmx/MANIFEST.MF +++ b/java/bdbstore/jmx/MANIFEST.MF @@ -8,7 +8,7 @@ Bundle-DocURL: http://www.apache.org/ Bundle-Version: 1.0.0 Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-ClassPath: . -Fragment-Host: broker-plugins-jmx +Fragment-Host: broker-plugins-management-jmx Import-Package: org.apache.qpid, org.apache.qpid.management.common.mbeans.annotations, org.apache.qpid.server.model, diff --git a/java/bdbstore/jmx/build.xml b/java/bdbstore/jmx/build.xml index d4ce4ea7d1..229631555d 100644 --- a/java/bdbstore/jmx/build.xml +++ b/java/bdbstore/jmx/build.xml @@ -17,13 +17,13 @@ - under the License. --> - + - + diff --git a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java index 455573f7bc..cfcea602b4 100644 --- a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java +++ b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java @@ -45,7 +45,7 @@ import org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore; *

* At runtime, the classloader loading this clas must have visibility of the other Qpid JMX classes. This is * currently arranged through OSGI using the fragment feature so that this bundle shares the - * same classloader as broker-plugins-jmx. See the Fragment-Host: header within the MANIFEST.MF + * same classloader as broker-plugins-management-jmx. See the Fragment-Host: header within the MANIFEST.MF * of this bundle. *

*/ diff --git a/java/broker-plugins/jmx/MANIFEST.MF b/java/broker-plugins/jmx/MANIFEST.MF deleted file mode 100644 index 268f11b67f..0000000000 --- a/java/broker-plugins/jmx/MANIFEST.MF +++ /dev/null @@ -1,66 +0,0 @@ -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.log4j, - org.apache.qpid.server.logging.actors, - org.apache.qpid.server.logging.messages, - org.apache.qpid.server.message, - org.apache.qpid.server.model, - org.apache.qpid.server.model.adapter, - org.apache.qpid.server.model.impl, - org.apache.qpid.server.configuration, - org.apache.qpid.server.configuration.plugins, - org.apache.qpid.server.connection, - org.apache.qpid.server.plugins, - org.apache.qpid.server.protocol, - org.apache.qpid.server.queue, - org.apache.qpid.server.registry, - org.apache.qpid.server.security, - org.apache.qpid.server.security.access, - org.apache.qpid.server.stats, - org.apache.qpid.server.virtualhost, - org.apache.qpid.util, - org.apache.commons.codec;version=1.3.0, - org.apache.commons.codec.binary;version=1.3.0, - org.apache.commons.configuration;version=1.0.0, - org.apache.commons.lang;version=1.0.0, - org.apache.commons.lang.builder;version=1.0.0, - org.apache.commons.lang.time;version=1.0.0, - org.apache.log4j;version=1.2.16, - org.codehaus.jackson;version=1.9.0, - org.codehaus.jackson.map;version=1.9.0, - javax.management.remote.rmi, - javax.management.remote, - javax.servlet, - javax.servlet.http, - javax.management;version=1.0.0, - javax.management.monitor;version=1.0.0, - javax.management.openmbean;version=1.0.0, - javax.security.auth.login;version=1.0.0, - javax.security.auth;version=1.0.0, - javax.rmi.ssl;version=1.0.0, - org.osgi.util.tracker;version=1.0.0, - org.osgi.framework;version=1.3 -Export-Package: org.apache.qpid.server.jmx;uses:="org.osgi.framework" diff --git a/java/broker-plugins/jmx/build.xml b/java/broker-plugins/jmx/build.xml deleted file mode 100644 index a5dd87c6f9..0000000000 --- a/java/broker-plugins/jmx/build.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java deleted file mode 100644 index 5c39a0c26a..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx; - -import java.util.concurrent.atomic.AtomicLong; - -import javax.management.ListenerNotFoundException; -import javax.management.NotCompliantMBeanException; -import javax.management.NotificationBroadcaster; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; - -/** - * This class provides additional feature of Notification Broadcaster to the - * DefaultManagedObject. - * @author Bhupendra Bhardwaj - * @version 0.1 - */ -public abstract class AMQManagedObject extends DefaultManagedObject - implements NotificationBroadcaster -{ - private final NotificationBroadcasterSupport _broadcaster = new NotificationBroadcasterSupport(); - - private AtomicLong _notificationSequenceNumber = new AtomicLong(); - - protected AMQManagedObject(Class managementInterface, String typeName, ManagedObjectRegistry registry) - throws NotCompliantMBeanException - { - super(managementInterface, typeName, registry); - // CurrentActor will be defined as these objects are created during - // broker startup. - - } - - // notification broadcaster implementation - - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, - Object handback) - { - _broadcaster.addNotificationListener(listener, filter, handback); - } - - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException - { - _broadcaster.removeNotificationListener(listener); - } - - - /** - * broadcaster support class - */ - protected NotificationBroadcasterSupport getBroadcaster() - { - return _broadcaster; - } - - protected long incrementAndGetSequenceNumber() - { - return _notificationSequenceNumber.incrementAndGet(); - } - - -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.java deleted file mode 100644 index 4446f96802..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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.log4j.Logger; - -import javax.management.JMException; -import javax.management.MBeanInfo; -import javax.management.MBeanNotificationInfo; -import javax.management.MalformedObjectNameException; -import javax.management.NotCompliantMBeanException; -import javax.management.ObjectName; -import javax.management.StandardMBean; - -/** - * Provides implementation of the boilerplate ManagedObject interface. Most managed objects should find it useful - * to extend this class rather than implementing ManagedObject from scratch. - * - */ -public abstract class DefaultManagedObject extends StandardMBean implements ManagedObject -{ - private static final Logger LOGGER = Logger.getLogger(DefaultManagedObject.class); - - private final Class _managementInterface; - - private final String _typeName; - - private final MBeanInfo _mbeanInfo; - - private ManagedObjectRegistry _registry; - - 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() - { - return _mbeanInfo; - } - - public String getType() - { - return _typeName; - } - - public Class getManagementInterface() - { - return _managementInterface; - } - - public abstract ManagedObject getParentObject(); - - - public void register() throws JMException - { - _registry.registerObject(this); - } - - public void unregister() throws JMException - { - try - { - if(_registry != null) - { - _registry.unregisterObject(this); - } - } - finally - { - _registry = null; - } - } - - public String toString() - { - return getObjectInstanceName() + "[" + getType() + "]"; - } - - /** - * Created the ObjectName as per the JMX Specs - * @return ObjectName - * @throws javax.management.MalformedObjectNameException - */ - public ObjectName getObjectName() throws MalformedObjectNameException - { - String name = getObjectInstanceName(); - StringBuffer objectName = new StringBuffer(ManagedObject.DOMAIN); - - objectName.append(":type="); - objectName.append(getHierarchicalType(this)); - - objectName.append(","); - objectName.append(getHierarchicalName(this)); - objectName.append("name=").append(name); - - return new ObjectName(objectName.toString()); - } - - protected ObjectName getObjectNameForSingleInstanceMBean() throws MalformedObjectNameException - { - StringBuffer objectName = new StringBuffer(ManagedObject.DOMAIN); - - objectName.append(":type="); - objectName.append(getHierarchicalType(this)); - - String hierarchyName = getHierarchicalName(this); - if (hierarchyName != null) - { - objectName.append(","); - objectName.append(hierarchyName.substring(0, hierarchyName.lastIndexOf(","))); - } - - return new ObjectName(objectName.toString()); - } - - protected String getHierarchicalType(ManagedObject obj) - { - if (obj.getParentObject() != null) - { - String parentType = getHierarchicalType(obj.getParentObject()).toString(); - return parentType + "." + obj.getType(); - } - else - { - return obj.getType(); - } - } - - protected String getHierarchicalName(ManagedObject obj) - { - if (obj.getParentObject() != null) - { - String parentName = obj.getParentObject().getType() + "=" + - obj.getParentObject().getObjectInstanceName() + ","+ - getHierarchicalName(obj.getParentObject()); - - return parentName; - } - else - { - return ""; - } - } - - private MBeanInfo buildMBeanInfo() throws NotCompliantMBeanException - { - return new MBeanInfo(this.getClass().getName(), - MBeanIntrospector.getMBeanDescription(this.getClass()), - MBeanIntrospector.getMBeanAttributesInfo(getManagementInterface()), - MBeanIntrospector.getMBeanConstructorsInfo(this.getClass()), - MBeanIntrospector.getMBeanOperationsInfo(getManagementInterface()), - this.getNotificationInfo()); - } - - public MBeanNotificationInfo[] getNotificationInfo() - { - return null; - } -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java deleted file mode 100644 index c588b40de7..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.log4j.Logger; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; - -public class JMXActivator implements BundleActivator -{ - private static final Logger LOGGER = Logger.getLogger(JMXActivator.class); - - private String _bundleName; - private JMXService _jmxService; - - private List _registeredServices; - - - public void start(final BundleContext ctx) throws Exception - { - boolean jmxManagementEnabled = ApplicationRegistry.getInstance().getConfiguration().getJMXManagementEnabled(); - - if (jmxManagementEnabled) - { - _jmxService = new JMXService(); - startJmsService(_jmxService); - - _bundleName = ctx.getBundle().getSymbolicName(); - - _registeredServices = registerServices(ctx); - } - else - { - LOGGER.debug("Skipping registration of JMX plugin as JMX Management disabled in config. "); - } - } - - public void stop(final BundleContext bundleContext) throws Exception - { - try - { - if (_jmxService != null) - { - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Stopping jmx plugin: " + _bundleName); - } - _jmxService.close(); - } - - if (_registeredServices != null) - { - unregisterServices(); - } - } - finally - { - _jmxService = null; - _registeredServices = null; - } - } - - - private List registerServices(BundleContext ctx) - { - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Registering jmx plugin: " + _bundleName); - } - - List serviceRegistrations = new ArrayList(); - - ServiceRegistration jmxServiceRegistration = ctx.registerService(JMXService.class.getName(), _jmxService, null); - ServiceRegistration jmxConfigFactoryRegistration = ctx.registerService(ConfigurationPluginFactory.class.getName(), JMXConfiguration.FACTORY, null); - - serviceRegistrations.add(jmxServiceRegistration); - serviceRegistrations.add(jmxConfigFactoryRegistration); - return serviceRegistrations; - } - - private void startJmsService(JMXService jmxService) throws Exception - { - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Starting JMX service"); - } - boolean startedSuccessfully = false; - try - { - jmxService.start(); - startedSuccessfully = true; - } - finally - { - if (!startedSuccessfully) - { - LOGGER.error("JMX failed to start normally, closing service"); - jmxService.close(); - } - } - } - - private void unregisterServices() - { - for (Iterator iterator = _registeredServices.iterator(); iterator.hasNext();) - { - ServiceRegistration service = iterator.next(); - service.unregister(); - } - } -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java deleted file mode 100644 index dc9a712f90..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; - -import java.util.Arrays; -import java.util.List; - -public class JMXConfiguration extends ConfigurationPlugin -{ - CompositeConfiguration _finalConfig; - - public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() - { - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException - { - ConfigurationPlugin instance = new JMXConfiguration(); - instance.setConfiguration(path, config); - return instance; - } - - public List getParentPaths() - { - return Arrays.asList("jmx"); - } - }; - - public String[] getElementsProcessed() - { - return new String[] { "" }; - } - - public Configuration getConfiguration() - { - return _finalConfig; - } - - - @Override - public void validateConfiguration() throws ConfigurationException - { - // Valid Configuration either has xml links to new files - _finalConfig = new CompositeConfiguration(getConfig()); - List subFiles = getConfig().getList("xml[@fileName]"); - for (Object subFile : subFiles) - { - _finalConfig.addConfiguration(new XMLConfiguration((String) subFile)); - } - - } - -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java deleted file mode 100644 index 0648235077..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java +++ /dev/null @@ -1,499 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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.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; -import java.lang.management.ManagementFactory; -import java.lang.reflect.Proxy; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.UnknownHostException; -import java.rmi.AlreadyBoundException; -import java.rmi.NoSuchObjectException; -import java.rmi.NotBoundException; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; -import java.rmi.server.RMIClientSocketFactory; -import java.rmi.server.RMIServerSocketFactory; -import java.rmi.server.UnicastRemoteObject; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * This class starts up an MBeanserver. If out of the box agent has been enabled then there are no - * security features implemented like user authentication and authorisation. - */ -public class JMXManagedObjectRegistry implements ManagedObjectRegistry -{ - private static final Logger _log = Logger.getLogger(JMXManagedObjectRegistry.class); - - private final MBeanServer _mbeanServer; - private JMXConnectorServer _cs; - private Registry _rmiRegistry; - private boolean _useCustomSocketFactory; - - private final int _jmxPortRegistryServer; - private final int _jmxPortConnectorServer; - - public JMXManagedObjectRegistry() throws AMQException - { - _log.info("Initialising managed object registry using platform MBean server"); - IApplicationRegistry appRegistry = ApplicationRegistry.getInstance(); - - // Retrieve the config parameters - _useCustomSocketFactory = appRegistry.getConfiguration().getUseCustomRMISocketFactory(); - boolean platformServer = appRegistry.getConfiguration().getPlatformMbeanserver(); - - _mbeanServer = - platformServer ? ManagementFactory.getPlatformMBeanServer() - : MBeanServerFactory.createMBeanServer(ManagedObject.DOMAIN); - - _jmxPortRegistryServer = appRegistry.getConfiguration().getJMXPortRegistryServer(); - _jmxPortConnectorServer = appRegistry.getConfiguration().getJMXConnectorServerPort(); - - } - - public void start() throws IOException, ConfigurationException - { - - CurrentActor.get().message(ManagementConsoleMessages.STARTUP()); - - //check if system properties are set to use the JVM's out-of-the-box JMXAgent - if (areOutOfTheBoxJMXOptionsSet()) - { - CurrentActor.get().message(ManagementConsoleMessages.READY(true)); - return; - } - - IApplicationRegistry appRegistry = ApplicationRegistry.getInstance(); - - - //Socket factories for the RMIConnectorServer, either default or SLL depending on configuration - RMIClientSocketFactory csf; - RMIServerSocketFactory ssf; - - //check ssl enabled option in config, default to true if option is not set - boolean sslEnabled = appRegistry.getConfiguration().getManagementSSLEnabled(); - - if (sslEnabled) - { - //set the SSL related system properties used by the SSL RMI socket factories to the values - //given in the configuration file, unless command line settings have already been specified - String keyStorePath; - - if(System.getProperty("javax.net.ssl.keyStore") != null) - { - keyStorePath = System.getProperty("javax.net.ssl.keyStore"); - } - else - { - keyStorePath = appRegistry.getConfiguration().getManagementKeyStorePath(); - } - - //check the keystore path value is valid - if (keyStorePath == null) - { - throw new ConfigurationException("JMX management SSL keystore path not defined, " + - "unable to start SSL protected JMX ConnectorServer"); - } - else - { - //ensure the system property is set - System.setProperty("javax.net.ssl.keyStore", keyStorePath); - - //check the file is usable - File ksf = new File(keyStorePath); - - if (!ksf.exists()) - { - throw new FileNotFoundException("Cannot find JMX management SSL keystore file: " + ksf); - } - if (!ksf.canRead()) - { - throw new FileNotFoundException("Cannot read JMX management SSL keystore file: " - + ksf + ". Check permissions."); - } - - CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(ksf.getAbsolutePath())); - } - - //check the key store password is set - if (System.getProperty("javax.net.ssl.keyStorePassword") == null) - { - - if (appRegistry.getConfiguration().getManagementKeyStorePassword() == null) - { - throw new ConfigurationException("JMX management SSL keystore password not defined, " + - "unable to start requested SSL protected JMX server"); - } - else - { - System.setProperty("javax.net.ssl.keyStorePassword", - appRegistry.getConfiguration().getManagementKeyStorePassword()); - } - } - - //create the SSL RMI socket factories - csf = new SslRMIClientSocketFactory(); - ssf = new SslRMIServerSocketFactory(); - } - else - { - //Do not specify any specific RMI socket factories, resulting in use of the defaults. - csf = null; - ssf = null; - } - - //add a JMXAuthenticator implementation the env map to authenticate the RMI based JMX connector server - RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator(new InetSocketAddress(_jmxPortRegistryServer)); - HashMap env = new HashMap(); - env.put(JMXConnectorServer.AUTHENTICATOR, rmipa); - - /* - * Start a RMI registry on the management port, to hold the JMX RMI ConnectorServer stub. - * Using custom socket factory to prevent anyone (including us unfortunately) binding to the registry using RMI. - * As a result, only binds made using the object reference will succeed, thus securing it from external change. - */ - System.setProperty("java.rmi.server.randomIDs", "true"); - if(_useCustomSocketFactory) - { - _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, new CustomRMIServerSocketFactory()); - } - else - { - _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, null); - } - - CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", _jmxPortRegistryServer)); - - /* - * We must now create the RMI ConnectorServer manually, as the JMX Factory methods use RMI calls - * to bind the ConnectorServer to the registry, which will now fail as for security we have - * locked it from any RMI based modifications, including our own. Instead, we will manually bind - * the RMIConnectorServer stub to the registry using its object reference, which will still succeed. - * - * The registry is exported on the defined management port 'port'. We will export the RMIConnectorServer - * on 'port +1'. Use of these two well-defined ports will ease any navigation through firewall's. - */ - final Map connectionIdUsernameMap = new ConcurrentHashMap(); - final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(_jmxPortConnectorServer, csf, ssf, env) - { - - /** - * Override makeClient so we can cache the username of the client in a Map keyed by connectionId. - * ConnectionId is guaranteed to be unique per client connection, according to the JMS spec. - * An instance of NotificationListener (mapCleanupListener) will be responsible for removing these Map - * entries. - * - * @see javax.management.remote.rmi.RMIJRMPServerImpl#makeClient(String, javax.security.auth.Subject) - */ - @Override - protected RMIConnection makeClient(String connectionId, Subject subject) throws IOException - { - final RMIConnection makeClient = super.makeClient(connectionId, subject); - final UsernamePrincipal usernamePrincipalFromSubject = UsernamePrincipal.getUsernamePrincipalFromSubject(subject); - connectionIdUsernameMap.put(connectionId, usernamePrincipalFromSubject.getName()); - return makeClient; - } - }; - - // Create a Listener responsible for removing the map entries add by the #makeClient entry above. - final NotificationListener mapCleanupListener = new NotificationListener() - { - - public void handleNotification(Notification notification, Object handback) - { - final String connectionId = ((JMXConnectionNotification) notification).getConnectionId(); - connectionIdUsernameMap.remove(connectionId); - } - }; - - String localHost; - try - { - localHost = InetAddress.getLocalHost().getHostName(); - } - catch(UnknownHostException ex) - { - localHost="127.0.0.1"; - } - final String hostname = localHost; - final JMXServiceURL externalUrl = new JMXServiceURL( - "service:jmx:rmi://"+hostname+":"+(_jmxPortConnectorServer)+"/jndi/rmi://"+hostname+":"+_jmxPortRegistryServer+"/jmxrmi"); - - final JMXServiceURL internalUrl = new JMXServiceURL("rmi", hostname, _jmxPortConnectorServer); - _cs = new RMIConnectorServer(internalUrl, env, rmiConnectorServerStub, _mbeanServer) - { - @Override - public synchronized void start() throws IOException - { - try - { - //manually bind the connector server to the registry at key 'jmxrmi', like the out-of-the-box agent - _rmiRegistry.bind("jmxrmi", rmiConnectorServerStub); - } - catch (AlreadyBoundException abe) - { - //key was already in use. shouldnt happen here as its a new registry, unbindable by normal means. - - //IOExceptions are the only checked type throwable by the method, wrap and rethrow - IOException ioe = new IOException(abe.getMessage()); - ioe.initCause(abe); - throw ioe; - } - - //now do the normal tasks - super.start(); - } - - @Override - public synchronized void stop() throws IOException - { - try - { - if (_rmiRegistry != null) - { - _rmiRegistry.unbind("jmxrmi"); - } - } - catch (NotBoundException nbe) - { - // TODO consider if we want to keep new logging - _log.error("Failed to unbind jmxrmi", nbe); - //ignore - } - - //now do the normal tasks - super.stop(); - } - - @Override - public JMXServiceURL getAddress() - { - //must return our pre-crafted url that includes the full details, inc JNDI details - return externalUrl; - } - - }; - - - //Add the custom invoker as an MBeanServerForwarder, and start the RMIConnectorServer. - MBeanServerForwarder mbsf = MBeanInvocationHandlerImpl.newProxyInstance(); - _cs.setMBeanServerForwarder(mbsf); - - - // Get the handler that is used by the above MBInvocationHandler Proxy. - // which is the MBeanInvocationHandlerImpl and so also a NotificationListener. - final NotificationListener invocationHandler = (NotificationListener) Proxy.getInvocationHandler(mbsf); - - // Install a notification listener on OPENED, CLOSED, and FAILED, - // passing the map of connection-ids to usernames as hand-back data. - final NotificationFilterSupport invocationHandlerFilter = new NotificationFilterSupport(); - invocationHandlerFilter.enableType(JMXConnectionNotification.OPENED); - invocationHandlerFilter.enableType(JMXConnectionNotification.CLOSED); - invocationHandlerFilter.enableType(JMXConnectionNotification.FAILED); - _cs.addNotificationListener(invocationHandler, invocationHandlerFilter, connectionIdUsernameMap); - - // Install a second notification listener on CLOSED AND FAILED only to remove the entry from the - // Map. Here we rely on the fact that JMX will call the listeners in the order in which they are - // installed. - final NotificationFilterSupport mapCleanupHandlerFilter = new NotificationFilterSupport(); - mapCleanupHandlerFilter.enableType(JMXConnectionNotification.CLOSED); - mapCleanupHandlerFilter.enableType(JMXConnectionNotification.FAILED); - _cs.addNotificationListener(mapCleanupListener, mapCleanupHandlerFilter, null); - - _cs.start(); - - String connectorServer = (sslEnabled ? "SSL " : "") + "JMX RMIConnectorServer"; - CurrentActor.get().message(ManagementConsoleMessages.LISTENING(connectorServer, _jmxPortConnectorServer)); - - CurrentActor.get().message(ManagementConsoleMessages.READY(false)); - } - - /* - * Custom RMIServerSocketFactory class, used to prevent updates to the RMI registry. - * Supplied to the registry at creation, this will prevent RMI-based operations on the - * registry such as attempting to bind a new object, thereby securing it from tampering. - * This is accomplished by always returning null when attempting to determine the address - * of the caller, thus ensuring the registry will refuse the attempt. Calls to bind etc - * made using the object reference will not be affected and continue to operate normally. - */ - - private static class CustomRMIServerSocketFactory implements RMIServerSocketFactory - { - - public ServerSocket createServerSocket(int port) throws IOException - { - return new NoLocalAddressServerSocket(port); - } - - private static class NoLocalAddressServerSocket extends ServerSocket - { - NoLocalAddressServerSocket(int port) throws IOException - { - super(port); - } - - @Override - public Socket accept() throws IOException - { - Socket s = new NoLocalAddressSocket(); - super.implAccept(s); - return s; - } - } - - private static class NoLocalAddressSocket extends Socket - { - @Override - public InetAddress getInetAddress() - { - return null; - } - } - } - - - public void registerObject(ManagedObject managedObject) throws JMException - { - _mbeanServer.registerMBean(managedObject, managedObject.getObjectName()); - } - - public void unregisterObject(ManagedObject managedObject) throws JMException - { - _mbeanServer.unregisterMBean(managedObject.getObjectName()); - } - - // checks if the system properties are set which enable the JVM's out-of-the-box JMXAgent. - private boolean areOutOfTheBoxJMXOptionsSet() - { - if (System.getProperty("com.sun.management.jmxremote") != null) - { - return true; - } - - if (System.getProperty("com.sun.management.jmxremote.port") != null) - { - return true; - } - - return false; - } - - //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 - try - { - CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("JMX RMIConnectorServer", _cs.getAddress().getPort())); - _cs.stop(); - } - catch (IOException e) - { - _log.error("Exception while closing the JMX ConnectorServer: ", e); - } - } - - if (_rmiRegistry != null) - { - // Stopping the RMI registry - CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _jmxPortRegistryServer)); - try - { - 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); - } - } - - //ObjectName query to gather all Qpid related MBeans - ObjectName mbeanNameQuery = null; - try - { - mbeanNameQuery = new ObjectName(ManagedObject.DOMAIN + ":*"); - } - catch (Exception e1) - { - _log.warn("Unable to generate MBean ObjectName query for close operation"); - } - - for (ObjectName name : _mbeanServer.queryNames(mbeanNameQuery, null)) - { - try - { - _mbeanServer.unregisterMBean(name); - } - catch (JMException e) - { - _log.error("Exception unregistering MBean '"+ name +"': " + e.getMessage()); - } - } - - CurrentActor.get().message(ManagementConsoleMessages.STOPPED()); - } - -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java deleted file mode 100644 index 7a232d2584..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.server.jmx; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.ServiceLoader; - -import javax.management.JMException; -import javax.management.StandardMBean; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.qpid.AMQException; -import org.apache.qpid.server.jmx.mbeans.LoggingManagementMBean; -import org.apache.qpid.server.jmx.mbeans.UserManagementMBean; -import org.apache.qpid.server.jmx.mbeans.ConfigurationManagementMBean; -import org.apache.qpid.server.jmx.mbeans.ServerInformationMBean; -import org.apache.qpid.server.jmx.mbeans.Shutdown; -import org.apache.qpid.server.jmx.mbeans.VirtualHostMBean; -import org.apache.qpid.server.logging.log4j.LoggingFacade; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.ConfigurationChangeListener; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.registry.ApplicationRegistry; - - -public class JMXService implements ConfigurationChangeListener -{ - private static final ClassLoader BUNDLE_CLASSLOADER = JMXService.class.getClassLoader(); - - private static final Logger LOGGER = Logger.getLogger(JMXService.class); - - private final Broker _broker; - private final JMXManagedObjectRegistry _objectRegistry; - private final Shutdown _shutdown; - private final ServerInformationMBean _serverInfo; - private final ConfigurationManagementMBean _configManagement; - private final LoggingManagementMBean _loggingManagement; - - private final Map _children = new HashMap(); - - public JMXService() throws AMQException, JMException - { - _broker = ApplicationRegistry.getInstance().getBroker(); - _objectRegistry = new JMXManagedObjectRegistry(); - - _broker.addChangeListener(this); - synchronized (_children) - { - for(VirtualHost virtualHost : _broker.getVirtualHosts()) - { - if(!_children.containsKey(virtualHost)) - { - _children.put(virtualHost, new VirtualHostMBean(virtualHost, _objectRegistry)); - } - } - } - _shutdown = new Shutdown(_objectRegistry); - _serverInfo = new ServerInformationMBean(_objectRegistry, _broker); - _configManagement = new ConfigurationManagementMBean(_objectRegistry); - _loggingManagement = new LoggingManagementMBean(LoggingFacade.getCurrentInstance(), _objectRegistry); - } - - public void start() throws IOException, ConfigurationException - { - _objectRegistry.start(); - } - - public void close() - { - _broker.removeChangeListener(this); - - _objectRegistry.close(); - } - - public void stateChanged(ConfiguredObject object, State oldState, State newState) - { - - } - - public void childAdded(ConfiguredObject object, ConfiguredObject child) - { - synchronized (_children) - { - try - { - AMQManagedObject mbean; - if(child instanceof VirtualHost) - { - VirtualHost vhostChild = (VirtualHost)child; - mbean = new VirtualHostMBean(vhostChild, _objectRegistry); - } - else if(child instanceof PasswordCredentialManagingAuthenticationProvider) - { - mbean = new UserManagementMBean((PasswordCredentialManagingAuthenticationProvider) child, _objectRegistry); - } - else - { - mbean = null; - } - - if (mbean != null) - { - createAdditionalMBeansFromProviders(child, mbean); - } - } - catch(JMException e) - { - LOGGER.error("Error creating mbean", e); - // TODO - Implement error reporting on mbean creation - } - } - } - - - public void childRemoved(ConfiguredObject object, ConfiguredObject child) - { - // TODO - implement vhost removal (possibly just removing the instanceof check below) - - synchronized (_children) - { - if(child instanceof PasswordCredentialManagingAuthenticationProvider) - { - AMQManagedObject mbean = _children.remove(child); - if(mbean != null) - { - try - { - mbean.unregister(); - } - catch(JMException e) - { - LOGGER.error("Error creating mbean", e); - //TODO - report error on removing child MBean - } - } - } - - } - } - - private void createAdditionalMBeansFromProviders(ConfiguredObject child, AMQManagedObject mbean) throws JMException - { - _children.put(child, mbean); - - for (Iterator iterator = getMBeanProviderIterator(); iterator.hasNext();) - { - MBeanProvider provider = iterator.next(); - LOGGER.debug("Consulting mbean provider : " + provider + " for child : " + child); - if (provider.isChildManageableByMBean(child)) - { - LOGGER.debug("Provider will create mbean "); - StandardMBean bean = provider.createMBean(child, mbean); - // TODO track the mbeans that have been created on behalf of a child in a map, then - // if the child is ever removed, destroy these beans too. - } - } - } - - /** - * Finds all classes implementing the {@link MBeanProvider} interface. This will find - * only those classes which are visible to the classloader of this OSGI bundle. - */ - private Iterator getMBeanProviderIterator() - { - return ServiceLoader.load(MBeanProvider.class, BUNDLE_CLASSLOADER).iterator(); - } -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java deleted file mode 100644 index 79ddc8cfc0..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java +++ /dev/null @@ -1,400 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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.qpid.management.common.mbeans.annotations.MBeanAttribute; -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.MBeanOperation; -import org.apache.qpid.management.common.mbeans.annotations.MBeanOperationParameter; - -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanConstructorInfo; -import javax.management.MBeanOperationInfo; -import javax.management.MBeanParameterInfo; -import javax.management.NotCompliantMBeanException; -import java.lang.annotation.Annotation; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -/** - * This class is a utility class to introspect the MBean class and the management - * interface class for various purposes. - * @author Bhupendra Bhardwaj - * @version 0.1 - */ -class MBeanIntrospector -{ - - private static final String _defaultAttributeDescription = "Management attribute"; - private static final String _defaultOerationDescription = "Management operation"; - private static final String _defaultConstructorDescription = "MBean constructor"; - private static final String _defaultMbeanDescription = "Management interface of the MBean"; - - private MBeanIntrospector() - { - } - - /** - * Introspects the management interface class for MBean attributes. - * @param interfaceClass - * @return MBeanAttributeInfo[] - * @throws javax.management.NotCompliantMBeanException - */ - static MBeanAttributeInfo[] getMBeanAttributesInfo(Class interfaceClass) - throws NotCompliantMBeanException - { - List attributesList = new ArrayList(); - - /** - * Using reflection, all methods of the managemetn interface will be analysed, - * and MBeanInfo will be created. - */ - for (Method method : interfaceClass.getMethods()) - { - String name = method.getName(); - Class resultType = method.getReturnType(); - MBeanAttributeInfo attributeInfo = null; - - if (isAttributeGetterMethod(method)) - { - String desc = getAttributeDescription(method); - attributeInfo = new MBeanAttributeInfo(name.substring(3), - resultType.getName(), - desc, - true, - false, - false); - int index = getIndexIfAlreadyExists(attributeInfo, attributesList); - if (index == -1) - { - attributesList.add(attributeInfo); - } - else - { - attributeInfo = new MBeanAttributeInfo(name.substring(3), - resultType.getName(), - desc, - true, - true, - false); - attributesList.set(index, attributeInfo); - } - } - else if (isAttributeSetterMethod(method)) - { - String desc = getAttributeDescription(method); - attributeInfo = new MBeanAttributeInfo(name.substring(3), - method.getParameterTypes()[0].getName(), - desc, - false, - true, - false); - int index = getIndexIfAlreadyExists(attributeInfo, attributesList); - if (index == -1) - { - attributesList.add(attributeInfo); - } - else - { - attributeInfo = new MBeanAttributeInfo(name.substring(3), - method.getParameterTypes()[0].getName(), - desc, - true, - true, - false); - attributesList.set(index, attributeInfo); - } - } - else if (isAttributeBoolean(method)) - { - attributeInfo = new MBeanAttributeInfo(name.substring(2), - resultType.getName(), - getAttributeDescription(method), - true, - false, - true); - attributesList.add(attributeInfo); - } - } - - return attributesList.toArray(new MBeanAttributeInfo[0]); - } - - /** - * Introspects the management interface class for management operations. - * @param interfaceClass - * @return MBeanOperationInfo[] - */ - static MBeanOperationInfo[] getMBeanOperationsInfo(Class interfaceClass) - { - List operationsList = new ArrayList(); - - for (Method method : interfaceClass.getMethods()) - { - if (!isAttributeGetterMethod(method) && - !isAttributeSetterMethod(method) && - !isAttributeBoolean(method)) - { - operationsList.add(getOperationInfo(method)); - } - } - - return operationsList.toArray(new MBeanOperationInfo[0]); - } - - /** - * Checks if the method is an attribute getter method. - * @param method - * @return true if the method is an attribute getter method. - */ - private static boolean isAttributeGetterMethod(Method method) - { - if (!(method.getName().equals("get")) && - method.getName().startsWith("get") && - method.getParameterTypes().length == 0 && - !method.getReturnType().equals(void.class)) - { - return true; - } - - return false; - } - - /** - * Checks if the method is an attribute setter method. - * @param method - * @return true if the method is an attribute setter method. - */ - private static boolean isAttributeSetterMethod(Method method) - { - if (!(method.getName().equals("set")) && - method.getName().startsWith("set") && - method.getParameterTypes().length == 1 && - method.getReturnType().equals(void.class)) - { - return true; - } - - return false; - } - - /** - * Checks if the attribute is a boolean and the method is a isX kind og method. - * @param method - * @return true if the method is an attribute isX type of method - */ - private static boolean isAttributeBoolean(Method method) - { - if (!(method.getName().equals("is")) && - method.getName().startsWith("is") && - method.getParameterTypes().length == 0 && - method.getReturnType().equals(boolean.class)) - { - return true; - } - - return false; - } - - /** - * Helper method to retrieve the attribute index from the list of attributes. - * @param attribute - * @param list - * @return attribute index no. -1 if attribtue doesn't exist - * @throws javax.management.NotCompliantMBeanException - */ - private static int getIndexIfAlreadyExists(MBeanAttributeInfo attribute, - List list) - throws NotCompliantMBeanException - { - String exceptionMsg = "Conflicting attribute methods for attribute " + attribute.getName(); - - for (MBeanAttributeInfo memberAttribute : list) - { - if (attribute.getName().equals(memberAttribute.getName())) - { - if (!attribute.getType().equals(memberAttribute.getType())) - { - throw new NotCompliantMBeanException(exceptionMsg); - } - if (attribute.isReadable() && memberAttribute.isReadable()) - { - if (attribute.isIs() != memberAttribute.isIs()) - { - throw new NotCompliantMBeanException(exceptionMsg); - } - } - - return list.indexOf(memberAttribute); - } - } - - return -1; - } - - /** - * Retrieves the attribute description from annotation - * @param attributeMethod - * @return attribute description - */ - private static String getAttributeDescription(Method attributeMethod) - { - MBeanAttribute anno = attributeMethod.getAnnotation(MBeanAttribute.class); - if (anno != null) - { - return anno.description(); - } - return _defaultAttributeDescription; - } - - /** - * Introspects the method to retrieve the operation information. - * @param operation - * @return MBeanOperationInfo - */ - private static MBeanOperationInfo getOperationInfo(Method operation) - { - MBeanOperationInfo operationInfo = null; - Class returnType = operation.getReturnType(); - - MBeanParameterInfo[] paramsInfo = getParametersInfo(operation.getParameterAnnotations(), - operation.getParameterTypes()); - - String operationDesc = _defaultOerationDescription; - int impact = MBeanOperationInfo.UNKNOWN; - - if (operation.getAnnotation(MBeanOperation.class) != null) - { - operationDesc = operation.getAnnotation(MBeanOperation.class).description(); - impact = operation.getAnnotation(MBeanOperation.class).impact(); - } - operationInfo = new MBeanOperationInfo(operation.getName(), - operationDesc, - paramsInfo, - returnType.getName(), - impact); - - return operationInfo; - } - - /** - * Constructs the parameter info. - * @param paramsAnno - * @param paramTypes - * @return MBeanParameterInfo[] - */ - private static MBeanParameterInfo[] getParametersInfo(Annotation[][] paramsAnno, - Class[] paramTypes) - { - int noOfParams = paramsAnno.length; - - MBeanParameterInfo[] paramsInfo = new MBeanParameterInfo[noOfParams]; - - for (int i = 0; i < noOfParams; i++) - { - MBeanParameterInfo paramInfo = null; - String type = paramTypes[i].getName(); - for (Annotation anno : paramsAnno[i]) - { - String name,desc; - if (MBeanOperationParameter.class.isInstance(anno)) - { - name = MBeanOperationParameter.class.cast(anno).name(); - desc = MBeanOperationParameter.class.cast(anno).description(); - paramInfo = new MBeanParameterInfo(name, type, desc); - } - } - - - if (paramInfo == null) - { - paramInfo = new MBeanParameterInfo("p " + (i + 1), type, "parameter " + (i + 1)); - } - if (paramInfo != null) - { - paramsInfo[i] = paramInfo; - } - } - - return paramsInfo; - } - - /** - * Introspects the MBean class for constructors - * @param implClass - * @return MBeanConstructorInfo[] - */ - static MBeanConstructorInfo[] getMBeanConstructorsInfo(Class implClass) - { - List constructors = new ArrayList(); - - for (Constructor cons : implClass.getConstructors()) - { - MBeanConstructorInfo constructorInfo = getMBeanConstructorInfo(cons); - if (constructorInfo != null) - { - constructors.add(constructorInfo); - } - } - - return constructors.toArray(new MBeanConstructorInfo[0]); - } - - /** - * Retrieves the constructor info from given constructor. - * @param cons - * @return MBeanConstructorInfo - */ - private static MBeanConstructorInfo getMBeanConstructorInfo(Constructor cons) - { - String desc = _defaultConstructorDescription; - Annotation anno = cons.getAnnotation(MBeanConstructor.class); - if (anno != null && MBeanConstructor.class.isInstance(anno)) - { - desc = MBeanConstructor.class.cast(anno).value(); - if(desc == null) - { - desc = _defaultConstructorDescription; - } - } - - return new MBeanConstructorInfo(cons.getName(), desc, null); - } - - /** - * Retrieves the description from the annotations of given class - * @param annotatedClass - * @return class description - */ - static String getMBeanDescription(Class annotatedClass) - { - Annotation anno = annotatedClass.getAnnotation(MBeanDescription.class); - if (anno != null && MBeanDescription.class.isInstance(anno)) - { - return MBeanDescription.class.cast(anno).value(); - } - return _defaultMbeanDescription; - } - -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java deleted file mode 100644 index 49f06d5121..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java +++ /dev/null @@ -1,382 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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.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; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.access.Operation; - -import javax.management.Attribute; -import javax.management.JMException; -import javax.management.MBeanInfo; -import javax.management.MBeanOperationInfo; -import javax.management.MBeanServer; -import javax.management.Notification; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.remote.JMXConnectionNotification; -import javax.management.remote.JMXPrincipal; -import javax.management.remote.MBeanServerForwarder; -import javax.security.auth.Subject; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.util.Map; -import java.util.Set; - -/** - * This class can be used by the JMXConnectorServer as an InvocationHandler for the mbean operations. It delegates - * JMX access decisions to the SecurityPlugin. - */ -public class MBeanInvocationHandlerImpl implements InvocationHandler, NotificationListener -{ - private static final Logger _logger = Logger.getLogger(MBeanInvocationHandlerImpl.class); - - private final IApplicationRegistry _appRegistry = ApplicationRegistry.getInstance(); - private final static String DELEGATE = "JMImplementation:type=MBeanServerDelegate"; - private MBeanServer _mbs; - private final ManagementActor _logActor = new ManagementActor(_appRegistry.getRootMessageLogger()); - private final boolean _managementRightsInferAllAccess = - _appRegistry.getConfiguration().getManagementRightsInferAllAccess(); - - public static MBeanServerForwarder newProxyInstance() - { - final InvocationHandler handler = new MBeanInvocationHandlerImpl(); - final Class[] interfaces = new Class[] { MBeanServerForwarder.class }; - - Object proxy = Proxy.newProxyInstance(MBeanServerForwarder.class.getClassLoader(), interfaces, handler); - return MBeanServerForwarder.class.cast(proxy); - } - - private boolean invokeDirectly(String methodName, Object[] args, Subject subject) - { - // Allow operations performed locally on behalf of the connector server itself - if (subject == null) - { - return true; - } - - if (args == null || DELEGATE.equals(args[0])) - { - return true; - } - - // Allow querying available object names and mbeans - if (methodName.equals("queryNames") || methodName.equals("queryMBeans")) - { - return true; - } - - if (args[0] instanceof ObjectName) - { - ObjectName mbean = (ObjectName) args[0]; - - if(!DefaultManagedObject.DOMAIN.equalsIgnoreCase(mbean.getDomain())) - { - return true; - } - } - - return false; - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable - { - String methodName = method.getName(); - - if (methodName.equals("getMBeanServer")) - { - return _mbs; - } - - if (methodName.equals("setMBeanServer")) - { - if (args[0] == null) - { - throw new IllegalArgumentException("Null MBeanServer"); - } - if (_mbs != null) - { - throw new IllegalArgumentException("MBeanServer object already initialized"); - } - _mbs = (MBeanServer) args[0]; - return null; - } - - // Restrict access to "createMBean" and "unregisterMBean" to any user - if (methodName.equals("createMBean") || methodName.equals("unregisterMBean")) - { - _logger.debug("User trying to create or unregister an MBean"); - throw new SecurityException("Access denied: " + methodName); - } - - // Retrieve Subject from current AccessControlContext - AccessControlContext acc = AccessController.getContext(); - Subject subject = Subject.getSubject(acc); - - try - { - if(invokeDirectly(methodName, args, subject)) - { - return method.invoke(_mbs, args); - } - - // Retrieve JMXPrincipal from Subject - Set principals = subject.getPrincipals(JMXPrincipal.class); - if (principals == null || principals.isEmpty()) - { - throw new SecurityException("Access denied: no JMX principal"); - } - - // Save the subject - SecurityManager.setThreadSubject(subject); - - // Get the component, type and impact, which may be null - String type = getType(method, args); - String vhost = getVirtualHost(method, args); - int impact = getImpact(method, args); - - // Get the security manager for the virtual host (if set) - SecurityManager security; - if (vhost == null) - { - security = _appRegistry.getSecurityManager(); - } - else - { - security = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhost).getSecurityManager(); - } - - methodName = getMethodName(method, args); - 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 - { - return doInvokeWrappingWithManagementActor(method, args); - } - finally - { - if(_managementRightsInferAllAccess) - { - SecurityManager.setAccessChecksDisabled(oldAccessChecksDisabled); - } - } - } - catch (InvocationTargetException e) - { - throw e.getTargetException(); - } - } - - 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; - } - - 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 - { - //if the name is quoted in the ObjectName, unquote it - vhost = ObjectName.unquote(vhost); - } - catch(IllegalArgumentException e) - { - //ignore, this just means the name is not quoted - //and can be left unchanged - } - } - - return vhost; - } - return null; - } - - private String getMethodName(Method method, Object[] args) - { - String methodName = method.getName(); - - // if arguments are set, try and work out real method name - if (args != null && args.length >= 1 && args[0] instanceof ObjectName) - { - if (methodName.equals("getAttribute")) - { - methodName = "get" + (String) args[1]; - } - else if (methodName.equals("setAttribute")) - { - methodName = "set" + ((Attribute) args[1]).getName(); - } - else if (methodName.equals("invoke")) - { - methodName = (String) args[1]; - } - } - - return methodName; - } - - private int getImpact(Method method, Object[] args) - { - //handle invocation of other methods on mbeans - if ((args[0] instanceof ObjectName) && (method.getName().equals("invoke"))) - { - //get invoked method name - String mbeanMethod = (args.length > 1) ? (String) args[1] : null; - if (mbeanMethod == null) - { - return -1; - } - - try - { - //Get the impact attribute - MBeanInfo mbeanInfo = _mbs.getMBeanInfo((ObjectName) args[0]); - if (mbeanInfo != null) - { - MBeanOperationInfo[] opInfos = mbeanInfo.getOperations(); - for (MBeanOperationInfo opInfo : opInfos) - { - if (opInfo.getName().equals(mbeanMethod)) - { - return opInfo.getImpact(); - } - } - } - } - catch (JMException ex) - { - _logger.error("Unable to determine mbean impact for method : " + mbeanMethod, ex); - } - } - - return -1; - } - - private boolean isAccessMethod(String methodName) - { - //handle standard get/query/is methods from MBeanServer - return (methodName.startsWith("query") || methodName.startsWith("get") || methodName.startsWith("is")); - } - - /** - * Receives notifications from the MBeanServer. - */ - public void handleNotification(final Notification notification, final Object handback) - { - assert notification instanceof JMXConnectionNotification; - - final String connectionId = ((JMXConnectionNotification) notification).getConnectionId(); - final String type = notification.getType(); - - if (_logger.isDebugEnabled()) - { - _logger.debug("Notification connectionId : " + connectionId + " type : " + type - + " Notification handback : " + handback); - } - - // Normally JMXManagedObjectRegistry provides a Map as handback data containing a map - // between connection id and username. - String user = null; - if (handback instanceof Map) - { - final Map connectionIdUsernameMap = (Map) handback; - user = connectionIdUsernameMap.get(connectionId); - } - - // If user is still null, fallback to an unordered list of Principals from the connection id. - if (user == null) - { - final String[] splitConnectionId = connectionId.split(" "); - user = splitConnectionId[1]; - } - - if (JMXConnectionNotification.OPENED.equals(type)) - { - _logActor.message(ManagementConsoleMessages.OPEN(user)); - } - else if (JMXConnectionNotification.CLOSED.equals(type) || - JMXConnectionNotification.FAILED.equals(type)) - { - _logActor.message(ManagementConsoleMessages.CLOSE(user)); - } - } -} - diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java deleted file mode 100644 index 83909dbe72..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.server.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 child 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/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java deleted file mode 100644 index 40b778fd93..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx; - -import javax.management.JMException; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; - -/** - * This should be implemented by all Managable objects. - */ -public interface ManagedObject -{ - static final String DOMAIN = "org.apache.qpid"; - - /** - * @return the name that uniquely identifies this object instance. It must be - * unique only among objects of this type at this level in the hierarchy so - * the uniqueness should not be too difficult to ensure. - */ - String getObjectInstanceName(); - - String getType(); - - Class getManagementInterface(); - - ManagedObject getParentObject(); - - void register() throws JMException; - - void unregister() throws JMException; - - /** - * Returns the ObjectName required for the mbeanserver registration. - * @return ObjectName - * @throws javax.management.MalformedObjectNameException - */ - ObjectName getObjectName() throws MalformedObjectNameException; -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java deleted file mode 100644 index 2ae0ac7052..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.common.Closeable; - -import javax.management.JMException; -import java.io.IOException; - -/** - * Handles the registration (and unregistration and so on) of managed objects. - * - * Managed objects are responsible for exposting attributes, operations and notifications. They will expose - * these outside the JVM therefore it is important not to use implementation objects directly as managed objects. - * Instead, creating inner classes and exposing those is an effective way of exposing internal state in a - * controlled way. - * - * Although we do not explictly use them while targetting Java 5, the enhanced MXBean approach in Java 6 will - * be the obvious choice for managed objects. - * - */ -public interface ManagedObjectRegistry extends Closeable -{ - void start() throws IOException, ConfigurationException; - - void registerObject(ManagedObject managedObject) throws JMException; - - void unregisterObject(ManagedObject managedObject) throws JMException; -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java deleted file mode 100644 index 6ab7db3629..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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 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; - -abstract class AbstractStatisticsGatheringMBean 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/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java deleted file mode 100644 index beffb4eaa9..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx.mbeans; - -import org.apache.qpid.management.common.mbeans.ConfigurationManagement; -import org.apache.qpid.server.jmx.AMQManagedObject; -import org.apache.qpid.server.jmx.ManagedObject; -import org.apache.qpid.server.jmx.ManagedObjectRegistry; -import org.apache.qpid.server.registry.ApplicationRegistry; - -import javax.management.JMException; -import javax.management.NotCompliantMBeanException; - -public class ConfigurationManagementMBean extends AMQManagedObject implements ConfigurationManagement -{ - - public ConfigurationManagementMBean(ManagedObjectRegistry registry) throws JMException - { - super(ConfigurationManagement.class, ConfigurationManagement.TYPE, registry); - register(); - } - - public String getObjectInstanceName() - { - return ConfigurationManagement.TYPE; - } - - public void reloadSecurityConfiguration() throws Exception - { - ApplicationRegistry.getInstance().getConfiguration().reparseConfigFileSecuritySections(); - } - - @Override - public ManagedObject getParentObject() - { - return null; - } -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java deleted file mode 100644 index d0c0d5e73f..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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 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 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) - { - 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/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java deleted file mode 100644 index 56802d0403..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java +++ /dev/null @@ -1,313 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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.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.OperationsException; -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 -{ - - public static final String FANOUT_EXCHANGE_TYPE = "fanout"; - public static final String HEADERS_EXCHANGE_TYPE = "headers"; - - 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()]); - - 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 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 headerMappings = binding.getArguments(); - - final List mappingList = new ArrayList(); - - if(headerMappings != null) - { - for(Map.Entry 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 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> bindingMap = new HashMap>(); - - for (Binding binding : bindings) - { - String key = FANOUT_EXCHANGE_TYPE.equals(_exchange.getExchangeType()) ? "*" : binding.getName(); - List queueList = bindingMap.get(key); - if(queueList == null) - { - queueList = new ArrayList(); - bindingMap.put(key, queueList); - } - queueList.add(binding.getParent(Queue.class).getName()); - - } - - for(Map.Entry> 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 arguments = new HashMap(); - - 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 \"=,=\""); - } - - 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]); - } - } - } - - VirtualHost virtualHost = _exchange.getParent(VirtualHost.class); - Queue queue = MBeanUtils.findQueueFromQueueName(virtualHost, queueName); - _exchange.createBinding(binding, queue, arguments, Collections.EMPTY_MAP); - } - - public void removeBinding(String queueName, String bindingKey) - throws IOException, JMException - { - VirtualHost virtualHost = _exchange.getParent(VirtualHost.class); - Queue queue = MBeanUtils.findQueueFromQueueName(virtualHost, queueName);; - - boolean deleted = false; - for(Binding binding : _exchange.getBindings()) - { - if(queue.equals(binding.getParent(Queue.class)) && bindingKey.equals(binding.getName())) - { - binding.delete(); - deleted = true; - } - } - - if (!deleted) - { - throw new OperationsException("No such binding \"" + bindingKey + "\" on queue \"" + queueName + "\""); - } - } -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java deleted file mode 100644 index 0dac8ebe37..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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.log4j.Logger; -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.apache.qpid.server.logging.log4j.LoggingFacade; -import org.apache.qpid.server.logging.log4j.LoggingFacadeException; - -import javax.management.JMException; -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.List; -import java.util.Map; - - -/** MBean class for LoggingManagement. It implements all the management features exposed for managing logging. */ -@MBeanDescription("Logging Management Interface") -public class LoggingManagementMBean extends AMQManagedObject implements LoggingManagement -{ - public static final String INHERITED_PSUEDO_LOG_LEVEL = "INHERITED"; - private static final Logger LOGGER = Logger.getLogger(LoggingManagementMBean.class); - private static final TabularType LOGGER_LEVEL_TABULAR_TYE; - private static final CompositeType LOGGER_LEVEL_COMPOSITE_TYPE; - - private final LoggingFacade _configurator; - - static - { - try - { - OpenType[] loggerLevelItemTypes = new OpenType[]{SimpleType.STRING, SimpleType.STRING}; - - LOGGER_LEVEL_COMPOSITE_TYPE = new CompositeType("LoggerLevelList", "Logger Level Data", - COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), - COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]), - loggerLevelItemTypes); - - LOGGER_LEVEL_TABULAR_TYE = new TabularType("LoggerLevel", "List of loggers with levels", - LOGGER_LEVEL_COMPOSITE_TYPE, - TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()])); - } - catch (OpenDataException e) - { - throw new ExceptionInInitializerError(e); - } - } - - public LoggingManagementMBean(LoggingFacade configurator, ManagedObjectRegistry registry) throws JMException - { - super(LoggingManagement.class, LoggingManagement.TYPE, registry); - register(); - _configurator = configurator; - } - - @Override - public String getObjectInstanceName() - { - return LoggingManagement.TYPE; - } - - @Override - public ManagedObject getParentObject() - { - return null; - } - - @Override - public Integer getLog4jLogWatchInterval() - { - return _configurator.getLog4jLogWatchInterval(); - } - - @Override - public String[] getAvailableLoggerLevels() - { - List levels = _configurator.getAvailableLoggerLevels(); - List mbeanLevels = new ArrayList(levels); - mbeanLevels.add(INHERITED_PSUEDO_LOG_LEVEL); - - return mbeanLevels.toArray(new String[mbeanLevels.size()]); - } - - @Override - public TabularData viewEffectiveRuntimeLoggerLevels() - { - Map levels = _configurator.retrieveRuntimeLoggersLevels(); - return createTabularDataFromLevelsMap(levels); - } - - @Override - public String getRuntimeRootLoggerLevel() - { - return _configurator.retrieveRuntimeRootLoggerLevel(); - } - - @Override - public boolean setRuntimeRootLoggerLevel(String level) - { - try - { - validateLevelNotAllowingInherited(level); - } - catch (IllegalArgumentException iae) - { - LOGGER.warn(level + " is not a known level"); - return false; - } - - _configurator.setRuntimeRootLoggerLevel(level); - return true; - } - - @Override - public boolean setRuntimeLoggerLevel(String logger, String level) - { - String validatedLevel; - try - { - validatedLevel = getValidateLevelAllowingInherited(level); - } - catch (IllegalArgumentException iae) - { - LOGGER.warn(level + " is not a known level"); - return false; - } - - try - { - _configurator.setRuntimeLoggerLevel(logger, validatedLevel); - } - catch (LoggingFacadeException e) - { - LOGGER.error("Cannot set runtime logging level", e); - return false; - } - return true; - } - - @Override - public TabularData viewConfigFileLoggerLevels() - { - Map levels; - try - { - levels = _configurator.retrieveConfigFileLoggersLevels(); - } - catch (LoggingFacadeException e) - { - LOGGER.error("Cannot determine logging levels", e); - return null; - } - - return createTabularDataFromLevelsMap(levels); - } - - @Override - public String getConfigFileRootLoggerLevel()throws IOException - { - try - { - return _configurator.retrieveConfigFileRootLoggerLevel().toUpperCase(); - } - catch (LoggingFacadeException e) - { - LOGGER.warn("The log4j configuration get config request was aborted: ", e); - throw new IOException("The log4j configuration get config request was aborted: " + e.getMessage()); - } - } - - @Override - public boolean setConfigFileLoggerLevel(String logger, String level) - { - String validatedLevel; - try - { - validatedLevel = getValidateLevelAllowingInherited(level); - } - catch (IllegalArgumentException iae) - { - LOGGER.warn(level + " is not a known level"); - return false; - } - - try - { - _configurator.setConfigFileLoggerLevel(logger, validatedLevel); - } - catch (LoggingFacadeException e) - { - LOGGER.warn("The log4j configuration set config request was aborted: ", e); - return false; - } - return true; - } - - @Override - public boolean setConfigFileRootLoggerLevel(String level) - { - try - { - validateLevelNotAllowingInherited(level); - } - catch (IllegalArgumentException iae) - { - LOGGER.warn(level + " is not a known level"); - return false; - } - - try - { - _configurator.setConfigFileRootLoggerLevel(level); - return true; - } - catch (LoggingFacadeException e) - { - LOGGER.warn("The log4j configuration set config request was aborted: ", e); - return false; - } - } - - @Override - public void reloadConfigFile() throws IOException - { - try - { - - _configurator.reload(); - } - catch (LoggingFacadeException e) - { - LOGGER.warn("The log4j configuration reload request was aborted: ", e); - throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage()); - } - } - - private String getValidateLevelAllowingInherited(String level) - { - if(level == null - || "null".equalsIgnoreCase(level) - || INHERITED_PSUEDO_LOG_LEVEL.equalsIgnoreCase(level)) - { - //the string "null" or "inherited" signals to inherit from a parent logger, - //using a null Level reference for the logger. - return null; - } - - validateLevelNotAllowingInherited(level); - return level; - } - - private void validateLevelNotAllowingInherited(String level) - { - final List availableLoggerLevels = _configurator.getAvailableLoggerLevels(); - if (!availableLoggerLevels.contains(level) - && !availableLoggerLevels.contains(String.valueOf(level).toUpperCase())) - { - throw new IllegalArgumentException(level + " not known"); - } - } - - private TabularData createTabularDataFromLevelsMap(Map levels) - { - TabularData loggerLevelList = new TabularDataSupport(LOGGER_LEVEL_TABULAR_TYE); - for (Map.Entry entry : levels.entrySet()) - { - String loggerName = entry.getKey(); - String level = entry.getValue(); - - CompositeData loggerData = createRow(loggerName, level); - loggerLevelList.put(loggerData); - } - return loggerLevelList; - } - - - private CompositeData createRow(String loggerName, String level) - { - Object[] itemData = {loggerName, level.toUpperCase()}; - try - { - CompositeData loggerData = new CompositeDataSupport(LOGGER_LEVEL_COMPOSITE_TYPE, - COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), itemData); - return loggerData; - } - catch (OpenDataException ode) - { - // Should not happen - throw new RuntimeException(ode); - } - } -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/MBeanUtils.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/MBeanUtils.java deleted file mode 100644 index 97e84d4796..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/MBeanUtils.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx.mbeans; - -import javax.management.OperationsException; - -import org.apache.qpid.server.model.ConfiguredObjectFinder; -import org.apache.qpid.server.model.Exchange; -import org.apache.qpid.server.model.Queue; -import org.apache.qpid.server.model.VirtualHost; - -public class MBeanUtils -{ - public static 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; - } - } - - public static 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/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java deleted file mode 100644 index 1416cfdd89..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java +++ /dev/null @@ -1,663 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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.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(); - } - - 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 = MBeanUtils.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 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 = MBeanUtils.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 = MBeanUtils.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 getMessages(final long first, final long last) - { - final List messages = new ArrayList((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 Number getStatisticValue(String name) - { - final Number statistic = (Number) _queue.getStatistics().getStatistic(name); - return statistic == null ? Integer.valueOf(0) : statistic; - } -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java deleted file mode 100644 index 67d5861dec..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx.mbeans; - -import java.io.IOException; - -import javax.management.JMException; -import javax.management.NotCompliantMBeanException; - -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 implements ServerInformation -{ - private final Broker _broker; - - public ServerInformationMBean(ManagedObjectRegistry registry, Broker broker) - throws NotCompliantMBeanException, JMException - { - super(ServerInformation.class, ServerInformation.TYPE, registry, broker); - _broker = broker; - - 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 (String) _broker.getAttribute(Broker.BUILD_VERSION); - } - - @Override - public String getProductVersion() throws IOException - { - return (String) _broker.getAttribute(Broker.PRODUCT_VERSION); - } - - @Override - public boolean isStatisticsEnabled() - { - return true; - } - - @Override - public ManagedObject getParentObject() - { - // does not have a parent - return null; - } -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java deleted file mode 100644 index 62733168ef..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.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; -import java.util.Date; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * Implementation of the JMX broker shutdown plugin. - */ -public class Shutdown extends DefaultManagedObject implements ShutdownMBean -{ - - private static final Logger _logger = Logger.getLogger(Shutdown.class); - - private static final String FORMAT = "yyyy/MM/dd HH:mm:ss"; - private static final int THREAD_COUNT = 1; - private static final ScheduledExecutorService EXECUTOR = new ScheduledThreadPoolExecutor(THREAD_COUNT); - - private final Runnable _shutdown = new SystemExiter(); - - public Shutdown(ManagedObjectRegistry registry) throws JMException - { - super(ShutdownMBean.class, ShutdownMBean.TYPE, registry); - register(); - } - - /** @see ShutdownMBean#shutdown() */ - public void shutdown() - { - _logger.info("Shutting down at user's request"); - shutdownBroker(0); - } - - /** @see ShutdownMBean#shutdown(long) */ - public void shutdown(final long delay) - { - if (delay < 0) - { - _logger.info("Shutting down at user's request"); - shutdownBroker(0); - } - else - { - _logger.info("Scheduled broker shutdown after " + delay + "ms"); - shutdownBroker(delay); - } - } - - /** @see ShutdownMBean#shutdownAt(String) */ - public void shutdownAt(final String when) - { - Date date; - DateFormat df = new SimpleDateFormat(FORMAT); - try - { - date = df.parse(when); - } - catch (ParseException e) - { - _logger.error("Invalid date \"" + when + "\": expecting " + FORMAT, e); - return; - } - _logger.info("Scheduled broker shutdown at " + when); - long now = System.currentTimeMillis(); - long time = date.getTime(); - if (time > now) - { - shutdownBroker(time - now); - } - else - { - shutdownBroker(0); - } - } - - /** - * Submits the {@link SystemExiter} job to shutdown the broker. - */ - private void shutdownBroker(long delay) - { - 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. - */ - class SystemExiter implements Runnable - { - public void run() - { - System.exit(0); - } - } - - /** - * @see ManagedObject#getObjectInstanceName() - */ - public String getObjectInstanceName() - { - return "Shutdown"; - } -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java deleted file mode 100644 index ed69c351f7..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.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. - * - * Shuts the Qpid broker down via JMX. - */ -public interface ShutdownMBean -{ - static final String TYPE = "Shutdown"; - - /** - * Broker will be shut down immediately. - */ - @MBeanOperation(name="shutdown", description="Shut down immediately", impact = MBeanOperationInfo.ACTION) - public void shutdown(); - - /** - * Broker will be shutdown after the specified delay - * - * @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); - - /** - * Broker will be shutdown at the specified date and time. - * - * @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); -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java deleted file mode 100644 index c7aade34b4..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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.log4j.Logger; - -import org.apache.qpid.management.common.mbeans.UserManagement; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.server.jmx.AMQManagedObject; -import org.apache.qpid.server.jmx.ManagedObject; -import org.apache.qpid.server.jmx.ManagedObjectRegistry; -import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider; - -import javax.management.JMException; -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 javax.security.auth.login.AccountNotFoundException; - -import java.io.IOException; -import java.util.Map; - -@MBeanDescription("User Management Interface") -public class UserManagementMBean extends AMQManagedObject implements UserManagement -{ - private static final Logger _logger = Logger.getLogger(UserManagementMBean.class); - - private PasswordCredentialManagingAuthenticationProvider _authProvider; - - // Setup for the TabularType - private static final TabularType _userlistDataType; // Datatype for representing User Lists - private static final CompositeType _userDataType; // Composite type for representing User - - static - { - OpenType[] userItemTypes = new OpenType[4]; // User item types. - userItemTypes[0] = SimpleType.STRING; // For Username - userItemTypes[1] = SimpleType.BOOLEAN; // For Rights - Read - No longer in use - userItemTypes[2] = SimpleType.BOOLEAN; // For Rights - Write - No longer in use - userItemTypes[3] = SimpleType.BOOLEAN; // For Rights - Admin - No longer is use - - try - { - _userDataType = - new CompositeType("User", "User Data", COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), - COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]), userItemTypes); - - _userlistDataType = new TabularType("Users", "List of users", _userDataType, TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()])); - } - catch (OpenDataException e) - { - _logger.error("Tabular data setup for viewing users incorrect.", e); - throw new ExceptionInInitializerError("Tabular data setup for viewing users incorrect"); - } - } - - public UserManagementMBean(PasswordCredentialManagingAuthenticationProvider provider, ManagedObjectRegistry registry) throws JMException - { - 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 - { - _authProvider.setPassword(username, password); - } - catch (AccountNotFoundException e) - { - _logger.warn("Attempt to set password of non-existent user '" + username + "'"); - return false; - } - return true; - } - - @Override - public boolean createUser(String username, String password) - { - return _authProvider.createUser(username, password, null); - } - - @Override - public boolean deleteUser(String username) - { - try - { - _authProvider.deleteUser(username); - } - catch (AccountNotFoundException e) - { - _logger.warn("Attempt to delete user (" + username + ") that doesn't exist"); - return false; - } - - return true; - } - - @Override - public boolean reloadData() - { - try - { - _authProvider.reload(); - return true; - } - catch (IOException e) - { - _logger.error("Unable to reload user data", e); - return false; - } - } - - @Override - public TabularData viewUsers() - { - Map> users = _authProvider.getUsers(); - - TabularDataSupport userList = new TabularDataSupport(_userlistDataType); - - try - { - // Create the tabular list of message header contents - for (String user : users.keySet()) - { - // Create header attributes list - // 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); - } - } - catch (OpenDataException e) - { - _logger.warn("Unable to create user list due to :", e); - return null; - } - - return userList; - } - - @Override - public ManagedObject getParentObject() - { - return null; - } -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java deleted file mode 100644 index 6990a40dee..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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.log4j.Logger; -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 static final Logger LOGGER = Logger.getLogger(VirtualHostMBean.class); - - private final VirtualHost _virtualHost; - - private final Map _children = - new HashMap(); - 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 - { - LOGGER.debug("Unsupported child : " + child.getName() + " type : " + child.getClass()); - } - - } - catch(JMException e) - { - LOGGER.error("Failed to add mbean for child : " + child.getName(), e); - } - } - } - - public void childRemoved(ConfiguredObject object, ConfiguredObject child) - { - synchronized (_children) - { - AMQManagedObject mbean = _children.remove(child); - if(mbean != null) - { - try - { - mbean.unregister(); - } - catch(JMException e) - { - LOGGER.error("Failed to remove mbean for child : " + child.getName(), e); - } - } - } - } - - @Override - public ManagedObject getParentObject() - { - return null; - } - - protected VirtualHost getVirtualHost() - { - return _virtualHost; - } - - public Collection getQueues() - { - Collection children; - synchronized (_children) - { - children = new ArrayList(_children.values()); - } - Collection queues = new ArrayList(); - - for(AMQManagedObject child : children) - { - if(child instanceof QueueMBean) - { - queues.add((QueueMBean) child); - } - } - - return queues; - } -} diff --git a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java b/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java deleted file mode 100644 index b3dbbc424a..0000000000 --- a/java/broker-plugins/jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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 javax.management.OperationsException; - -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 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(); - } - - - @Override - public String getObjectInstanceName() - { - return ObjectName.quote(_virtualHostMBean.getName()); - } - - @Override - public ManagedObject getParentObject() - { - return _virtualHostMBean; - } - - @Override - public String[] getExchangeTypes() throws IOException - { - Collection exchangeTypes = _virtualHostMBean.getVirtualHost().getExchangeTypes(); - return exchangeTypes.toArray(new String[exchangeTypes.size()]); - } - - @Override - public List retrieveQueueAttributeNames() throws IOException - { - return ManagedQueue.QUEUE_ATTRIBUTES; - } - - @Override - public List> retrieveQueueAttributeValues( - @MBeanOperationParameter(name = "attributes", description = "Attributes to retrieve") String[] attributes) - throws IOException - { - int attributesLength = attributes.length; - - List> queueAttributesList = new ArrayList>(); - - for(QueueMBean queue : _virtualHostMBean.getQueues()) - { - - if(queue == null) - { - continue; - } - - List attributeValues = new ArrayList(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; - - } - - @Override - public void createNewExchange(String name, String type, boolean durable) - throws IOException, JMException, MBeanException - { - if (!getConfiguredObject().getExchangeTypes().contains(type)) - { - throw new OperationsException("No such exchange type \""+type+"\""); - } - - try - { - getConfiguredObject().createExchange(name, State.ACTIVE, durable, - LifetimePolicy.PERMANENT, 0l, type, Collections.EMPTY_MAP); - } - catch (IllegalArgumentException iae) - { - JMException jme = new JMException(iae.toString()); - throw new MBeanException(jme, "Error in creating exchange " + name); - } - - } - - @Override - public void unregisterExchange(String exchangeName) - throws IOException, JMException, MBeanException - { - Exchange theExchange = MBeanUtils.findExchangeFromExchangeName(_virtualHostMBean.getVirtualHost(), exchangeName); - try - { - theExchange.delete(); - } - catch (IllegalStateException ex) - { - final JMException jme = new JMException(ex.toString()); - throw new MBeanException(jme, "Error in unregistering exchange " + exchangeName); - } - } - - @Override - public void createNewQueue(String queueName, String owner, boolean durable) - throws IOException, JMException, MBeanException - { - createNewQueue(queueName, owner, durable, Collections.EMPTY_MAP); - } - - @Override - public void createNewQueue(String queueName, String owner, boolean durable, Map originalArguments) - throws IOException, JMException - { - final Map 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 processNewQueueArguments(String queueName, - String owner, Map arguments) - { - final Map argumentsCopy; - if (_moveNonExclusiveQueueOwnerToDescription && owner != null) - { - argumentsCopy = new HashMap(arguments == null ? new HashMap() : 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; - } - - @Override - public void deleteQueue( - @MBeanOperationParameter(name = ManagedQueue.TYPE, description = "Queue Name") String queueName) - throws IOException, JMException, MBeanException - { - Queue theQueue = MBeanUtils.findQueueFromQueueName(_virtualHostMBean.getVirtualHost(), queueName); - theQueue.delete(); - } - - @Override - public ObjectName getObjectName() throws MalformedObjectNameException - { - return getObjectNameForSingleInstanceMBean(); - } - - public synchronized boolean isStatisticsEnabled() - { - updateStats(); - return false; //TODO - implement isStatisticsEnabled - } - -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.java deleted file mode 100644 index a2631bab7f..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx; - -import javax.management.JMException; - -public class NoopManagedObjectRegistry implements ManagedObjectRegistry -{ - public NoopManagedObjectRegistry() - { - } - - public void start() - { - } - - public void registerObject(ManagedObject managedObject) throws JMException - { - } - - public void unregisterObject(ManagedObject managedObject) throws JMException - { - } - - public void close() - { - } -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java deleted file mode 100644 index 0c5fb0bf1f..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpid.server.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.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 testGetClientId() throws Exception - { - assertAttribute("clientId", "testClientId", Connection.CLIENT_ID); - } - - 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); - MBeanTestUtils.assertMBeanAttribute(_connectionMBean, jmxAttributeName, expectedValue); - } - - 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/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBeanTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBeanTest.java deleted file mode 100644 index e350f80a25..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBeanTest.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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.Mockito.never; -import static org.mockito.Matchers.isNull; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.anyMap; - - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; - -import javax.management.JMException; -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.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.Statistics; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.queue.NotificationCheck; -import org.mockito.ArgumentMatcher; - -import junit.framework.TestCase; - -public class ExchangeMBeanTest extends TestCase -{ - private static final String EXCHANGE_NAME = "EXCHANGE_NAME"; - private static final String EXCHANGE_TYPE = "EXCHANGE_TYPE"; - private static final String QUEUE1_NAME = "QUEUE1_NAME"; - private static final String QUEUE2_NAME = "QUEUE2_NAME"; - private static final String BINDING1 = "BINDING1"; - private static final String BINDING2 = "BINDING2"; - - private Exchange _mockExchange; - private VirtualHostMBean _mockVirtualHostMBean; - private ManagedObjectRegistry _mockManagedObjectRegistry; - private ExchangeMBean _exchangeMBean; - private Queue _mockQueue1; - private Queue _mockQueue2; - private Exchange _mockHeadersExchange; - - @Override - protected void setUp() throws Exception - { - _mockExchange = mock(Exchange.class); - when(_mockExchange.getName()).thenReturn(EXCHANGE_NAME); - when(_mockExchange.getExchangeType()).thenReturn(EXCHANGE_TYPE); - _mockVirtualHostMBean = mock(VirtualHostMBean.class); - - _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class); - when(_mockVirtualHostMBean.getRegistry()).thenReturn(_mockManagedObjectRegistry); - - _mockQueue1 = createMockQueue(QUEUE1_NAME); - _mockQueue2 = createMockQueue(QUEUE2_NAME); - - VirtualHost mockVirtualHost = mock(VirtualHost.class); - when(mockVirtualHost.getQueues()).thenReturn(Arrays.asList(new Queue[] {_mockQueue1, _mockQueue2})); - when(_mockExchange.getParent(VirtualHost.class)).thenReturn(mockVirtualHost); - - _exchangeMBean = new ExchangeMBean(_mockExchange, _mockVirtualHostMBean); - - _mockHeadersExchange = mock(Exchange.class); - when(_mockHeadersExchange.getExchangeType()).thenReturn(ExchangeMBean.HEADERS_EXCHANGE_TYPE); - when(_mockHeadersExchange.getParent(VirtualHost.class)).thenReturn(mockVirtualHost); - - } - - public void testExchangeName() - { - assertEquals(EXCHANGE_NAME, _exchangeMBean.getName()); - } - - public void testExchangeType() - { - assertEquals(EXCHANGE_TYPE, _exchangeMBean.getExchangeType()); - } - - public void testNonHeadersExchangeCreateNewBinding() throws Exception - { - _exchangeMBean.createNewBinding(QUEUE1_NAME, BINDING1); - verify(_mockExchange).createBinding(BINDING1, _mockQueue1, Collections.EMPTY_MAP, Collections.EMPTY_MAP); - } - - public void testCreateNewBindingWhereQueueIsUnknown() throws Exception - { - try - { - _exchangeMBean.createNewBinding("unknown", BINDING1); - } - catch (OperationsException oe) - { - // PASS - assertEquals("No such queue \"unknown\"", oe.getMessage()); - } - verify(_mockExchange, never()).createBinding(anyString(), any(Queue.class), anyMap(), anyMap()); - } - - public void testRemoveBinding() throws Exception - { - Binding mockBinding1 = createBindingOnQueue(BINDING1, _mockQueue1); - Binding mockBinding2 = createBindingOnQueue(BINDING2, _mockQueue1); - when(_mockExchange.getBindings()).thenReturn(Arrays.asList(new Binding[] {mockBinding1, mockBinding2})); - - _exchangeMBean.removeBinding(QUEUE1_NAME, BINDING1); - verify(mockBinding1).delete(); - } - - public void testRemoveBindingWhereQueueIsUnknown() throws Exception - { - Binding mockBinding1 = createBindingOnQueue(BINDING1, _mockQueue1); - when(_mockExchange.getBindings()).thenReturn(Arrays.asList(new Binding[] {mockBinding1})); - - try - { - _exchangeMBean.removeBinding("unknown", BINDING1); - fail("Exception not thrown"); - } - catch (OperationsException oe) - { - // PASS - assertEquals("No such queue \"unknown\"", oe.getMessage()); - } - verify(mockBinding1, never()).delete(); - } - - public void testRemoveBindingWhereBindingNameIsUnknown() throws Exception - { - Binding mockBinding1 = createBindingOnQueue(BINDING1, _mockQueue1); - when(_mockExchange.getBindings()).thenReturn(Arrays.asList(new Binding[] {mockBinding1})); - - try - { - _exchangeMBean.removeBinding(QUEUE1_NAME, "unknown"); - fail("Exception not thrown"); - } - catch (OperationsException oe) - { - // PASS - assertEquals("No such binding \"unknown\" on queue \"" + QUEUE1_NAME + "\"", oe.getMessage()); - } - verify(mockBinding1, never()).delete(); - } - - public void testHeadersExchangeCreateNewBinding() throws Exception - { - String binding = "key1=binding1,key2=binding2"; - Map expectedBindingMap = new HashMap() - {{ - put("key1", "binding1"); - put("key2", "binding2"); - }}; - _exchangeMBean = new ExchangeMBean(_mockHeadersExchange, _mockVirtualHostMBean); - - _exchangeMBean.createNewBinding(QUEUE1_NAME, binding); - verify(_mockHeadersExchange).createBinding(binding, _mockQueue1, expectedBindingMap, Collections.EMPTY_MAP); - } - - public void testHeadersExchangeCreateNewBindingWithFieldWithoutValue() throws Exception - { - String binding = "key1=binding1,key2="; - Map expectedBindingMap = new HashMap() - {{ - put("key1", "binding1"); - put("key2", ""); - }}; - _exchangeMBean = new ExchangeMBean(_mockHeadersExchange, _mockVirtualHostMBean); - - _exchangeMBean.createNewBinding(QUEUE1_NAME, binding); - verify(_mockHeadersExchange).createBinding(binding, _mockQueue1, expectedBindingMap, Collections.EMPTY_MAP); - } - - public void testHeadersExchangeCreateNewBindingMalformed() throws Exception - { - String binding = "=binding1,="; - _exchangeMBean = new ExchangeMBean(_mockHeadersExchange, _mockVirtualHostMBean); - - try - { - _exchangeMBean.createNewBinding(QUEUE1_NAME, binding); - fail("Exception not thrown"); - } - catch (JMException e) - { - assertEquals("Format for headers binding should be \"=,=\"", e.getMessage()); - } - } - - private Binding createBindingOnQueue(String bindingName, Queue queue) - { - Binding mockBinding = mock(Binding.class); - when(mockBinding.getParent(Queue.class)).thenReturn(queue); - when(mockBinding.getName()).thenReturn(bindingName); - return mockBinding; - } - - private Queue createMockQueue(String queueName) - { - Queue mockQueue = mock(Queue.class); - when(mockQueue.getName()).thenReturn(queueName); - return mockQueue; - } - -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java deleted file mode 100644 index ae1be5db00..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * - */ -package org.apache.qpid.server.jmx.mbeans; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.Matchers.anyString; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.TabularData; - -import junit.framework.TestCase; - -import org.apache.qpid.management.common.mbeans.LoggingManagement; -import org.apache.qpid.server.jmx.ManagedObjectRegistry; -import org.apache.qpid.server.logging.log4j.LoggingFacade; - -public class LoggingManagementMBeanTest extends TestCase -{ - private static final String TEST_LEVEL1 = "LEVEL1"; - private static final String TEST_LEVEL2 = "LEVEL2"; - - private LoggingManagementMBean _loggingMBean; - private LoggingFacade _mockLoggingFacade; - private ManagedObjectRegistry _mockManagedObjectRegistry; - - @Override - protected void setUp() throws Exception - { - _mockLoggingFacade = mock(LoggingFacade.class); - final List listOfLevels = new ArrayList() - {{ - add(TEST_LEVEL1); - add(TEST_LEVEL2); - }}; - when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(listOfLevels); - - _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class); - - _loggingMBean = new LoggingManagementMBean(_mockLoggingFacade, _mockManagedObjectRegistry); - } - - public void testMBeanRegistersItself() throws Exception - { - LoggingManagementMBean connectionMBean = new LoggingManagementMBean(_mockLoggingFacade, _mockManagedObjectRegistry); - verify(_mockManagedObjectRegistry).registerObject(connectionMBean); - } - - public void testLog4jLogWatchInterval() throws Exception - { - final Integer value = 5000; - when(_mockLoggingFacade.getLog4jLogWatchInterval()).thenReturn(value); - - assertEquals("Unexpected watch interval",value, _loggingMBean.getLog4jLogWatchInterval()); - } - - public void testGetAvailableLoggerLevels() throws Exception - { - String[] actualLevels = _loggingMBean.getAvailableLoggerLevels(); - assertEquals(3, actualLevels.length); - assertEquals(TEST_LEVEL1, actualLevels[0]); - assertEquals(TEST_LEVEL2, actualLevels[1]); - assertEquals(LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL, actualLevels[2]); - } - - public void testViewEffectiveRuntimeLoggerLevels() throws Exception - { - Map loggerLevels = new TreeMap(); - loggerLevels.put("a.b.D", TEST_LEVEL2); - loggerLevels.put("a.b.C", TEST_LEVEL1); - loggerLevels.put("a.b.c.E", TEST_LEVEL2); - - when(_mockLoggingFacade.retrieveRuntimeLoggersLevels()).thenReturn(loggerLevels ); - - TabularData table = _loggingMBean.viewEffectiveRuntimeLoggerLevels(); - assertEquals(3, table.size()); - - final CompositeData row1 = table.get(new String[] {"a.b.C"} ); - final CompositeData row2 = table.get(new String[] {"a.b.D"} ); - final CompositeData row3 = table.get(new String[] {"a.b.c.E"} ); - assertChannelRow(row1, "a.b.C", TEST_LEVEL1); - assertChannelRow(row2, "a.b.D", TEST_LEVEL2); - assertChannelRow(row3, "a.b.c.E", TEST_LEVEL2); - } - - public void testGetRuntimeRootLoggerLevel() throws Exception - { - when(_mockLoggingFacade.retrieveRuntimeRootLoggerLevel()).thenReturn(TEST_LEVEL1); - - assertEquals(TEST_LEVEL1, _loggingMBean.getRuntimeRootLoggerLevel()); - } - - public void testSetRuntimeRootLoggerLevel() throws Exception - { - _loggingMBean.setRuntimeRootLoggerLevel(TEST_LEVEL1); - verify(_mockLoggingFacade).setRuntimeRootLoggerLevel(TEST_LEVEL1); - } - - public void testSetRuntimeRootLoggerLevelWhenLoggingLevelUnknown() throws Exception - { - boolean result = _loggingMBean.setRuntimeRootLoggerLevel("unknown"); - assertFalse(result); - verify(_mockLoggingFacade, never()).setRuntimeRootLoggerLevel("unknown"); - } - - public void testSetRuntimeRootLoggerLevelWhenLoggingLevelInherited() throws Exception - { - boolean result = _loggingMBean.setRuntimeRootLoggerLevel(LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL); - assertFalse(result); - verify(_mockLoggingFacade, never()).setRuntimeRootLoggerLevel(anyString()); - } - - public void testSetRuntimeLoggerLevel() throws Exception - { - _loggingMBean.setRuntimeLoggerLevel("a.b.c.D", TEST_LEVEL1); - verify(_mockLoggingFacade).setRuntimeLoggerLevel("a.b.c.D", TEST_LEVEL1); - } - - public void testSetRuntimeLoggerLevelWhenLoggingLevelUnknown() throws Exception - { - boolean result = _loggingMBean.setRuntimeLoggerLevel("a.b.c.D", "unknown"); - assertFalse(result); - verify(_mockLoggingFacade, never()).setRuntimeLoggerLevel(anyString(), anyString()); - } - - public void testSetRuntimeLoggerLevelWhenLoggingLevelInherited() throws Exception - { - boolean result = _loggingMBean.setRuntimeLoggerLevel("a.b.c.D", LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL); - assertTrue(result); - verify(_mockLoggingFacade).setRuntimeLoggerLevel("a.b.c.D", null); - } - - public void testViewEffectiveConfigFileLoggerLevels() throws Exception - { - Map loggerLevels = new TreeMap(); - loggerLevels.put("a.b.D", "level2"); - loggerLevels.put("a.b.C", TEST_LEVEL1); - loggerLevels.put("a.b.c.E", "level2"); - - when(_mockLoggingFacade.retrieveConfigFileLoggersLevels()).thenReturn(loggerLevels ); - - TabularData table = _loggingMBean.viewConfigFileLoggerLevels(); - assertEquals(3, table.size()); - - final CompositeData row1 = table.get(new String[] {"a.b.C"} ); - final CompositeData row2 = table.get(new String[] {"a.b.D"} ); - final CompositeData row3 = table.get(new String[] {"a.b.c.E"} ); - assertChannelRow(row1, "a.b.C", TEST_LEVEL1); - assertChannelRow(row2, "a.b.D", TEST_LEVEL2); - assertChannelRow(row3, "a.b.c.E", TEST_LEVEL2); - } - - public void testGetConfigFileRootLoggerLevel() throws Exception - { - when(_mockLoggingFacade.retrieveConfigFileRootLoggerLevel()).thenReturn(TEST_LEVEL1); - - assertEquals(TEST_LEVEL1, _loggingMBean.getConfigFileRootLoggerLevel()); - } - - public void testSetConfigFileRootLoggerLevel() throws Exception - { - when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1)); - _loggingMBean.setConfigFileRootLoggerLevel(TEST_LEVEL1); - verify(_mockLoggingFacade).setConfigFileRootLoggerLevel(TEST_LEVEL1); - } - - public void testSetConfigFileRootLoggerLevelWhenLoggingLevelUnknown() throws Exception - { - when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1)); - boolean result = _loggingMBean.setConfigFileRootLoggerLevel("unknown"); - assertFalse(result); - verify(_mockLoggingFacade, never()).setConfigFileRootLoggerLevel("unknown"); - } - - public void testSetConfigFileRootLoggerLevelWhenLoggingLevelInherited() throws Exception - { - when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1)); - boolean result = _loggingMBean.setConfigFileRootLoggerLevel(LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL); - assertFalse(result); - verify(_mockLoggingFacade, never()).setConfigFileRootLoggerLevel(anyString()); - } - - public void testSetConfigFileLoggerLevel() throws Exception - { - when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1)); - _loggingMBean.setConfigFileLoggerLevel("a.b.c.D", TEST_LEVEL1); - verify(_mockLoggingFacade).setConfigFileLoggerLevel("a.b.c.D", TEST_LEVEL1); - } - - public void testSetConfigFileLoggerLevelWhenLoggingLevelUnknown() throws Exception - { - when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1)); - boolean result = _loggingMBean.setConfigFileLoggerLevel("a.b.c.D", "unknown"); - assertFalse(result); - verify(_mockLoggingFacade, never()).setConfigFileLoggerLevel("a.b.c.D", "unknown"); - } - - public void testSetConfigFileLoggerLevelWhenLoggingLevelInherited() throws Exception - { - when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1)); - boolean result = _loggingMBean.setConfigFileLoggerLevel("a.b.c.D", LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL); - assertTrue(result); - verify(_mockLoggingFacade).setConfigFileLoggerLevel("a.b.c.D", null); - } - - public void testReloadConfigFile() throws Exception - { - _loggingMBean.reloadConfigFile(); - - verify(_mockLoggingFacade).reload(); - } - - private void assertChannelRow(final CompositeData row, String logger, String level) - { - assertNotNull("No row for " + logger, row); - assertEquals("Unexpected logger name", logger, row.get(LoggingManagement.LOGGER_NAME)); - assertEquals("Unexpected level", level, row.get(LoggingManagement.LOGGER_LEVEL)); - } -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/MBeanTestUtils.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/MBeanTestUtils.java deleted file mode 100644 index 5f913e5f33..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/MBeanTestUtils.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx.mbeans; - -import junit.framework.TestCase; - -import org.apache.commons.beanutils.PropertyUtils; -import org.apache.qpid.server.jmx.DefaultManagedObject; - -public class MBeanTestUtils -{ - - public static void assertMBeanAttribute(DefaultManagedObject managedObject, String jmxAttributeName, Object expectedValue) throws Exception - { - Object actualValue = PropertyUtils.getSimpleProperty(managedObject, jmxAttributeName); - TestCase.assertEquals("Attribute " + jmxAttributeName + " has unexpected value", expectedValue, actualValue); - } - - public static void setMBeanAttribute(DefaultManagedObject managedObject, String jmxAttributeName, Object newValue) throws Exception - { - PropertyUtils.setSimpleProperty(managedObject, jmxAttributeName, newValue); - } -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java deleted file mode 100644 index 2003c12735..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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.LifetimePolicy; -import org.apache.qpid.server.model.Queue; -import org.apache.qpid.server.model.Statistics; -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 Statistics _mockQueueStatistics; - private VirtualHostMBean _mockVirtualHostMBean; - private ManagedObjectRegistry _mockManagedObjectRegistry; - private QueueMBean _queueMBean; - - @Override - protected void setUp() throws Exception - { - _mockQueue = mock(Queue.class); - _mockQueueStatistics = mock(Statistics.class); - when(_mockQueue.getName()).thenReturn(QUEUE_NAME); - when(_mockQueue.getStatistics()).thenReturn(_mockQueueStatistics); - _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()); - } - - /********** Statistics **********/ - - public void testGetMessageCount() throws Exception - { - assertStatistic("messageCount", 1000, Queue.QUEUE_DEPTH_MESSAGES); - } - - public void testGetReceivedMessageCount() throws Exception - { - assertStatistic("receivedMessageCount", 1000l, Queue.TOTAL_ENQUEUED_MESSAGES); - } - - public void testQueueDepth() throws Exception - { - assertStatistic("queueDepth", 4096l, Queue.QUEUE_DEPTH_BYTES); - } - - public void testActiveConsumerCount() throws Exception - { - assertStatistic("activeConsumerCount", 3, Queue.CONSUMER_COUNT_WITH_CREDIT); - } - - public void testConsumerCount() throws Exception - { - assertStatistic("consumerCount", 3, Queue.CONSUMER_COUNT); - } - - /********** Simple Attributes **********/ - - public void testGetQueueDescription() throws Exception - { - assertAttribute("description", QUEUE_DESCRIPTION, Queue.DESCRIPTION); - } - - public void testSetQueueDescription() throws Exception - { - testSetAttribute("description", Queue.DESCRIPTION, "descriptionold", "descriptionnew"); - } - - public void testQueueType() throws Exception - { - assertAttribute("queueType", QUEUE_TYPE, Queue.TYPE); - } - - public void testMaximumDeliveryCount() throws Exception - { - assertAttribute("maximumDeliveryCount", 5, Queue.MAXIMUM_DELIVERY_ATTEMPTS); - } - - public void testOwner() throws Exception - { - assertAttribute("owner", "testOwner", Queue.OWNER); - } - - public void testIsDurable() throws Exception - { - when(_mockQueue.isDurable()).thenReturn(true); - assertTrue(_queueMBean.isDurable()); - } - - public void testIsNotDurable() throws Exception - { - when(_mockQueue.isDurable()).thenReturn(false); - assertFalse(_queueMBean.isDurable()); - } - - public void testIsAutoDelete() throws Exception - { - when(_mockQueue.getLifetimePolicy()).thenReturn(LifetimePolicy.AUTO_DELETE); - assertTrue(_queueMBean.isAutoDelete()); - } - - public void testIsNotAutoDelete() throws Exception - { - when(_mockQueue.getLifetimePolicy()).thenReturn(LifetimePolicy.PERMANENT); - assertFalse(_queueMBean.isAutoDelete()); - } - - public void testGetMaximumMessageAge() throws Exception - { - assertAttribute("maximumMessageAge", 10000l, Queue.ALERT_THRESHOLD_MESSAGE_AGE); - } - - public void testSetMaximumMessageAge() throws Exception - { - testSetAttribute("maximumMessageAge", Queue.ALERT_THRESHOLD_MESSAGE_AGE, 1000l, 10000l); - } - - public void testGetMaximumMessageSize() throws Exception - { - assertAttribute("maximumMessageSize", 1024l, Queue.ALERT_THRESHOLD_MESSAGE_SIZE); - } - - public void testSetMaximumMessageSize() throws Exception - { - testSetAttribute("maximumMessageSize", Queue.ALERT_THRESHOLD_MESSAGE_SIZE, 1024l, 2048l); - } - - public void testGetMaximumMessageCount() throws Exception - { - assertAttribute("maximumMessageCount", 5000l, Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES); - } - - public void testSetMaximumMessageCount() throws Exception - { - testSetAttribute("maximumMessageCount", Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 4000l, 5000l); - } - - public void testGetMaximumQueueDepth() throws Exception - { - assertAttribute("maximumQueueDepth", 1048576l, Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES); - } - - public void testSetMaximumQueueDepth() throws Exception - { - testSetAttribute("maximumQueueDepth", Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES,1048576l , 2097152l); - } - - public void testGetCapacity() throws Exception - { - assertAttribute("capacity", 1048576l, Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES); - } - - public void testSetCapacity() throws Exception - { - testSetAttribute("capacity", Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES,1048576l , 2097152l); - } - - public void testGetFlowResumeCapacity() throws Exception - { - assertAttribute("flowResumeCapacity", 1048576l, Queue.QUEUE_FLOW_RESUME_SIZE_BYTES); - } - - public void testSetFlowResumeCapacity() throws Exception - { - testSetAttribute("flowResumeCapacity", Queue.QUEUE_FLOW_RESUME_SIZE_BYTES,1048576l , 2097152l); - } - - public void testIsExclusive() throws Exception - { - assertAttribute("exclusive", Boolean.TRUE, Queue.EXCLUSIVE); - } - - public void testIsNotExclusive() throws Exception - { - assertAttribute("exclusive", Boolean.FALSE, Queue.EXCLUSIVE); - } - - public void testSetExclusive() throws Exception - { - testSetAttribute("exclusive", Queue.EXCLUSIVE, Boolean.FALSE , Boolean.TRUE); - } - - /********** Other attributes **********/ - - 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); - } - - /********** Operations **********/ - - /********** Notifications **********/ - - 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() - { - @Override - public boolean matches(Object argument) - { - Notification actual = (Notification) argument; - return actual.getMessage().endsWith(expectedMessage); - } - }); - } - - private void assertStatistic(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception - { - when(_mockQueueStatistics.getStatistic(underlyingAttributeName)).thenReturn(expectedValue); - MBeanTestUtils.assertMBeanAttribute(_queueMBean, jmxAttributeName, expectedValue); - } - - private void assertAttribute(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception - { - when(_mockQueue.getAttribute(underlyingAttributeName)).thenReturn(expectedValue); - MBeanTestUtils.assertMBeanAttribute(_queueMBean, jmxAttributeName, expectedValue); - } - - private void testSetAttribute(String jmxAttributeName, String underlyingAttributeName, Object originalAttributeValue, Object newAttributeValue) throws Exception - { - when(_mockQueue.getAttribute(underlyingAttributeName)).thenReturn(originalAttributeValue); - - MBeanTestUtils.setMBeanAttribute(_queueMBean, jmxAttributeName, newAttributeValue); - - verify(_mockQueue).setAttribute(underlyingAttributeName, originalAttributeValue, newAttributeValue); - } - -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBeanTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBeanTest.java deleted file mode 100644 index 86eab0245e..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBeanTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx.mbeans; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.apache.qpid.server.jmx.ManagedObjectRegistry; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.Connection; -import org.apache.qpid.server.model.Statistics; - -import junit.framework.TestCase; - -public class ServerInformationMBeanTest extends TestCase -{ - private ManagedObjectRegistry _mockManagedObjectRegistry; - private Broker _mockBroker; - private Statistics _mockBrokerStatistics; - private ServerInformationMBean _mbean; - - @Override - protected void setUp() throws Exception - { - _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class); - _mockBroker = mock(Broker.class); - _mockBrokerStatistics = mock(Statistics.class); - when(_mockBroker.getStatistics()).thenReturn(_mockBrokerStatistics); - - _mbean = new ServerInformationMBean(_mockManagedObjectRegistry, _mockBroker); - } - - public void testMBeanRegistersItself() throws Exception - { - ServerInformationMBean mbean = new ServerInformationMBean(_mockManagedObjectRegistry, _mockBroker); - verify(_mockManagedObjectRegistry).registerObject(mbean); - } - - /********** Statistics **********/ - - public void testGetMessageCount() throws Exception - { - assertStatistic("totalDataDelivered", 16384l, Connection.BYTES_OUT); - } - - /********** Attributes **********/ - - public void testBuildVersion() throws Exception - { - assertAttribute("buildVersion", "0.0.1", Broker.BUILD_VERSION); - } - - public void testProductVersion() throws Exception - { - assertAttribute("productVersion", "0.0.1", Broker.PRODUCT_VERSION); - } - - /********** Other Attributes **********/ - - public void testIsStatisticsEnabled() throws Exception - { - assertTrue("isStatisticsEnabled", _mbean.isStatisticsEnabled()); - } - - private void assertStatistic(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception - { - when(_mockBrokerStatistics.getStatistic(underlyingAttributeName)).thenReturn(expectedValue); - MBeanTestUtils.assertMBeanAttribute(_mbean, jmxAttributeName, expectedValue); - } - - private void assertAttribute(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception - { - when(_mockBroker.getAttribute(underlyingAttributeName)).thenReturn(expectedValue); - MBeanTestUtils.assertMBeanAttribute(_mbean, jmxAttributeName, expectedValue); - } -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.java deleted file mode 100644 index 8ca6c521eb..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.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 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/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java deleted file mode 100644 index e3fac9f711..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx.mbeans; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.when; - -import java.util.Collections; -import java.util.Map; - -import javax.management.OperationsException; - -import junit.framework.TestCase; - -import org.apache.qpid.server.jmx.ManagedObjectRegistry; -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; - -public class VirtualHostManagerMBeanTest extends TestCase -{ - private static final String TEST_QUEUE_NAME = "QUEUE_NAME"; - private static final String TEST_EXCHANGE_NAME = "EXCHANGE_NAME"; - private static final String TEST_OWNER = "OWNER"; - private static final String TEST_DESCRIPTION = "DESCRIPTION"; - private static final String TEST_EXCHANGE_TYPE = "EXCHANGE_TYPE"; - - private static final Map EMPTY_ARGUMENT_MAP = Collections.emptyMap(); - - private VirtualHost _mockVirtualHost; - private ManagedObjectRegistry _mockManagedObjectRegistry; - private VirtualHostManagerMBean _virtualHostManagerMBean; - - @Override - protected void setUp() throws Exception - { - _mockVirtualHost = mock(VirtualHost.class); - when(_mockVirtualHost.getExchangeTypes()).thenReturn(Collections.singletonList(TEST_EXCHANGE_TYPE)); - - _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 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 arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_DESCRIPTION); - _virtualHostManagerMBean.createNewQueue(TEST_QUEUE_NAME, TEST_OWNER, true, arguments); - - Map expectedArguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_DESCRIPTION); - verify(_mockVirtualHost).createQueue(TEST_QUEUE_NAME, State.ACTIVE, true, false, LifetimePolicy.PERMANENT, 0, expectedArguments); - } - - public void testDeleteQueue() throws Exception - { - Queue mockQueue = mock(Queue.class); - when(mockQueue.getName()).thenReturn("queue1"); - when(_mockVirtualHost.getQueues()).thenReturn(Collections.singletonList(mockQueue)); - - _virtualHostManagerMBean.deleteQueue("queue1"); - verify(mockQueue).delete(); - } - - public void testDeleteQueueWhenQueueDoesNotExist() throws Exception - { - Queue mockQueue = mock(Queue.class); - when(mockQueue.getName()).thenReturn("queue1"); - when(_mockVirtualHost.getQueues()).thenReturn(Collections.singletonList(mockQueue)); - - try - { - _virtualHostManagerMBean.deleteQueue("unknownqueue"); - fail("Exception not thrown"); - } - catch(OperationsException oe) - { - // PASS - assertEquals("No such queue \"unknownqueue\"", oe.getMessage()); - } - verify(mockQueue, never()).delete(); - } - - public void testCreateNewDurableExchange() throws Exception - { - _virtualHostManagerMBean.createNewExchange(TEST_EXCHANGE_NAME, TEST_EXCHANGE_TYPE, true); - verify(_mockVirtualHost).createExchange(TEST_EXCHANGE_NAME, State.ACTIVE, true, LifetimePolicy.PERMANENT, 0, TEST_EXCHANGE_TYPE, EMPTY_ARGUMENT_MAP); - } - - public void testCreateNewExchangeWithUnknownExchangeType() throws Exception - { - String exchangeType = "notknown"; - try - { - _virtualHostManagerMBean.createNewExchange(TEST_EXCHANGE_NAME, exchangeType, true); - fail("Exception not thrown"); - } - catch (OperationsException oe) - { - // PASS - } - verify(_mockVirtualHost, never()).createExchange(TEST_EXCHANGE_NAME, State.ACTIVE, true, LifetimePolicy.PERMANENT, 0, exchangeType, EMPTY_ARGUMENT_MAP); - } - - public void testUnregisterExchange() throws Exception - { - Exchange mockExchange = mock(Exchange.class); - when(mockExchange.getName()).thenReturn("exchange1"); - when(_mockVirtualHost.getExchanges()).thenReturn(Collections.singletonList(mockExchange)); - - _virtualHostManagerMBean.unregisterExchange("exchange1"); - verify(mockExchange).delete(); - } - - public void testUnregisterExchangeWhenExchangeDoesNotExist() throws Exception - { - Exchange mockExchange = mock(Exchange.class); - when(mockExchange.getName()).thenReturn("exchange1"); - when(_mockVirtualHost.getExchanges()).thenReturn(Collections.singletonList(mockExchange)); - - try - { - _virtualHostManagerMBean.unregisterExchange("unknownexchange"); - fail("Exception not thrown"); - } - catch(OperationsException oe) - { - // PASS - assertEquals("No such exchange \"unknownexchange\"", oe.getMessage()); - } - - verify(mockExchange, never()).delete(); - } -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java deleted file mode 100644 index 2c341b7f2e..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.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.systest.management.jmx; - -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.management.common.mbeans.ManagedBroker; -import org.apache.qpid.management.common.mbeans.ManagedExchange; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.management.MBeanException; -import javax.management.ObjectName; - -/** - * Tests the JMX API for the Managed Broker. - * - */ -public class BrokerManagementTest extends QpidBrokerTestCase -{ - private static final String VIRTUAL_HOST = "test"; - - /** - * JMX helper. - */ - private JMXTestUtils _jmxUtils; - private ManagedBroker _managedBroker; - - public void setUp() throws Exception - { - _jmxUtils = new JMXTestUtils(this); - _jmxUtils.setUp(); - super.setUp(); - _jmxUtils.open(); - _managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); - } - - public void tearDown() throws Exception - { - if (_jmxUtils != null) - { - _jmxUtils.close(); - } - super.tearDown(); - } - - /** - * Tests queue creation/deletion also verifying the automatic binding to the default exchange. - */ - public void testCreateQueueAndDeletion() throws Exception - { - final String queueName = getTestQueueName(); - final ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString()); - - // Check that bind does not exist before queue creation - assertFalse("Binding to " + queueName + " should not exist in default exchange before queue creation", - defaultExchange.bindings().containsKey(new String[] {queueName})); - - _managedBroker.createNewQueue(queueName, "testowner", true); - - // Ensure the queue exists - assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName)); - assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName)); - - // Now verify that the default exchange has been bound. - assertTrue("Binding to " + queueName + " should exist in default exchange after queue creation", - defaultExchange.bindings().containsKey(new String[] {queueName})); - - // Now delete the queue - _managedBroker.deleteQueue(queueName); - - // Finally ensure that the binding has been removed. - assertFalse("Binding to " + queueName + " should not exist in default exchange after queue deletion", - defaultExchange.bindings().containsKey(new String[] {queueName})); - } - - /** - * Tests exchange creation/deletion via JMX API. - */ - public void testCreateExchangeAndUnregister() throws Exception - { - String exchangeName = getTestName(); - _managedBroker.createNewExchange(exchangeName, "topic", true); - - ManagedExchange exchange = _jmxUtils.getManagedExchange(exchangeName); - assertNotNull("Exchange should exist", exchange); - - _managedBroker.unregisterExchange(exchangeName); - } - - /** - * Tests that it is disallowed to unregister the default exchange. - */ - public void testUnregisterOfDefaultExchangeDisallowed() throws Exception - { - String defaultExchangeName = ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString(); - - try - { - _managedBroker.unregisterExchange(defaultExchangeName); - fail("Exception not thrown"); - } - catch (MBeanException mbe) - { - // PASS - assertEquals("Error in unregistering exchange " + defaultExchangeName, mbe.getMessage()); - assertTrue(mbe.getCause().getMessage().contains("Cannot unregister the default exchange")); - } - final ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(defaultExchangeName); - assertNotNull("Exchange should exist", defaultExchange); - } - -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java deleted file mode 100644 index 28d7bf4aed..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpid.systest.management.jmx; - -import java.io.IOException; -import java.util.Date; -import java.util.Iterator; -import java.util.List; - -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.management.JMException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.TabularData; - -import org.apache.commons.lang.StringUtils; -import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.management.common.mbeans.ManagedConnection; -import org.apache.qpid.management.common.mbeans.ManagedQueue; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -public class ConnectionManagementTest extends QpidBrokerTestCase -{ - private static final String VIRTUAL_HOST_NAME = "test"; - - private JMXTestUtils _jmxUtils; - private Connection _connection; - - public void setUp() throws Exception - { - _jmxUtils = new JMXTestUtils(this); - _jmxUtils.setUp(); // modifies broker config therefore must be done before super.setUp() - super.setUp(); - _jmxUtils.open(); - } - - public void tearDown() throws Exception - { - try - { - if (_jmxUtils != null) - { - _jmxUtils.close(); - } - } - finally - { - super.tearDown(); - } - } - - public void testNumberOfManagedConnectionsMatchesNumberOfClientConnections() throws Exception - { - assertEquals("Expected no managed connections", 0, getManagedConnections().size()); - - _connection = getConnection(); - assertEquals("Expected one managed connection", 1, getManagedConnections().size()); - - _connection.close(); - assertEquals("Expected no managed connections after client connection closed", 0, getManagedConnections().size()); - } - - public void testGetAttributes() throws Exception - { - _connection = getConnection(); - final ManagedConnection mBean = getConnectionMBean(); - - checkAuthorisedId(mBean); - checkClientVersion(mBean); - checkClientId(mBean); - } - - public void testNonTransactedSession() throws Exception - { - _connection = getConnection(); - - boolean transactional = false; - boolean flowBlocked = false; - - _connection.createSession(transactional, Session.AUTO_ACKNOWLEDGE); - - final ManagedConnection mBean = getConnectionMBean(); - final CompositeDataSupport row = getTheOneChannelRow(mBean); - assertChannelRowData(row, 0, transactional, flowBlocked); - } - - public void testTransactedSessionWithUnackMessages() throws Exception - { - _connection = getConnection(); - _connection.start(); - - boolean transactional = true; - int numberOfMessages = 2; - final Session session = _connection.createSession(transactional, Session.SESSION_TRANSACTED); - final Destination destination = session.createQueue(getTestQueueName()); - final MessageConsumer consumer = session.createConsumer(destination); - - sendMessage(session, destination, numberOfMessages); - receiveMessagesWithoutCommit(consumer, numberOfMessages); - - final ManagedConnection mBean = getConnectionMBean(); - final CompositeDataSupport row = getTheOneChannelRow(mBean); - boolean flowBlocked = false; - assertChannelRowData(row, numberOfMessages, transactional, flowBlocked); - - // check that commit advances the lastIoTime - final Date initialLastIOTime = mBean.getLastIoTime(); - session.commit(); - assertTrue("commit should have caused last IO time to advance", mBean.getLastIoTime().after(initialLastIOTime)); - - // check that channels() now returns one session with no unacknowledged messages - final CompositeDataSupport rowAfterCommit = getTheOneChannelRow(mBean); - final Number unackCountAfterCommit = (Number) rowAfterCommit.get(ManagedConnection.UNACKED_COUNT); - assertEquals("Unexpected number of unacknowledged messages", 0, unackCountAfterCommit); - } - - - public void testProducerFlowBlocked() throws Exception - { - _connection = getConnection(); - _connection.start(); - - String queueName = getTestQueueName(); - Session session = _connection.createSession(true, Session.SESSION_TRANSACTED); - Queue queue = session.createQueue(queueName); - createQueueOnBroker(session, queue); - - ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - managedQueue.setFlowResumeCapacity(DEFAULT_MESSAGE_SIZE * 2l); - managedQueue.setCapacity(DEFAULT_MESSAGE_SIZE * 3l); - - final ManagedConnection managedConnection = getConnectionMBean(); - - // Check that producer flow is not block before test - final CompositeDataSupport rowBeforeSend = getTheOneChannelRow(managedConnection); - assertFlowBlocked(rowBeforeSend, false); - - - // Check that producer flow does not become block too soon - sendMessage(session, queue, 3); - final CompositeDataSupport rowBeforeFull = getTheOneChannelRow(managedConnection); - assertFlowBlocked(rowBeforeFull, false); - - // Fourth message will over-fill the queue (but as we are not sending more messages, client thread wont't block) - sendMessage(session, queue, 1); - final CompositeDataSupport rowAfterFull = getTheOneChannelRow(managedConnection); - assertFlowBlocked(rowAfterFull, true); - - // Consume two to bring the queue down to the resume capacity - MessageConsumer consumer = session.createConsumer(queue); - assertNotNull("Could not receive first message", consumer.receive(1000)); - assertNotNull("Could not receive second message", consumer.receive(1000)); - session.commit(); - - // Check that producer flow is no longer blocked - final CompositeDataSupport rowAfterReceive = getTheOneChannelRow(managedConnection); - assertFlowBlocked(rowAfterReceive, false); - } - - private void createQueueOnBroker(Session session, Destination destination) throws JMSException - { - session.createConsumer(destination).close(); // Create a consumer only to cause queue creation - } - - private void assertChannelRowData(final CompositeData row, int unacknowledgedMessages, boolean isTransactional, boolean flowBlocked) - { - assertNotNull(row); - assertEquals("Unexpected transactional flag", isTransactional, row.get(ManagedConnection.TRANSACTIONAL)); - assertEquals("Unexpected unacknowledged message count", unacknowledgedMessages, row.get(ManagedConnection.UNACKED_COUNT)); - assertEquals("Unexpected flow blocked", flowBlocked, row.get(ManagedConnection.FLOW_BLOCKED)); - } - - private void assertFlowBlocked(final CompositeData row, boolean flowBlocked) - { - assertNotNull(row); - assertEquals("Unexpected flow blocked", flowBlocked, row.get(ManagedConnection.FLOW_BLOCKED)); - } - - private void checkAuthorisedId(ManagedConnection mBean) throws Exception - { - assertEquals("Unexpected authorized id", GUEST_USERNAME, mBean.getAuthorizedId()); - } - - private void checkClientVersion(ManagedConnection mBean) throws Exception - { - String expectedVersion = QpidProperties.getReleaseVersion(); - assertTrue(StringUtils.isNotBlank(expectedVersion)); - - assertEquals("Unexpected version", expectedVersion, mBean.getVersion()); - } - - private void checkClientId(ManagedConnection mBean) throws Exception - { - String expectedClientId = _connection.getClientID(); - assertTrue(StringUtils.isNotBlank(expectedClientId)); - - assertEquals("Unexpected ClientId", expectedClientId, mBean.getClientId()); - } - - private ManagedConnection getConnectionMBean() - { - List connections = getManagedConnections(); - assertNotNull("Connection MBean is not found", connections); - assertEquals("Unexpected number of connection mbeans", 1, connections.size()); - final ManagedConnection mBean = connections.get(0); - assertNotNull("Connection MBean is null", mBean); - return mBean; - } - - private List getManagedConnections() - { - return _jmxUtils.getManagedConnections(VIRTUAL_HOST_NAME); - } - - private CompositeDataSupport getTheOneChannelRow(final ManagedConnection mBean) throws Exception - { - TabularData channelsData = getChannelsDataWithRetry(mBean); - - assertEquals("Unexpected number of rows in channel table", 1, channelsData.size()); - - @SuppressWarnings("unchecked") - final Iterator rowItr = (Iterator) channelsData.values().iterator(); - final CompositeDataSupport row = rowItr.next(); - return row; - } - - private void receiveMessagesWithoutCommit(final MessageConsumer consumer, int numberOfMessages) throws Exception - { - for (int i = 0; i < numberOfMessages; i++) - { - final Message m = consumer.receive(1000l); - assertNotNull("Message " + i + " is not received", m); - } - } - - private TabularData getChannelsDataWithRetry(final ManagedConnection mBean) - throws IOException, JMException - { - TabularData channelsData = mBean.channels(); - int retries = 0; - while(channelsData.size() == 0 && retries < 5) - { - sleep(); - channelsData = mBean.channels(); - retries++; - } - return channelsData; - } - - private void sleep() - { - try - { - Thread.sleep(50); - } - catch (InterruptedException ie) - { - Thread.currentThread().interrupt(); - } - }} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java deleted file mode 100644 index ac6730638e..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpid.systest.management.jmx; - -import java.io.File; -import java.util.List; - -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.TabularData; - -import org.apache.qpid.management.common.mbeans.LoggingManagement; -import org.apache.qpid.server.jmx.mbeans.LoggingManagementMBeanTest; -import org.apache.qpid.server.logging.log4j.LoggingFacadeTest; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.util.FileUtils; -import org.apache.qpid.util.LogMonitor; - -/** - * System test for Logging Management. These tests rely on value set within - * test-profiles/log4j-test.xml. - * - * @see LoggingManagementMBeanTest - * @see LoggingFacadeTest - * - */ -public class LoggingManagementTest extends QpidBrokerTestCase -{ - private JMXTestUtils _jmxUtils; - private LoggingManagement _loggingManagement; - private LogMonitor _monitor; - - public void setUp() throws Exception - { - _jmxUtils = new JMXTestUtils(this); - _jmxUtils.setUp(); - - // System test normally run with log for4j test config from beneath test-profiles. We need to - // copy it as some of our tests write to this file. - - File tmpLogFile = File.createTempFile("log4j" + "." + getName(), ".xml"); - tmpLogFile.deleteOnExit(); - FileUtils.copy(_logConfigFile, tmpLogFile); - - _logConfigFile = tmpLogFile; - - super.setUp(); - _jmxUtils.open(); - - _loggingManagement = _jmxUtils.getLoggingManagement(); - _monitor = new LogMonitor(_outputFile); - } - - public void tearDown() throws Exception - { - try - { - if (_jmxUtils != null) - { - _jmxUtils.close(); - } - } - finally - { - super.tearDown(); - } - } - - public void testViewEffectiveRuntimeLoggerLevels() throws Exception - { - final String qpidMainLogger = "org.apache.qpid"; - - TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels(); - final CompositeData row = table.get(new String[] {qpidMainLogger} ); - assertChannelRow(row, qpidMainLogger, "DEBUG"); - } - - public void testViewConfigFileLoggerLevels() throws Exception - { - final String operationalLoggingLogger = "qpid.message"; - - TabularData table = _loggingManagement.viewConfigFileLoggerLevels(); - final CompositeData row = table.get(new String[] {operationalLoggingLogger} ); - assertChannelRow(row, operationalLoggingLogger, "INFO"); - } - - public void testTurnOffOrgApacheQpidAtRuntime() throws Exception - { - final String logger = "org.apache.qpid"; - _monitor.markDiscardPoint(); - _loggingManagement.setRuntimeLoggerLevel(logger, "OFF"); - - List matches = _monitor.findMatches("Setting level to OFF for logger 'org.apache.qpid'"); - assertEquals(1, matches.size()); - - TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels(); - final CompositeData row1 = table.get(new String[] {logger} ); - assertChannelRow(row1, logger, "OFF"); - } - - public void testChangesToConfigFileBecomeEffectiveAfterReload() throws Exception - { - final String operationalLoggingLogger = "qpid.message"; - assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO"); - - _monitor.markDiscardPoint(); - _loggingManagement.setConfigFileLoggerLevel(operationalLoggingLogger, "OFF"); - - List matches = _monitor.findMatches("Setting level to OFF for logger 'qpid.message'"); - assertEquals(1, matches.size()); - - assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO"); - - _loggingManagement.reloadConfigFile(); - - assertEffectiveLoggingLevel(operationalLoggingLogger, "OFF"); - } - - private void assertEffectiveLoggingLevel(String operationalLoggingLogger, String expectedLevel) - { - TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels(); - final CompositeData row1 = table.get(new String[] {operationalLoggingLogger} ); - assertChannelRow(row1, operationalLoggingLogger, expectedLevel); - } - - private void assertChannelRow(final CompositeData row, String logger, String level) - { - assertNotNull("No row for " + logger, row); - assertEquals("Unexpected logger name", logger, row.get(LoggingManagement.LOGGER_NAME)); - assertEquals("Unexpected level", level, row.get(LoggingManagement.LOGGER_LEVEL)); - } - -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java deleted file mode 100644 index 47b38381c5..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java +++ /dev/null @@ -1,480 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.systest.management.jmx; - -import org.apache.qpid.management.common.mbeans.ManagedBroker; -import org.apache.qpid.management.common.mbeans.ManagedConnection; -import org.apache.qpid.management.common.mbeans.ManagedExchange; -import org.apache.qpid.server.logging.AbstractTestLogging; -import org.apache.qpid.server.logging.subjects.AbstractTestLogSubject; -import org.apache.qpid.test.utils.JMXTestUtils; - -import javax.jms.Connection; -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import javax.management.JMException; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * Test class to test if any change in the broker JMX code is affesting the management console - * There are some hardcoding of management feature names and parameter names to create a customized - * look in the console. - */ -public class ManagementActorLoggingTest extends AbstractTestLogging -{ - private JMXTestUtils _jmxUtils; - private boolean _closed = false; - - @Override - public void setUp() throws Exception - { - _jmxUtils = new JMXTestUtils(this); - _jmxUtils.setUp(); - super.setUp(); - _jmxUtils.open(); - } - - @Override - public void tearDown() throws Exception - { - if(!_closed) - { - _jmxUtils.close(); - } - super.tearDown(); - } - - /** - * Description: - * When a connected client has its connection closed via the Management Console this will be logged as a CON-1002 message. - * Input: - * - * 1. Running Broker - * 2. Connected Client - * 3. Connection is closed via Management Console - * Output: - * - * CON-1002 : Close - * - * Validation Steps: - * 4. The CON ID is correct - * 5. This must be the last CON message for the Connection - * 6. It must be preceded by a CON-1001 for this Connection - * - * @throws Exception - {@see ManagedConnection.closeConnection and #getConnection} - * @throws java.io.IOException - if there is a problem reseting the log monitor - */ - public void testConnectionCloseViaManagement() throws IOException, Exception - { - //Create a connection to the broker - Connection connection = getConnection(); - - // Monitor the connection for an exception being thrown - // this should be a DisconnectionException but it is not this tests - // job to valiate that. Only use the exception as a synchronisation - // to check the log file for the Close message - final CountDownLatch exceptionReceived = new CountDownLatch(1); - connection.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - //Failover being attempted. - exceptionReceived.countDown(); - } - }); - - //Remove the connection close from any 0-10 connections - _monitor.markDiscardPoint(); - - // Get a managedConnection - ManagedConnection mangedConnection = _jmxUtils.getManagedObject(ManagedConnection.class, "org.apache.qpid:type=VirtualHost.Connection,*"); - - //Close the connection - mangedConnection.closeConnection(); - - //Wait for the connection to close - assertTrue("Timed out waiting for conneciton to report close", - exceptionReceived.await(2, TimeUnit.SECONDS)); - - //Validate results - List results = waitAndFindMatches("CON-1002"); - - assertEquals("Unexpected Connection Close count", 1, results.size()); - } - - /** - * Description: - * Exchange creation is possible from the Management Console. - * When an exchanged is created in this way then a EXH-1001 create message - * is expected to be logged. - * Input: - * - * 1. Running broker - * 2. Connected Management Console - * 3. Exchange Created via Management Console - * Output: - * - * EXH-1001 : Create : [Durable] Type: Name: - * - * Validation Steps: - * 4. The EXH ID is correct - * 5. The correct tags are present in the message based on the create options - * - * @throws java.io.IOException - if there is a problem reseting the log monitor - * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue} - */ - public void testCreateExchangeDirectTransientViaManagementConsole() throws IOException, JMException - { - _monitor.markDiscardPoint(); - - _jmxUtils.createExchange("test", getName(), "direct", false); - - // Validate - - //1 - ID is correct - List results = waitAndFindMatches("EXH-1001"); - - assertEquals("More than one exchange creation found", 1, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct exchange name - assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } - - public void testCreateExchangeTopicTransientViaManagementConsole() throws IOException, JMException - { - //Remove any previous exchange declares - _monitor.markDiscardPoint(); - - _jmxUtils.createExchange("test", getName(), "topic", false); - - // Validate - - //1 - ID is correct - List results = waitAndFindMatches("EXH-1001"); - - assertEquals("More than one exchange creation found", 1, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct exchange name - assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - - } - - public void testCreateExchangeFanoutTransientViaManagementConsole() throws IOException, JMException - { - //Remove any previous exchange declares - _monitor.markDiscardPoint(); - - _jmxUtils.createExchange("test", getName(), "fanout", false); - - // Validate - - //1 - ID is correct - List results = waitAndFindMatches("EXH-1001"); - - assertEquals("More than one exchange creation found", 1, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct exchange name - assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - - } - - public void testCreateExchangeHeadersTransientViaManagementConsole() throws IOException, JMException - { - //Remove any previous exchange declares - _monitor.markDiscardPoint(); - - _jmxUtils.createExchange("test", getName(), "headers", false); - - // Validate - - //1 - ID is correct - List results = waitAndFindMatches("EXH-1001"); - - assertEquals("More than one exchange creation found", 1, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct exchange name - assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - - } - - /** - * Description: - * Queue creation is possible from the Management Console. When a queue is created in this way then a QUE-1001 create message is expected to be logged. - * Input: - * - * 1. Running broker - * 2. Connected Management Console - * 3. Queue Created via Management Console - * Output: - * - * QUE-1001 : Create : Transient Owner: - * - * Validation Steps: - * 4. The QUE ID is correct - * 5. The correct tags are present in the message based on the create options - * - * @throws java.io.IOException - if there is a problem reseting the log monitor - * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue} - */ - public void testCreateQueueTransientViaManagementConsole() throws IOException, JMException - { - //Remove any previous queue declares - _monitor.markDiscardPoint(); - - _jmxUtils.createQueue("test", getName(), null, false); - - // Validate - - List results = waitAndFindMatches("QUE-1001"); - - assertEquals("More than one queue creation found", 1, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct queue name - String subject = fromSubject(log); - assertEquals("Incorrect queue name created", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } - - /** - * Description: - * The ManagementConsole can be used to delete a queue. When this is done a QUE-1002 Deleted message must be logged. - * Input: - * - * 1. Running Broker - * 2. Queue created on the broker with no subscribers - * 3. Management Console connected - * 4. Queue is deleted via Management Console - * Output: - * - * QUE-1002 : Deleted - * - * Validation Steps: - * 5. The QUE ID is correct - * - * @throws java.io.IOException - if there is a problem reseting the log monitor - * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue} - */ - public void testQueueDeleteViaManagementConsole() throws IOException, JMException - { - //Remove any previous queue declares - _monitor.markDiscardPoint(); - - _jmxUtils.createQueue("test", getName(), null, false); - - ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test"); - - managedBroker.deleteQueue(getName()); - - List results = waitAndFindMatches("QUE-1002"); - - assertEquals("More than one queue deletion found", 1, results.size()); - - String log = getLog(results.get(0)); - - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect queue named in delete", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - - } - - /** - * Description: - * The binding of a Queue and an Exchange is done via a Binding. When this Binding is created via the Management Console a BND-1001 Create message will be logged. - * Input: - * - * 1. Running Broker - * 2. Connected Management Console - * 3. Use Management Console to perform binding - * Output: - * - * BND-1001 : Create - * - * Validation Steps: - * 4. The BND ID is correct - * 5. This will be the first message for the given binding - * - * @throws java.io.IOException - if there is a problem reseting the log monitor - * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.createNewBinding} - */ - public void testBindingCreateOnDirectViaManagementConsole() throws IOException, JMException - { - //Remove any previous queue declares - _monitor.markDiscardPoint(); - - _jmxUtils.createQueue("test", getName(), null, false); - - ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.direct"); - - managedExchange.createNewBinding(getName(), getName()); - - List results = waitAndFindMatches("BND-1001"); - - assertEquals("Unexpected number of bindings logged", 2, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } - - public void testBindingCreateOnTopicViaManagementConsole() throws IOException, JMException - { - //Remove any previous queue declares - _monitor.markDiscardPoint(); - - _jmxUtils.createQueue("test", getName(), null, false); - - ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.topic"); - - managedExchange.createNewBinding(getName(), getName()); - - List results = waitAndFindMatches("BND-1001"); - - assertEquals("Unexpected number of bindings logged", 2, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } - - public void testBindingCreateOnFanoutViaManagementConsole() throws IOException, JMException - { - //Remove any previous queue declares - _monitor.markDiscardPoint(); - - _jmxUtils.createQueue("test", getName(), null, false); - - ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.fanout"); - - managedExchange.createNewBinding(getName(), getName()); - - List results = waitAndFindMatches("BND-1001"); - - assertEquals("Unexpected number of bindings logged", 2, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } - - /** - * Description: - * Bindings can be deleted so that a queue can be rebound with a different set of values. This can be performed via the Management Console - * Input: - * - * 1. Running Broker - * 2. Management Console connected - * 3. Management Console is used to perform unbind. - * Output: - * - * BND-1002 : Deleted - * - * Validation Steps: - * 4. The BND ID is correct - * 5. There must have been a BND-1001 Create message first. - * 6. This will be the last message for the given binding - * - * @throws java.io.IOException - if there is a problem reseting the log monitor or an issue with the JMX Connection - * @throws javax.management.JMException - {@see #createExchange and ManagedBroker.unregisterExchange} - */ - public void testUnRegisterExchangeViaManagementConsole() throws IOException, JMException - { - //Remove any previous queue declares - _monitor.markDiscardPoint(); - - _jmxUtils.createExchange("test", getName(), "direct", false); - - ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test"); - - managedBroker.unregisterExchange(getName()); - - List results = waitAndFindMatches("EXH-1002"); - - assertEquals("More than one exchange deletion found", 1, results.size()); - - String log = getLog(results.get(0)); - - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect exchange named in delete", "direct/" + getName(), AbstractTestLogSubject.getSlice("ex", subject)); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } - -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java deleted file mode 100644 index 6100d5a23e..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.systest.management.jmx; - - -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.logging.AbstractTestLogging; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.util.LogMonitor; - -import java.io.File; -import java.util.List; - -/** - * Management Console Test Suite - * - * The Management Console test suite validates that the follow log messages as specified in the Functional Specification. - * - * This suite of tests validate that the management console messages occur correctly and according to the following format: - * - * MNG-1001 : Startup - * MNG-1002 : Starting : : Listening on port - * MNG-1003 : Shutting down : : port - * MNG-1004 : Ready - * MNG-1005 : Stopped - * MNG-1006 : Using SSL Keystore : - * MNG-1007 : Open : User - * MNG-1008 : Close : User - */ -public class ManagementLoggingTest extends AbstractTestLogging -{ - private static final String MNG_PREFIX = "MNG-"; - - public void setUp() throws Exception - { - setLogMessagePrefix(); - - // We either do this here or have a null check in tearDown. - // As when this test is run against profiles other than java it will NPE - _monitor = new LogMonitor(_outputFile); - //We explicitly do not call super.setUp as starting up the broker is - //part of the test case. - - } - - /** - * Description: - * Using the startup configuration validate that the management startup - * message is logged correctly. - * Input: - * Standard configuration with management enabled - * Output: - * - * MNG-1001 : Startup - * - * Constraints: - * This is the FIRST message logged by MNG - * Validation Steps: - * - * 1. The BRK ID is correct - * 2. This is the FIRST message logged by MNG - */ - public void testManagementStartupEnabled() throws Exception - { - // This test only works on java brokers - if (isJavaBroker()) - { - startBrokerAndCreateMonitor(true, false); - - // Ensure we have received the MNG log msg. - waitForMessage("MNG-1001"); - - List results = findMatches(MNG_PREFIX); - // Validation - - assertTrue("MNGer message not logged", results.size() > 0); - - String log = getLogMessage(results, 0); - - //1 - validateMessageID("MNG-1001", log); - - //2 - //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J) - results = findMatches("MNG-1001"); - assertEquals("Unexpected startup message count.", - 2, results.size()); - - //3 - assertEquals("Startup log message is not 'Startup'.", "Startup", - getMessageString(log)); - } - } - - /** - * Description: - * Verify that when management is disabled in the configuration file the - * startup message is not logged. - * Input: - * Standard configuration with management disabled - * Output: - * NO MNG messages - * Validation Steps: - * - * 1. Validate that no MNG messages are produced. - */ - public void testManagementStartupDisabled() throws Exception - { - if (isJavaBroker()) - { - startBrokerAndCreateMonitor(false, false); - - List results = findMatches(MNG_PREFIX); - // Validation - - assertEquals("MNGer messages logged", 0, results.size()); - } - } - - /** - * The two MNG-1002 messages are logged at the same time so lets test them - * at the same time. - * - * Description: - * Using the default configuration validate that the RMI Registry socket is - * correctly reported as being opened - * - * Input: - * The default configuration file - * Output: - * - * MESSAGE MNG-1002 : Starting : RMI Registry : Listening on port 8999 - * - * Constraints: - * The RMI ConnectorServer and Registry log messages do not have a prescribed order - * Validation Steps: - * - * 1. The MNG ID is correct - * 2. The specified port is the correct '8999' - * - * Description: - * Using the default configuration validate that the RMI ConnectorServer - * socket is correctly reported as being opened - * - * Input: - * The default configuration file - * Output: - * - * MESSAGE MNG-1002 : Starting : RMI ConnectorServer : Listening on port 9099 - * - * Constraints: - * The RMI ConnectorServer and Registry log messages do not have a prescribed order - * Validation Steps: - * - * 1. The MNG ID is correct - * 2. The specified port is the correct '9099' - */ - public void testManagementStartupRMIEntries() throws Exception - { - if (isJavaBroker()) - { - startBrokerAndCreateMonitor(true, false); - - List results = waitAndFindMatches("MNG-1002"); - // Validation - - //There will be 4 startup messages (two via SystemOut, and two via Log4J) - assertEquals("Unexpected MNG-1002 message count", 4, results.size()); - - String log = getLogMessage(results, 0); - - //1 - validateMessageID("MNG-1002", log); - - //Check the RMI Registry port is as expected - int mPort = getManagementPort(getPort()); - assertTrue("RMI Registry port not as expected(" + mPort + ").:" + getMessageString(log), - getMessageString(log).endsWith(String.valueOf(mPort))); - - log = getLogMessage(results, 2); - - //1 - validateMessageID("MNG-1002", log); - - // We expect the RMI Registry port (the defined 'management port') to be - // 100 lower than the JMX RMIConnector Server Port (the actual JMX server) - int jmxPort = mPort + ServerConfiguration.JMXPORT_CONNECTORSERVER_OFFSET; - assertTrue("JMX RMIConnectorServer port not as expected(" + jmxPort + ").:" + getMessageString(log), - getMessageString(log).endsWith(String.valueOf(jmxPort))); - } - } - - /** - * Description: - * Using the default configuration with SSL enabled for the management port the SSL Keystore path should be reported via MNG-1006 - * Input: - * Management SSL enabled default configuration. - * Output: - * - * MESSAGE MNG-1006 : Using SSL Keystore : test_resources/ssl/keystore.jks - * - * Validation Steps: - * - * 1. The MNG ID is correct - * 2. The keystore path is as specified in the configuration - */ - public void testManagementStartupSSLKeystore() throws Exception - { - if (isJavaBroker()) - { - startBrokerAndCreateMonitor(true, true); - - List results = waitAndFindMatches("MNG-1006"); - - assertTrue("MNGer message not logged", results.size() > 0); - - String log = getLogMessage(results, 0); - - //1 - validateMessageID("MNG-1006", log); - - // Validate we only have two MNG-1002 (one via stdout, one via log4j) - results = findMatches("MNG-1006"); - assertEquals("Upexpected SSL Keystore message count", - 2, results.size()); - - // Validate the keystore path is as expected - assertTrue("SSL Keystore entry expected.:" + getMessageString(log), - getMessageString(log).endsWith(new File(getConfigurationStringProperty("management.ssl.keyStorePath")).getName())); - } - } - - /** - * Description: Tests the management connection open/close are logged correctly. - * - * Output: - * - * MESSAGE MNG-1007 : Open : User - * MESSAGE MNG-1008 : Close : User - * - * Validation Steps: - * - * 1. The MNG ID is correct - * 2. The message and username are correct - */ - public void testManagementUserOpenClose() throws Exception - { - if (isJavaBroker()) - { - startBrokerAndCreateMonitor(true, false); - - final JMXTestUtils jmxUtils = new JMXTestUtils(this); - List openResults = null; - List closeResults = null; - try - { - jmxUtils.setUp(); - jmxUtils.open(); - openResults = waitAndFindMatches("MNG-1007"); - } - finally - { - if (jmxUtils != null) - { - jmxUtils.close(); - closeResults = waitAndFindMatches("MNG-1008"); - } - } - - assertNotNull("Management Open results null", openResults.size()); - assertEquals("Management Open logged unexpected number of times", 1, openResults.size()); - - assertNotNull("Management Close results null", closeResults.size()); - assertEquals("Management Close logged unexpected number of times", 1, closeResults.size()); - - final String openMessage = getMessageString(getLogMessage(openResults, 0)); - assertTrue("Unexpected open message " + openMessage, openMessage.endsWith("Open : User admin")); - final String closeMessage = getMessageString(getLogMessage(closeResults, 0)); - assertTrue("Unexpected close message " + closeMessage, closeMessage.endsWith("Close : User admin")); - } - } - - private void startBrokerAndCreateMonitor(boolean managementEnabled, boolean useManagementSSL) throws Exception - { - //Ensure management is on - setConfigurationProperty("management.enabled", String.valueOf(managementEnabled)); - - if(useManagementSSL) - { - // This test requires we have an ssl connection - setConfigurationProperty("management.ssl.enabled", "true"); - } - - startBroker(); - - // Now we can create the monitor as _outputFile will now be defined - _monitor = new LogMonitor(_outputFile); - } -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java deleted file mode 100644 index 8ae4fec975..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpid.systest.management.jmx; - -import org.apache.commons.lang.time.FastDateFormat; - -import org.apache.log4j.Logger; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.configuration.ClientProperties; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.management.common.mbeans.ManagedBroker; -import org.apache.qpid.management.common.mbeans.ManagedQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.queue.NotificationCheckTest; -import org.apache.qpid.server.queue.SimpleAMQQueueTest; -import org.apache.qpid.test.client.destination.AddressBasedDestinationTest; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.Queue; -import javax.jms.Session; -import javax.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; -import java.util.Map; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -/** - * Tests the JMX API for the Managed Queue. - * - */ -public class QueueManagementTest extends QpidBrokerTestCase -{ - - private static final Logger LOGGER = Logger.getLogger(QueueManagementTest.class); - - private static final String VIRTUAL_HOST = "test"; - private static final String TEST_QUEUE_DESCRIPTION = "my description"; - - private JMXTestUtils _jmxUtils; - private Connection _connection; - private Session _session; - - private String _sourceQueueName; - private String _destinationQueueName; - private Destination _sourceQueue; - private Destination _destinationQueue; - private ManagedQueue _managedSourceQueue; - private ManagedQueue _managedDestinationQueue; - - - public void setUp() throws Exception - { - _jmxUtils = new JMXTestUtils(this); - _jmxUtils.setUp(); - - super.setUp(); - _sourceQueueName = getTestQueueName() + "_src"; - _destinationQueueName = getTestQueueName() + "_dest"; - - _connection = getConnection(); - _connection.start(); - - _session = _connection.createSession(true, Session.SESSION_TRANSACTED); - _sourceQueue = _session.createQueue(_sourceQueueName); - _destinationQueue = _session.createQueue(_destinationQueueName); - createQueueOnBroker(_sourceQueue); - createQueueOnBroker(_destinationQueue); - - _jmxUtils.open(); - - _managedSourceQueue = _jmxUtils.getManagedQueue(_sourceQueueName); - _managedDestinationQueue = _jmxUtils.getManagedQueue(_destinationQueueName); - } - - public void tearDown() throws Exception - { - if (_jmxUtils != null) - { - _jmxUtils.close(); - } - super.tearDown(); - } - - public void testQueueAttributes() throws Exception - { - Queue queue = _session.createQueue(getTestQueueName()); - createQueueOnBroker(queue); - - final String queueName = queue.getQueueName(); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals("Unexpected name", queueName, managedQueue.getName()); - assertEquals("Unexpected queue type", "standard", managedQueue.getQueueType()); - } - - public void testExclusiveQueueHasJmsClientIdAsOwner() throws Exception - { - Queue tmpQueue = _session.createTemporaryQueue(); - - final String queueName = tmpQueue.getQueueName(); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertNotNull(_connection.getClientID()); - assertEquals("Unexpected owner", _connection.getClientID(), managedQueue.getOwner()); - } - - public void testNonExclusiveQueueHasNoOwner() throws Exception - { - Queue nonExclusiveQueue = _session.createQueue(getTestQueueName()); - createQueueOnBroker(nonExclusiveQueue); - - final String queueName = nonExclusiveQueue.getQueueName(); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertNull("Unexpected owner", managedQueue.getOwner()); - } - - public void testSetNewQueueDescriptionOnExistingQueue() throws Exception - { - Queue queue = _session.createQueue(getTestQueueName()); - createQueueOnBroker(queue); - - final String queueName = queue.getQueueName(); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertNull("Unexpected description", managedQueue.getDescription()); - - managedQueue.setDescription(TEST_QUEUE_DESCRIPTION); - assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); - } - - public void testNewQueueWithDescription() throws Exception - { - String queueName = getTestQueueName(); - Map arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION); - ((AMQSession)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); - } - - /** - * Requires persistent store. - */ - public void testQueueDescriptionSurvivesRestart() throws Exception - { - String queueName = getTestQueueName(); - Map arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION); - - ((AMQSession)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments); - - ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); - - restartBroker(); - - managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); - } - - /** - * Tests queue creation with {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument. Also tests - * that the attribute is exposed correctly through {@link ManagedQueue#getMaximumDeliveryCount()}. - */ - public void testCreateQueueWithMaximumDeliveryCountSet() throws Exception - { - final String queueName = getName(); - final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); - - final Integer deliveryCount = 1; - final Map arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, (Object)deliveryCount); - managedBroker.createNewQueue(queueName, null, true, arguments); - - // Ensure the queue exists - assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName("test", queueName)); - assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName)); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals("Unexpected maximum delivery count", deliveryCount, managedQueue.getMaximumDeliveryCount()); - } - - /** - * Requires 0-10 as relies on ADDR addresses. - * @see AddressBasedDestinationTest for the testing of message routing to the alternate exchange - */ - public void testGetSetAlternateExchange() throws Exception - { - String queueName = getTestQueueName(); - String altExchange = "amq.fanout"; - String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange); - Queue queue = _session.createQueue(addrWithAltExch); - - createQueueOnBroker(queue); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange()); - - String newAltExch = "amq.topic"; - managedQueue.setAlternateExchange(newAltExch); - assertEquals("Unexpected alternate exchange after set", newAltExch, managedQueue.getAlternateExchange()); - } - - /** - * Requires 0-10 as relies on ADDR addresses. - */ - public void testRemoveAlternateExchange() throws Exception - { - String queueName = getTestQueueName(); - String altExchange = "amq.fanout"; - String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange); - Queue queue = _session.createQueue(addrWithAltExch); - - createQueueOnBroker(queue); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange()); - - managedQueue.setAlternateExchange(""); - assertNull("Unexpected alternate exchange after set", managedQueue.getAlternateExchange()); - } - - /** - * Requires persistent store - * Requires 0-10 as relies on ADDR addresses. - */ - public void testAlternateExchangeSurvivesRestart() throws Exception - { - String nonMandatoryExchangeName = "exch" + getName(); - - final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); - managedBroker.createNewExchange(nonMandatoryExchangeName, "fanout", true); - - String queueName1 = getTestQueueName() + "1"; - String altExchange1 = "amq.fanout"; - String addr1WithAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName1, altExchange1); - Queue queue1 = _session.createQueue(addr1WithAltExch); - - String queueName2 = getTestQueueName() + "2"; - String addr2WithoutAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue}}", queueName2); - Queue queue2 = _session.createQueue(addr2WithoutAltExch); - - createQueueOnBroker(queue1); - createQueueOnBroker(queue2); - - ManagedQueue managedQueue1 = _jmxUtils.getManagedQueue(queueName1); - assertEquals("Newly created queue1 does not have expected alternate exchange", altExchange1, managedQueue1.getAlternateExchange()); - - ManagedQueue managedQueue2 = _jmxUtils.getManagedQueue(queueName2); - assertNull("Newly created queue2 does not have expected alternate exchange", managedQueue2.getAlternateExchange()); - - String altExchange2 = nonMandatoryExchangeName; - managedQueue2.setAlternateExchange(altExchange2); - - restartBroker(); - - managedQueue1 = _jmxUtils.getManagedQueue(queueName1); - assertEquals("Queue1 does not have expected alternate exchange after restart", altExchange1, managedQueue1.getAlternateExchange()); - - managedQueue2 = _jmxUtils.getManagedQueue(queueName2); - assertEquals("Queue2 does not have expected updated alternate exchange after restart", altExchange2, managedQueue2.getAlternateExchange()); - } - - /** - * Tests the ability to receive queue alerts as JMX notifications. - * - * @see NotificationCheckTest - * @see SimpleAMQQueueTest#testNotificationFiredAsync() - * @see SimpleAMQQueueTest#testNotificationFiredOnEnqueue() - */ - public void testQueueNotification() throws Exception - { - final String queueName = getName(); - final long maximumMessageCount = 3; - - Queue queue = _session.createQueue(queueName); - createQueueOnBroker(queue); - - ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - managedQueue.setMaximumMessageCount(maximumMessageCount); - - RecordingNotificationListener listener = new RecordingNotificationListener(1); - - _jmxUtils.addNotificationListener(_jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName), listener, null, null); - - // Send two messages - this should *not* trigger the notification - sendMessage(_session, queue, 2); - - assertEquals("Premature notification received", 0, listener.getNumberOfNotificationsReceived()); - - // A further message should trigger the message count alert - sendMessage(_session, queue, 1); - - listener.awaitExpectedNotifications(5, TimeUnit.SECONDS); - - assertEquals("Unexpected number of JMX notifications received", 1, listener.getNumberOfNotificationsReceived()); - - Notification notification = listener.getLastNotification(); - assertEquals("Unexpected notification message", "MESSAGE_COUNT_ALERT 3: Maximum count on queue threshold (3) breached.", notification.getMessage()); - } - - /** - * Tests {@link ManagedQueue#viewMessages(long, long)} interface. - */ - public void testViewSingleMessage() throws Exception - { - final List sentMessages = sendMessage(_session, _sourceQueue, 1); - syncSession(_session); - final Message sentMessage = sentMessages.get(0); - - assertEquals("Unexpected queue depth", 1, _managedSourceQueue.getMessageCount().intValue()); - - // Check the contents of the message - final TabularData tab = _managedSourceQueue.viewMessages(1l, 1l); - assertEquals("Unexpected number of rows in table", 1, tab.size()); - final Iterator rowItr = (Iterator) tab.values().iterator(); - - final CompositeData row1 = rowItr.next(); - assertNotNull("Message should have AMQ message id", row1.get(ManagedQueue.MSG_AMQ_ID)); - assertEquals("Unexpected queue position", 1l, row1.get(ManagedQueue.MSG_QUEUE_POS)); - assertEquals("Unexpected redelivered flag", Boolean.FALSE, row1.get(ManagedQueue.MSG_REDELIVERED)); - - // Check the contents of header (encoded in a string array) - final String[] headerArray = (String[]) row1.get(ManagedQueue.MSG_HEADER); - assertNotNull("Expected message header array", headerArray); - final Map headers = headerArrayToMap(headerArray); - - final String expectedJMSMessageID = isBroker010() ? sentMessage.getJMSMessageID().replace("ID:", "") : sentMessage.getJMSMessageID(); - final String expectedFormattedJMSTimestamp = FastDateFormat.getInstance(ManagedQueue.JMSTIMESTAMP_DATETIME_FORMAT).format(sentMessage.getJMSTimestamp()); - assertEquals("Unexpected JMSMessageID within header", expectedJMSMessageID, headers.get("JMSMessageID")); - assertEquals("Unexpected JMSPriority within header", String.valueOf(sentMessage.getJMSPriority()), headers.get("JMSPriority")); - assertEquals("Unexpected JMSTimestamp within header", expectedFormattedJMSTimestamp, headers.get("JMSTimestamp")); - } - - /** - * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface. - */ - public void testMoveMessagesBetweenQueues() throws Exception - { - final int numberOfMessagesToSend = 10; - - sendMessage(_session, _sourceQueue, numberOfMessagesToSend); - syncSession(_session); - assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); - - // Move first three messages to destination - long fromMessageId = amqMessagesIds.get(0); - long toMessageId = amqMessagesIds.get(2); - _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); - - assertEquals("Unexpected queue depth on destination queue after first move", 3, _managedDestinationQueue.getMessageCount().intValue()); - assertEquals("Unexpected queue depth on source queue after first move", 7, _managedSourceQueue.getMessageCount().intValue()); - - // Now move a further two messages to destination - fromMessageId = amqMessagesIds.get(7); - toMessageId = amqMessagesIds.get(8); - _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); - assertEquals("Unexpected queue depth on destination queue after second move", 5, _managedDestinationQueue.getMessageCount().intValue()); - assertEquals("Unexpected queue depth on source queue after second move", 5, _managedSourceQueue.getMessageCount().intValue()); - - assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8); - } - - /** - * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface. - */ - public void testCopyMessagesBetweenQueues() throws Exception - { - final int numberOfMessagesToSend = 10; - sendMessage(_session, _sourceQueue, numberOfMessagesToSend); - syncSession(_session); - assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); - - // Copy first three messages to destination - long fromMessageId = amqMessagesIds.get(0); - long toMessageId = amqMessagesIds.get(2); - _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName); - - assertEquals("Unexpected queue depth on destination queue after first copy", 3, _managedDestinationQueue.getMessageCount().intValue()); - assertEquals("Unexpected queue depth on source queue after first copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - // Now copy a further two messages to destination - fromMessageId = amqMessagesIds.get(7); - toMessageId = amqMessagesIds.get(8); - _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName); - assertEquals("Unexpected queue depth on destination queue after second copy", 5, _managedDestinationQueue.getMessageCount().intValue()); - assertEquals("Unexpected queue depth on source queue after second copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8); - } - - public void testMoveMessagesBetweenQueuesWithActiveConsumerOnSourceQueue() throws Exception - { - setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString()); - Connection asyncConnection = getConnection(); - asyncConnection.start(); - - final int numberOfMessagesToSend = 50; - sendMessage(_session, _sourceQueue, numberOfMessagesToSend); - syncSession(_session); - assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); - - long fromMessageId = amqMessagesIds.get(0); - long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1); - - CountDownLatch consumerReadToHalfwayLatch = new CountDownLatch(numberOfMessagesToSend / 2); - AtomicInteger totalConsumed = new AtomicInteger(0); - startAsyncConsumerOn(_sourceQueue, asyncConnection, consumerReadToHalfwayLatch, totalConsumed); - - boolean halfwayPointReached = consumerReadToHalfwayLatch.await(5000, TimeUnit.MILLISECONDS); - assertTrue("Did not read half of messages within time allowed", halfwayPointReached); - - _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); - - asyncConnection.stop(); - - // The exact number of messages moved will be non deterministic, as the number of messages processed - // by the consumer cannot be predicted. There is also the possibility that a message can remain - // on the source queue. This situation will arise if a message has been acquired by the consumer, but not - // yet delivered to the client application (i.e. MessageListener#onMessage()) when the Connection#stop() occurs. - // - // The number of messages moved + the number consumed + any messages remaining on source should - // *always* be equal to the number we originally sent. - - int numberOfMessagesReadByConsumer = totalConsumed.intValue(); - int numberOfMessagesOnDestinationQueue = _managedDestinationQueue.getMessageCount().intValue(); - int numberOfMessagesRemainingOnSourceQueue = _managedSourceQueue.getMessageCount().intValue(); - - LOGGER.debug("Async consumer read : " + numberOfMessagesReadByConsumer - + " Number of messages moved to destination : " + numberOfMessagesOnDestinationQueue - + " Number of messages remaining on source : " + numberOfMessagesRemainingOnSourceQueue); - assertEquals("Unexpected number of messages after move", numberOfMessagesToSend, numberOfMessagesReadByConsumer + numberOfMessagesOnDestinationQueue + numberOfMessagesRemainingOnSourceQueue); - } - - public void testMoveMessagesBetweenQueuesWithActiveConsumerOnDestinationQueue() throws Exception - { - setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString()); - Connection asyncConnection = getConnection(); - asyncConnection.start(); - - final int numberOfMessagesToSend = 50; - sendMessage(_session, _sourceQueue, numberOfMessagesToSend); - syncSession(_session); - assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); - long fromMessageId = amqMessagesIds.get(0); - long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1); - - AtomicInteger totalConsumed = new AtomicInteger(0); - CountDownLatch allMessagesConsumedLatch = new CountDownLatch(numberOfMessagesToSend); - startAsyncConsumerOn(_destinationQueue, asyncConnection, allMessagesConsumedLatch, totalConsumed); - - _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); - - allMessagesConsumedLatch.await(5000, TimeUnit.MILLISECONDS); - assertEquals("Did not consume all messages from destination queue", numberOfMessagesToSend, totalConsumed.intValue()); - } - - private void startAsyncConsumerOn(Destination queue, Connection asyncConnection, - final CountDownLatch requiredNumberOfMessagesRead, final AtomicInteger totalConsumed) throws Exception - { - Session session = asyncConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - MessageConsumer consumer = session.createConsumer(queue); - consumer.setMessageListener(new MessageListener() - { - - @Override - public void onMessage(Message arg0) - { - totalConsumed.incrementAndGet(); - requiredNumberOfMessagesRead.countDown(); - } - }); - } - - private void assertMessageIndicesOn(Destination queue, int... expectedIndices) throws Exception - { - MessageConsumer consumer = _session.createConsumer(queue); - - for (int i : expectedIndices) - { - Message message = consumer.receive(1000); - assertNotNull("Expected message with index " + i, message); - assertEquals("Expected message with index " + i, i, message.getIntProperty(INDEX)); - } - - assertNull("Unexpected message encountered", consumer.receive(1000)); - } - - private List getAMQMessageIdsOn(ManagedQueue managedQueue, long startIndex, long endIndex) throws Exception - { - final SortedSet messageIds = new TreeSet(); - - final TabularData tab = managedQueue.viewMessages(startIndex, endIndex); - final Iterator rowItr = (Iterator) tab.values().iterator(); - while(rowItr.hasNext()) - { - final CompositeData row = rowItr.next(); - long amqMessageId = (Long)row.get(ManagedQueue.MSG_AMQ_ID); - messageIds.add(amqMessageId); - } - - return new ArrayList(messageIds); - } - - /** - * - * Utility method to convert array of Strings in the form x = y into a - * map with key/value x => y. - * - */ - private Map headerArrayToMap(final String[] headerArray) - { - final Map headerMap = new HashMap(); - final List headerList = Arrays.asList(headerArray); - for (Iterator iterator = headerList.iterator(); iterator.hasNext();) - { - final String nameValuePair = iterator.next(); - final String[] nameValue = nameValuePair.split(" *= *", 2); - headerMap.put(nameValue[0], nameValue[1]); - } - return headerMap; - } - - private void createQueueOnBroker(Destination destination) throws JMSException - { - _session.createConsumer(destination).close(); // Create a consumer only to cause queue creation - } - - private void syncSession(Session session) throws Exception - { - ((AMQSession)session).sync(); - } - - private final class RecordingNotificationListener implements NotificationListener - { - private final CountDownLatch _notificationReceivedLatch; - private final AtomicInteger _numberOfNotifications; - private final AtomicReference _lastNotification; - - private RecordingNotificationListener(int expectedNumberOfNotifications) - { - _notificationReceivedLatch = new CountDownLatch(expectedNumberOfNotifications); - _numberOfNotifications = new AtomicInteger(0); - _lastNotification = new AtomicReference(); - } - - @Override - public void handleNotification(Notification notification, Object handback) - { - _lastNotification.set(notification); - _numberOfNotifications.incrementAndGet(); - _notificationReceivedLatch.countDown(); - } - - public int getNumberOfNotificationsReceived() - { - return _numberOfNotifications.get(); - } - - public Notification getLastNotification() - { - return _lastNotification.get(); - } - - public void awaitExpectedNotifications(long timeout, TimeUnit timeunit) throws InterruptedException - { - _notificationReceivedLatch.await(timeout, timeunit); - } - } - -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java deleted file mode 100644 index c3fff94923..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.systest.management.jmx; - -import java.util.List; - -import javax.jms.Connection; -import javax.jms.MessageConsumer; -import javax.jms.Queue; -import javax.jms.Session; - -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.management.common.mbeans.ManagedBroker; -import org.apache.qpid.management.common.mbeans.ManagedConnection; -import org.apache.qpid.management.common.mbeans.ServerInformation; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -public class StatisticsTest extends QpidBrokerTestCase -{ - private static final String TEST_USER = "admin"; - private static final String TEST_PASSWORD = "admin"; - private static final int MESSAGE_COUNT_TEST = 5; - private static final int MESSAGE_COUNT_DEV = 9; - - private JMXTestUtils _jmxUtils; - private Connection _test1, _dev; - private Session _testSession, _developmentSession; - private Queue _developmentQueue, _testQueue; - protected String _brokerUrl; - - @Override - public void setUp() throws Exception - { - _jmxUtils = new JMXTestUtils(this, TEST_USER, TEST_PASSWORD); - _jmxUtils.setUp(); - - super.setUp(); - - _brokerUrl = getBroker().toString(); - _test1 = new AMQConnection(_brokerUrl, TEST_USER, TEST_PASSWORD, "clientid", "test"); - _dev = new AMQConnection(_brokerUrl, TEST_USER, TEST_PASSWORD, "clientid", "development"); - _test1.start(); - _dev.start(); - - _testSession = _test1.createSession(true, Session.SESSION_TRANSACTED); - _developmentSession = _dev.createSession(true, Session.SESSION_TRANSACTED); - - _developmentQueue = _developmentSession.createQueue(getTestQueueName()); - _testQueue = _testSession.createQueue(getTestQueueName()); - - //Create queues by opening and closing consumers - final MessageConsumer testConsumer = _testSession.createConsumer(_testQueue); - testConsumer.close(); - final MessageConsumer developmentConsumer = _developmentSession.createConsumer(_developmentQueue); - developmentConsumer.close(); - - _jmxUtils.open(); - } - - @Override - public void tearDown() throws Exception - { - _jmxUtils.close(); - - super.tearDown(); - } - - public void testInitialStatisticValues() throws Exception - { - //Check initial values - checkSingleConnectionOnVHostStatistics("test", 0, 0, 0, 0); - checkVHostStatistics("test", 0, 0, 0, 0); - checkSingleConnectionOnVHostStatistics("development", 0, 0, 0, 0); - checkVHostStatistics("development", 0, 0, 0, 0); - checkBrokerStatistics(0, 0, 0, 0); - } - - public void testSendOnSingleVHost() throws Exception - { - sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST); - - //Check values - checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); - checkVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); - checkSingleConnectionOnVHostStatistics("development", 0, 0, 0, 0); - checkVHostStatistics("development", 0, 0, 0, 0); - checkBrokerStatistics(MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); - } - - public void testSendOnTwoVHosts() throws Exception - { - sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST); - sendMessagesAndSync(_developmentSession, _developmentQueue, MESSAGE_COUNT_DEV); - - //Check values - checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); - checkVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); - checkSingleConnectionOnVHostStatistics("development", MESSAGE_COUNT_DEV, 0, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, 0); - checkVHostStatistics("development", MESSAGE_COUNT_DEV, 0, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, 0); - checkBrokerStatistics(MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, 0, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE, 0); - } - - public void testSendAndConsumeOnSingleVHost() throws Exception - { - sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST); - consumeMessages(_testSession, _testQueue, MESSAGE_COUNT_TEST); - - //Check values - checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); - checkVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); - checkSingleConnectionOnVHostStatistics("development", 0, 0, 0, 0); - checkVHostStatistics("development", 0, 0, 0, 0); - checkBrokerStatistics(MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); - } - - public void testSendAndConsumeOnTwoVHosts() throws Exception - { - sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST); - sendMessagesAndSync(_developmentSession, _developmentQueue, MESSAGE_COUNT_DEV); - consumeMessages(_testSession, _testQueue, MESSAGE_COUNT_TEST); - consumeMessages(_developmentSession, _developmentQueue, MESSAGE_COUNT_DEV); - - //Check values - checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); - checkVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); - checkSingleConnectionOnVHostStatistics("development", MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE); - checkVHostStatistics("development", MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE); - checkBrokerStatistics(MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE); - } - - private void sendMessagesAndSync(Session session, Queue queue, int numberOfMessages) throws Exception - { - //Send messages via connection on and sync - sendMessage(session, queue, numberOfMessages); - ((AMQSession)session).sync(); - } - - private void consumeMessages(Session session, Queue queue, int numberOfMessages) throws Exception - { - //consume the messages on the virtual host - final MessageConsumer consumer = session.createConsumer(queue); - for (int i = 0 ; i < numberOfMessages ; i++) - { - assertNotNull("an expected message was not received", consumer.receive(1500)); - } - session.commit(); - consumer.close(); - } - - private void checkSingleConnectionOnVHostStatistics(String vHostName, long messagesSent, long messagesReceived, long dataSent, long dataReceived) - { - List managedConnections = _jmxUtils.getManagedConnections(vHostName); - assertEquals(1, managedConnections.size()); - - ManagedConnection managedConnection = managedConnections.get(0); - - assertEquals(messagesSent, managedConnection.getTotalMessagesReceived()); - assertEquals(messagesReceived, managedConnection.getTotalMessagesDelivered()); - - assertEquals(dataSent, managedConnection.getTotalDataReceived()); - assertEquals(dataReceived, managedConnection.getTotalDataDelivered()); - } - - private void checkVHostStatistics(String vHostName, long messagesSent, long messagesReceived, long dataSent, long dataReceived) - { - ManagedBroker vhost = _jmxUtils.getManagedBroker(vHostName); - - assertEquals(messagesSent, vhost.getTotalMessagesReceived()); - assertEquals(messagesReceived, vhost.getTotalMessagesDelivered()); - - assertEquals(dataSent, vhost.getTotalDataReceived()); - assertEquals(dataReceived, vhost.getTotalDataDelivered()); - } - - private void checkBrokerStatistics(long messagesSent, long messagesReceived, long dataSent, long dataReceived) - { - ServerInformation broker = _jmxUtils.getServerInformation(); - - assertEquals(messagesSent, broker.getTotalMessagesReceived()); - assertEquals(messagesReceived, broker.getTotalMessagesDelivered()); - - assertEquals(dataSent, broker.getTotalDataReceived()); - assertEquals(dataReceived, broker.getTotalDataDelivered()); - } -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java deleted file mode 100644 index 62b1b554a9..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpid.systest.management.jmx; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; - -import javax.jms.Connection; -import javax.jms.JMSException; - -import org.apache.qpid.management.common.mbeans.UserManagement; -import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase; -import org.apache.qpid.server.security.auth.database.PrincipalDatabase; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.tools.security.Passwd; - -/** - * System test for User Management. - * - */ -public class UserManagementTest extends QpidBrokerTestCase -{ - private static final String TEST_NEWPASSWORD = "newpassword"; - private static final String TEST_PASSWORD = "password"; - private JMXTestUtils _jmxUtils; - private String _testUserName; - private File _passwordFile; - private UserManagement _userManagement; - private Passwd _passwd; - - public void setUp() throws Exception - { - _passwd = createPasswordEncodingUtility(); - _passwordFile = createTemporaryPasswordFileWithJmxAdminUser(); - - setConfigurationProperty("security.pd-auth-manager.principal-database.class", getPrincipalDatabaseImplClass().getName()); - setConfigurationProperty("security.pd-auth-manager.principal-database.attributes.attribute.name", "passwordFile"); - setConfigurationProperty("security.pd-auth-manager.principal-database.attributes.attribute.value", _passwordFile.getAbsolutePath()); - - _jmxUtils = new JMXTestUtils(this); - _jmxUtils.setUp(); - - super.setUp(); - _jmxUtils.open(); - - _testUserName = getTestName() + System.currentTimeMillis(); - - _userManagement = _jmxUtils.getUserManagement(); - } - - - public void tearDown() throws Exception - { - try - { - if (_jmxUtils != null) - { - _jmxUtils.close(); - } - } - finally - { - super.tearDown(); - } - } - - public void testCreateUser() throws Exception - { - final int initialNumberOfUsers = _userManagement.viewUsers().size(); - assertFileDoesNotContainsPasswordForUser(_testUserName); - - boolean success = _userManagement.createUser(_testUserName, TEST_PASSWORD); - assertTrue("Should have been able to create new user " + _testUserName, success); - assertEquals("Unexpected number of users after add", initialNumberOfUsers + 1, _userManagement.viewUsers().size()); - - assertFileContainsPasswordForUser(_testUserName); - } - - public void testJmsLoginForNewUser() throws Exception - { - assertJmsConnectionFails(_testUserName, TEST_PASSWORD); - testCreateUser(); - - assertJmsConnectionSucceeds(_testUserName, TEST_PASSWORD); - } - - public void testDeleteUser() throws Exception - { - final int initialNumberOfUsers = _userManagement.viewUsers().size(); - - testCreateUser(); - - boolean success = _userManagement.deleteUser(_testUserName); - assertTrue("Should have been able to delete new user " + _testUserName, success); - assertEquals("Unexpected number of users after delete", initialNumberOfUsers, _userManagement.viewUsers().size()); - assertFileDoesNotContainsPasswordForUser(_testUserName); - } - - public void testJmsLoginNotPossibleForDeletedUser() throws Exception - { - testDeleteUser(); - - assertJmsConnectionFails(_testUserName, TEST_PASSWORD); - } - - public void testSetPassword() throws Exception - { - testCreateUser(); - - _userManagement.setPassword(_testUserName, TEST_NEWPASSWORD); - - assertFileContainsPasswordForUser(_testUserName); - } - - public void testJmsLoginForPasswordChangedUser() throws Exception - { - testSetPassword(); - - assertJmsConnectionSucceeds(_testUserName, TEST_NEWPASSWORD); - assertJmsConnectionFails(_testUserName, TEST_PASSWORD); - } - - public void testReload() throws Exception - { - writePasswordFile(_passwordFile, JMXTestUtils.DEFAULT_USERID, JMXTestUtils.DEFAULT_PASSWORD, _testUserName, TEST_PASSWORD); - - assertJmsConnectionFails(_testUserName, TEST_PASSWORD); - - _userManagement.reloadData(); - - assertJmsConnectionSucceeds(_testUserName, TEST_PASSWORD); - } - - protected Passwd createPasswordEncodingUtility() - { - return new Passwd() - { - @Override - public String getOutput(String username, String password) - { - return username + ":" + password; - } - }; - } - - protected Class getPrincipalDatabaseImplClass() - { - return PlainPasswordFilePrincipalDatabase.class; - } - - private File createTemporaryPasswordFileWithJmxAdminUser() throws Exception - { - File passwordFile = File.createTempFile("passwd", "pwd"); - passwordFile.deleteOnExit(); - writePasswordFile(passwordFile, JMXTestUtils.DEFAULT_USERID, JMXTestUtils.DEFAULT_PASSWORD); - return passwordFile; - } - - private void writePasswordFile(File passwordFile, String... userNamePasswordPairs) throws Exception - { - FileWriter writer = null; - try - { - writer = new FileWriter(passwordFile); - for (int i = 0; i < userNamePasswordPairs.length; i=i+2) - { - String username = userNamePasswordPairs[i]; - String password = userNamePasswordPairs[i+1]; - writer.append(_passwd.getOutput(username, password) + "\n"); - } - } - finally - { - writer.close(); - } - } - - - private void assertFileContainsPasswordForUser(String username) throws IOException - { - assertTrue("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username)); - } - - private void assertFileDoesNotContainsPasswordForUser(String username) throws IOException - { - assertFalse("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username)); - } - - private boolean passwordFileContainsUser(String username) throws IOException - { - BufferedReader reader = null; - try - { - reader = new BufferedReader(new FileReader(_passwordFile)); - String line = reader.readLine(); - while(line != null) - { - if (line.startsWith(username)) - { - return true; - } - line = reader.readLine(); - } - - return false; - } - finally - { - reader.close(); - } - } - - private void assertJmsConnectionSucceeds(String username, String password) throws Exception - { - Connection connection = getConnection(username, password); - assertNotNull(connection); - } - - private void assertJmsConnectionFails(String username, String password) throws Exception - { - try - { - getConnection(username, password); - fail("Exception not thrown"); - } - catch (JMSException e) - { - // PASS - } - } -} diff --git a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java b/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java deleted file mode 100644 index 84a66232ce..0000000000 --- a/java/broker-plugins/jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpid.systest.management.jmx; - -import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase; -import org.apache.qpid.server.security.auth.database.PrincipalDatabase; -import org.apache.qpid.tools.security.Passwd; - -public class UserManagementWithBase64MD5PasswordsTest extends UserManagementTest -{ - @Override - protected Passwd createPasswordEncodingUtility() - { - return new Passwd(); - } - - @Override - protected Class getPrincipalDatabaseImplClass() - { - return Base64MD5PasswordFilePrincipalDatabase.class; - } - -} diff --git a/java/broker-plugins/management-http/MANIFEST.MF b/java/broker-plugins/management-http/MANIFEST.MF new file mode 100644 index 0000000000..389ff03b2d --- /dev/null +++ b/java/broker-plugins/management-http/MANIFEST.MF @@ -0,0 +1,66 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Qpid Broker-Plugins Management HTTP +Bundle-SymbolicName: broker-plugins-management-http +Bundle-Description: HTTP management plugin for Qpid. +Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt +Bundle-DocURL: http://www.apache.org/ +Bundle-Version: 1.0.0 +Bundle-Activator: org.apache.qpid.server.management.plugin.ManagementActivator +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-ClassPath: . +Bundle-ActivationPolicy: lazy +Import-Package: org.apache.qpid, + org.apache.qpid.framing, + org.apache.qpid.protocol, + org.apache.qpid.common, + org.apache.qpid.server.security.auth, + org.apache.qpid.server.security.auth.manager, + org.apache.qpid.server.security.auth.sasl, + org.apache.qpid.server.binding, + org.apache.qpid.server.exchange, + org.apache.qpid.server.logging, + org.apache.qpid.server.message, + org.apache.qpid.server.model, + org.apache.qpid.server.model.adapter, + org.apache.qpid.server.model.impl, + org.apache.qpid.server.configuration, + org.apache.qpid.server.configuration.plugins, + org.apache.qpid.server.connection, + org.apache.qpid.server.plugins, + org.apache.qpid.server.protocol, + org.apache.qpid.server.queue, + org.apache.qpid.server.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/java/broker-plugins/management-http/build.xml b/java/broker-plugins/management-http/build.xml new file mode 100644 index 0000000000..bfcefee411 --- /dev/null +++ b/java/broker-plugins/management-http/build.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java new file mode 100644 index 0000000000..589f46749d --- /dev/null +++ b/java/broker-plugins/management-http/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 _servers = new ArrayList(); + + + public Management() + { + _broker = ApplicationRegistry.getInstance().getBroker(); + + Collection 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... 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/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java new file mode 100644 index 0000000000..2600d8a7bf --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java new file mode 100644 index 0000000000..3866da8f89 --- /dev/null +++ b/java/broker-plugins/management-http/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 getParentPaths() + { + return Arrays.asList("management"); + } + }; + + public String[] getElementsProcessed() + { + return new String[] { "" }; + } + + public Configuration getConfiguration() + { + return _finalConfig; + } + + + @Override + public void validateConfiguration() throws ConfigurationException + { + // Valid Configuration either has xml links to new files + _finalConfig = new CompositeConfiguration(getConfig()); + List subFiles = getConfig().getList("xml[@fileName]"); + for (Object subFile : subFiles) + { + _finalConfig.addConfiguration(new XMLConfiguration((String) subFile)); + } + + } + +} diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java new file mode 100644 index 0000000000..d8a8395550 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.qpid.server.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; + +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/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java new file mode 100644 index 0000000000..f8ca082d79 --- /dev/null +++ b/java/broker-plugins/management-http/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 CONTENT_TYPES; + + static + { + + Map contentTypes = new HashMap(); + 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/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java new file mode 100644 index 0000000000..a3c5ec68a2 --- /dev/null +++ b/java/broker-plugins/management-http/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 vhosts = _broker.getVirtualHosts(); + Collection exchanges = new ArrayList(); + Collection> outputObject = new ArrayList>(); + + final PrintWriter writer = response.getWriter(); + + ObjectMapper mapper = new ObjectMapper(); + String vhostName = null; + String exchangeName = null; + + if(request.getPathInfo() != null && request.getPathInfo().length()>0) + { + String path = request.getPathInfo().substring(1); + String[] parts = path.split("/"); + vhostName = parts.length == 0 ? "" : parts[0]; + if(parts.length > 1) + { + exchangeName = parts[1]; + } + } + + for(VirtualHost vhost : vhosts) + { + if(vhostName == null || vhostName.equals(vhost.getName())) + { + for(Exchange exchange : vhost.getExchanges()) + { + if(exchangeName == null || exchangeName.equals(exchange.getName())) + { + outputObject.add(convertToObject(exchange)); + if(exchangeName != null) + { + break; + } + } + } + if(vhostName != null) + { + break; + } + } + } + + mapper.writeValue(writer, outputObject); + + } + + private Map convertToObject(final Exchange exchange) + { + Map object = new LinkedHashMap(); + object.put("name",exchange.getName()); + object.put("type", exchange.getExchangeType()); + object.put("durable", exchange.isDurable()); + object.put("auto-delete", exchange.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE); + + Map arguments = new HashMap(); + for(String key : exchange.getAttributeNames()) + { + if(!key.equals(Exchange.TYPE)) + { + arguments.put(key, exchange.getAttribute(key)); + } + } + object.put("arguments", arguments); + return object; + } + + protected void doPut(final HttpServletRequest request, final HttpServletResponse response) + throws ServletException, IOException + { + + response.setContentType("application/json"); + + + String vhostName = null; + String exchangeName = null; + if(request.getPathInfo() != null && request.getPathInfo().length()>0) + { + String path = request.getPathInfo().substring(1); + String[] parts = path.split("/"); + vhostName = parts.length == 0 ? "" : parts[0]; + if(parts.length > 1) + { + exchangeName = parts[1]; + } + } + if(vhostName == null) + { + response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED); + } + else if (exchangeName == null) + { + response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED); + } + else + { + VirtualHost vhost = null; + for(VirtualHost host : _broker.getVirtualHosts()) + { + if(host.getName().equals(vhostName)) + { + vhost = host; + } + } + if(vhost == null) + { + response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED); + } + else + { + response.setStatus(HttpServletResponse.SC_NO_CONTENT); + ObjectMapper mapper = new ObjectMapper(); + Map exchangeObject = mapper.readValue(request.getInputStream(), LinkedHashMap.class); + + final boolean isDurable = exchangeObject.get("durable") instanceof Boolean + && ((Boolean)exchangeObject.get("durable")); + final boolean isAutoDelete = exchangeObject.get("auto_delete") instanceof Boolean + && ((Boolean)exchangeObject.get("auto_delete")); + + final String type = (String) exchangeObject.get("type"); + final Map attributes = new HashMap(exchangeObject); + attributes.remove("durable"); + attributes.remove("auto_delete"); + attributes.remove("type"); + + vhost.createExchange(exchangeName, State.ACTIVE, isDurable, + isAutoDelete ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT, + 0l, + type, + attributes); + } + + + + } + + + + } +} diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java new file mode 100644 index 0000000000..b2c0fcfe52 --- /dev/null +++ b/java/broker-plugins/management-http/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 vhosts = _broker.getVirtualHosts(); + + + + final PrintWriter writer = response.getWriter(); + + ObjectMapper mapper = new ObjectMapper(); + + if(request.getPathInfo() == null || request.getPathInfo().length()==0) + { + + LinkedHashMap vhostObject = new LinkedHashMap(); + List vhostList = new ArrayList(); + + for(VirtualHost vhost : vhosts) + { + vhostList.add(Collections.singletonMap("name", vhost.getName())); + } + mapper.writeValue(writer, vhostList); + } + else + { + LinkedHashMap vhostObject = new LinkedHashMap(); + String vhostName = request.getPathInfo().substring(1); + + for(VirtualHost vhost : vhosts) + { + if(vhostName.equals(vhost.getName())) + { + vhostObject.put("name", vhost.getName()); + break; + } + } + mapper.writeValue(writer, vhostObject); + } + } + + + protected void doPut(final HttpServletRequest request, final HttpServletResponse response) + throws ServletException, IOException + { + + response.setContentType("application/json"); + response.setStatus(HttpServletResponse.SC_NO_CONTENT); + + if(request.getPathInfo() != null && request.getPathInfo().length()>0) + { + String vhostName = request.getPathInfo().substring(1); + _broker.createVirtualHost(vhostName, State.ACTIVE, true, LifetimePolicy.PERMANENT, 0L, Collections.EMPTY_MAP); + } + + + } +} diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java new file mode 100644 index 0000000000..123f352ec1 --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.java new file mode 100644 index 0000000000..3d862ce321 --- /dev/null +++ b/java/broker-plugins/management-http/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 +{ + 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/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java new file mode 100644 index 0000000000..7a4b92f907 --- /dev/null +++ b/java/broker-plugins/management-http/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> logRecords = new ArrayList>(); + + 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 logRecordToObject(LogRecorder.Record record) + { + Map recordMap = new LinkedHashMap(); + 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/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.java new file mode 100644 index 0000000000..84d987813b --- /dev/null +++ b/java/broker-plugins/management-http/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 +{ + private Comparator[] _sortKeys; + + public MapComparator(final String[] sortKeys) + { + _sortKeys = parseKeys(sortKeys); + } + + private static Comparator[] parseKeys(final String[] sortKeys) + { + Comparator[] 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/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java new file mode 100644 index 0000000000..4d58a9f3b0 --- /dev/null +++ b/java/broker-plugins/management-http/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 names = new ArrayList(); + // 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/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java new file mode 100644 index 0000000000..b47dc8b28e --- /dev/null +++ b/java/broker-plugins/management-http/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> 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 names = new ArrayList(); + // 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 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 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 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> _messages = new ArrayList>(); + + 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 messageObject = convertToObject(entry, false); + messageObject.put("position", _position); + _messages.add(messageObject); + } + return _last != -1 && _position > _last; + } + + public List> getMessages() + { + return _messages; + } + } + + + private class MessageFinder implements QueueEntryVisitor + { + private final long _messageNumber; + private Map _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 getMessageObject() + { + return _messageObject; + } + } + + private Map convertToObject(QueueEntry entry, boolean includeContent) + { + Map object = new LinkedHashMap(); + 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 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 object, String name, Object property) + { + if(property != null) + { + object.put(name, property); + } + } + + private void convertMessageHeaders(Map object, ServerMessage message) + { + final AMQMessageHeader messageHeader = message.getMessageHeader(); + if(messageHeader != null) + { + Map headers = new HashMap(); + 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 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 messageIds = new ArrayList(); + 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/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java new file mode 100644 index 0000000000..dbf9f9b48d --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java @@ -0,0 +1,577 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.*; +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; + + +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 RESERVED_PARAMS = new HashSet(Arrays.asList(DEPTH_PARAM, SORT_PARAM)); + + private Class[] _hierarchy; + + private volatile boolean initializationRequired = false; + + public RestServlet() + { + super(); + initializationRequired = true; + } + + public RestServlet(Broker broker, SocketAddress socketaddress, Class... 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> classes = new ArrayList>(); + 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 clazz = (Class)itemClass; + classes.add(clazz); + } + Class[] hierachyClasses = (Class[])new Class[classes.size()]; + _hierarchy = classes.toArray(hierachyClasses); + } + else + { + _hierarchy = (Class[])new Class[0]; + } + } + + protected Collection getObjects(HttpServletRequest request) + { + List names = new ArrayList(); + 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 parents = Collections.singleton((ConfiguredObject) getBroker()); + Collection children = new ArrayList(); + + Map, String> filters = + new HashMap, 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(); + } + + if(!filters.isEmpty()) + { + Collection potentials = parents; + parents = new ArrayList(); + + for(ConfiguredObject o : potentials) + { + + boolean match = true; + + for(Map.Entry, String> entry : filters.entrySet()) + { + Collection 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 filter(Collection objects, HttpServletRequest request) + { + + + Map> filters = new HashMap>(); + + for(String param : (Collection) Collections.list(request.getParameterNames())) + { + if(!RESERVED_PARAMS.contains(param)) + { + filters.put(param, Arrays.asList(request.getParameterValues(param))); + } + } + + if(filters.isEmpty()) + { + return objects; + } + + Collection filteredObj = new ArrayList(objects); + + Iterator iter = filteredObj.iterator(); + + while(iter.hasNext()) + { + ConfiguredObject obj = iter.next(); + for(Map.Entry> entry : filters.entrySet()) + { + Object value = obj.getAttribute(entry.getKey()); + if(!entry.getValue().contains(String.valueOf(value))) + { + iter.remove(); + } + } + + } + + return filteredObj; + } + + private Collection getAncestors(Class childType, + Class ancestorType, + ConfiguredObject child) + { + Collection ancestors = new HashSet(); + Collection> parentTypes = Model.getParentTypes(childType); + + for(Class 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 convertObjectToMap(final ConfiguredObject confObject, + Class clazz, + int depth) + { + Map object = new LinkedHashMap(); + + for(String name : confObject.getAttributeNames()) + { + Object value = confObject.getAttribute(name); + if(value != null) + { + object.put(name, value); + } + } + + Statistics statistics = confObject.getStatistics(); + Map statMap = new HashMap(); + 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 childClass : Model.getChildTypes(clazz)) + { + Collection children = confObject.getChildren(childClass); + if(children != null) + { + List> childObjects = new ArrayList>(); + + 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 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> output = new ArrayList>(); + + // 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 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 providedObject = mapper.readValue(request.getInputStream(), LinkedHashMap.class); + + + List names = new ArrayList(); + 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[] 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(); + 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 parents = new ArrayList(); + Class objClass = getConfiguredClass(); + Collection> 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 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 providedObject) + { + for(Map.Entry 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 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/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java new file mode 100644 index 0000000000..0787e7ec1d --- /dev/null +++ b/java/broker-plugins/management-http/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.log4j.Logger; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; + +import 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 Logger LOGGER = Logger.getLogger(SaslServlet.class); + + 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 outputObject = new LinkedHashMap(); + 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) + { + LOGGER.error("Error processing SASL request", e); + throw e; + } + catch(RuntimeException e) + { + LOGGER.error("Error processing SASL request", e); + 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 outputObject = new LinkedHashMap(); + 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/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java new file mode 100644 index 0000000000..6295d74b42 --- /dev/null +++ b/java/broker-plugins/management-http/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 + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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 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 generateStructure(ConfiguredObject object, Class clazz) + { + Map structure = new LinkedHashMap(); + structure.put("id", object.getId()); + structure.put("name", object.getName()); + + for(Class childClass : Model.getChildTypes(clazz)) + { + Collection children = object.getChildren(childClass); + if(children != null) + { + List> childObjects = new ArrayList>(); + + for(ConfiguredObject child : children) + { + childObjects.add(generateStructure(child, childClass)); + } + + if(!childObjects.isEmpty()) + { + structure.put(pluralize(childClass),childObjects); + } + } + } + + return structure; + } + + private String pluralize(Class childClass) + { + String name = childClass.getSimpleName().toLowerCase(); + return name + (name.endsWith("s") ? "es" : "s"); + } +} diff --git a/java/broker-plugins/management-http/src/main/java/resources/addBinding.html b/java/broker-plugins/management-http/src/main/java/resources/addBinding.html new file mode 100644 index 0000000000..8dbd219c8d --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/addBinding.html @@ -0,0 +1,42 @@ + +

+
+
+ + + + + + + + + + + + + +
Exchange Name*:
Queue Name*:
Binding Key*:
+
+ + + + +
+
+
diff --git a/java/broker-plugins/management-http/src/main/java/resources/addExchange.html b/java/broker-plugins/management-http/src/main/java/resources/addExchange.html new file mode 100644 index 0000000000..cccdfbd00c --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/addExchange.html @@ -0,0 +1,53 @@ + +
+
+
+ + + + + + + + + + + + + +
Exchange Name*:
Durable?
Exchange Type: + +
+
+ + + + +
+
+
diff --git a/java/broker-plugins/management-http/src/main/java/resources/addQueue.html b/java/broker-plugins/management-http/src/main/java/resources/addQueue.html new file mode 100644 index 0000000000..8154f053cd --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/addQueue.html @@ -0,0 +1,174 @@ + +
+
+
+ + + + + + + + + + + + + +
Queue Name*:
Durable?
Queue Type: + + +    + + +    + + +    + + +
+
+ + + + + + + + +
+
+ + + + + + + + + + + + +
Capacity:
Resume Capacity:
+
+
+
+ + + + + + + + + + + + + + + + + + + + +
Maximum Message Age:
Maximum Message Size:
Maximum Number in Queue:
Gap between alerts:
+
+
+
+ + + + + + + + + +
Maximum Delivery Retries:
+
+
+ + + +
+
+
diff --git a/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/addUser.html b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/addUser.html new file mode 100644 index 0000000000..785605f694 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/addUser.html @@ -0,0 +1,42 @@ + +
+
+
+ + + + + + + + + +
User Name*:
Password*
+
+ + + + +
+
+
diff --git a/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/setPassword.html b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/setPassword.html new file mode 100644 index 0000000000..3d67463abd --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/setPassword.html @@ -0,0 +1,42 @@ + +
+
+
+ + + + + + + + + +
User Name:
Password*
+
+ + + + +
+
+
diff --git a/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html new file mode 100644 index 0000000000..baadc8c35f --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html @@ -0,0 +1,29 @@ + +
+
+
+ + + +
+ +
diff --git a/java/broker-plugins/management-http/src/main/java/resources/css/common.css b/java/broker-plugins/management-http/src/main/java/resources/css/common.css new file mode 100644 index 0000000000..78780edcd9 --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/resources/footer.html b/java/broker-plugins/management-http/src/main/java/resources/footer.html new file mode 100644 index 0000000000..fa84825e80 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/footer.html @@ -0,0 +1,28 @@ + + + \ No newline at end of file diff --git a/java/broker-plugins/management-http/src/main/java/resources/images/qpid-logo.png b/java/broker-plugins/management-http/src/main/java/resources/images/qpid-logo.png new file mode 100644 index 0000000000..95d49ea469 Binary files /dev/null and b/java/broker-plugins/management-http/src/main/java/resources/images/qpid-logo.png differ diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js new file mode 100644 index 0000000000..152504da86 --- /dev/null +++ b/java/broker-plugins/management-http/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>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: + '' + + '

' + + '' + + '

' + + '' + }); + + button = new DropDownButton({ + label: "Login", + dropDown: dialog + }); + + usernameSpan = domConstruct.create("span", { innerHTML: 'User: ', + 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/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/UpdatableStore.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/UpdatableStore.js new file mode 100644 index 0000000000..f7ede1a7f7 --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/footer.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/footer.js new file mode 100644 index 0000000000..ea13b1fc53 --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/formatter.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/formatter.js new file mode 100644 index 0000000000..2f8683ee1c --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/properties.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/properties.js new file mode 100644 index 0000000000..8d85345b74 --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/updater.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/updater.js new file mode 100644 index 0000000000..86bbaa46ba --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js new file mode 100644 index 0000000000..d7917b640e --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js new file mode 100644 index 0000000000..7613fd5d71 --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js new file mode 100644 index 0000000000..dcf6711073 --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Connection.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Connection.js new file mode 100644 index 0000000000..01f9a325c5 --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js new file mode 100644 index 0000000000..0450ef53ac --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js new file mode 100644 index 0000000000..1eb0bfdd79 --- /dev/null +++ b/java/broker-plugins/management-http/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"; + tableStr += ""+encode(val[ name ])+""; + } + field.innerHTML = tableStr; + } + tableStr += ""; + } 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 = "Download"; + } + 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/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js new file mode 100644 index 0000000000..b1d4abf8c1 --- /dev/null +++ b/java/broker-plugins/management-http/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/java/broker-plugins/management-http/src/main/java/resources/management.html b/java/broker-plugins/management-http/src/main/java/resources/management.html new file mode 100644 index 0000000000..a8345a8503 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/management.html @@ -0,0 +1,92 @@ + + + + + + Qpid Management + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/java/broker-plugins/management-http/src/main/java/resources/moveCopyMessages.html b/java/broker-plugins/management-http/src/main/java/resources/moveCopyMessages.html new file mode 100644 index 0000000000..f188c3001c --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/moveCopyMessages.html @@ -0,0 +1,36 @@ + + +
+
+
+ + + + + +
Queue:
+
+ + + + + + +
+
+
diff --git a/java/broker-plugins/management-http/src/main/java/resources/showAuthProvider.html b/java/broker-plugins/management-http/src/main/java/resources/showAuthProvider.html new file mode 100644 index 0000000000..c5d4e48a75 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/showAuthProvider.html @@ -0,0 +1,25 @@ + +
+ Name: +
+ Type: +
\ No newline at end of file diff --git a/java/broker-plugins/management-http/src/main/java/resources/showBroker.html b/java/broker-plugins/management-http/src/main/java/resources/showBroker.html new file mode 100644 index 0000000000..cb2f4a4b9a --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/showBroker.html @@ -0,0 +1,25 @@ +
+ Broker: +
+ +
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ diff --git a/java/broker-plugins/management-http/src/main/java/resources/showConnection.html b/java/broker-plugins/management-http/src/main/java/resources/showConnection.html new file mode 100644 index 0000000000..84854daf47 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/showConnection.html @@ -0,0 +1,47 @@ + +
+ Name: +
+ State: + Pre-fetched: +
+ Durable: + Inbound: + + msg/s + + +
+ Lifespan: + Outbound: + + msg/s + + +
+
+
+
+
+
+ +
diff --git a/java/broker-plugins/management-http/src/main/java/resources/showExchange.html b/java/broker-plugins/management-http/src/main/java/resources/showExchange.html new file mode 100644 index 0000000000..64f351d218 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/showExchange.html @@ -0,0 +1,46 @@ + +
+ Exchange: +
+ State: +
+ Durable: + Inbound: + + msg/s + + +
+ Lifespan: + Dropped: + + msg/s + + +
+
+
+
+ +
+
+
diff --git a/java/broker-plugins/management-http/src/main/java/resources/showMessage.html b/java/broker-plugins/management-http/src/main/java/resources/showMessage.html new file mode 100644 index 0000000000..0dea508c60 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/showMessage.html @@ -0,0 +1,73 @@ + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Message Number:
Message Id:
State:
Persistent:
Priority:
Arrival Time: +
Expiration:
MIME Type:
User:
Headers:
Content:
+
+ + +
+
+ diff --git a/java/broker-plugins/management-http/src/main/java/resources/showQueue.html b/java/broker-plugins/management-http/src/main/java/resources/showQueue.html new file mode 100644 index 0000000000..c87a462760 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/showQueue.html @@ -0,0 +1,97 @@ + +
+ Queue: + Size: + + msgs + ( + ) +
+ State: + Pre-fetched: + + msgs + + +
+ Durable: + Inbound: + + msg/s + + +
+ Lifespan: + Outbound: + + msg/s + + +
+
+
+
+ +
+
+
+
+
+
+
+
+ + + +
+
+
+ Max. Queue Size: + + msgs + + + +
+ Max. Message Age: + + + + Size: + + +
+
+ Alert frequency: + + + + + +
+
+ diff --git a/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html b/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html new file mode 100644 index 0000000000..9d16d523d6 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html @@ -0,0 +1,84 @@ + + + +
+ Name: +
+ State: +
+ Durable: + Inbound: + + msg/s + + +
+ Lifespan: + Outbound: + + msg/s + + +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+ Max. Queue Size: + + msgs + + + +
+ Max. Message Age: + + + + Size: + + +
+
+ Alert frequency: + + +
+
+ diff --git a/java/broker-plugins/management-jmx/MANIFEST.MF b/java/broker-plugins/management-jmx/MANIFEST.MF new file mode 100644 index 0000000000..b18ec1ace7 --- /dev/null +++ b/java/broker-plugins/management-jmx/MANIFEST.MF @@ -0,0 +1,66 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Qpid Broker-Plugins Management JMX +Bundle-SymbolicName: broker-plugins-management-jmx +Bundle-Description: JMX management plugin for Qpid. +Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt +Bundle-DocURL: http://www.apache.org/ +Bundle-Version: 1.0.0 +Bundle-Activator: org.apache.qpid.server.jmx.JMXActivator +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-ClassPath: . +Bundle-ActivationPolicy: lazy +Import-Package: org.apache.qpid, + org.apache.qpid.framing, + org.apache.qpid.protocol, + org.apache.qpid.common, + org.apache.qpid.management.common.mbeans, + org.apache.qpid.management.common.mbeans.annotations, + org.apache.qpid.server.security.auth, + org.apache.qpid.server.security.auth.manager, + org.apache.qpid.server.security.auth.rmi, + org.apache.qpid.server.security.auth.sasl, + org.apache.qpid.server.binding, + org.apache.qpid.server.exchange, + org.apache.qpid.server.logging, + org.apache.qpid.server.logging.log4j, + org.apache.qpid.server.logging.actors, + org.apache.qpid.server.logging.messages, + org.apache.qpid.server.message, + org.apache.qpid.server.model, + org.apache.qpid.server.model.adapter, + org.apache.qpid.server.model.impl, + org.apache.qpid.server.configuration, + org.apache.qpid.server.configuration.plugins, + org.apache.qpid.server.connection, + org.apache.qpid.server.plugins, + org.apache.qpid.server.protocol, + org.apache.qpid.server.queue, + org.apache.qpid.server.registry, + org.apache.qpid.server.security, + org.apache.qpid.server.security.access, + org.apache.qpid.server.stats, + org.apache.qpid.server.virtualhost, + org.apache.qpid.util, + org.apache.commons.codec;version=1.3.0, + org.apache.commons.codec.binary;version=1.3.0, + org.apache.commons.configuration;version=1.0.0, + org.apache.commons.lang;version=1.0.0, + org.apache.commons.lang.builder;version=1.0.0, + org.apache.commons.lang.time;version=1.0.0, + org.apache.log4j;version=1.2.16, + org.codehaus.jackson;version=1.9.0, + org.codehaus.jackson.map;version=1.9.0, + javax.management.remote.rmi, + javax.management.remote, + javax.servlet, + javax.servlet.http, + javax.management;version=1.0.0, + javax.management.monitor;version=1.0.0, + javax.management.openmbean;version=1.0.0, + javax.security.auth.login;version=1.0.0, + javax.security.auth;version=1.0.0, + javax.rmi.ssl;version=1.0.0, + org.osgi.util.tracker;version=1.0.0, + org.osgi.framework;version=1.3 +Export-Package: org.apache.qpid.server.jmx;uses:="org.osgi.framework" diff --git a/java/broker-plugins/management-jmx/build.xml b/java/broker-plugins/management-jmx/build.xml new file mode 100644 index 0000000000..fa50b8467d --- /dev/null +++ b/java/broker-plugins/management-jmx/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java new file mode 100644 index 0000000000..5c39a0c26a --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/AMQManagedObject.java @@ -0,0 +1,84 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.jmx; + +import java.util.concurrent.atomic.AtomicLong; + +import javax.management.ListenerNotFoundException; +import javax.management.NotCompliantMBeanException; +import javax.management.NotificationBroadcaster; +import javax.management.NotificationBroadcasterSupport; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; + +/** + * This class provides additional feature of Notification Broadcaster to the + * DefaultManagedObject. + * @author Bhupendra Bhardwaj + * @version 0.1 + */ +public abstract class AMQManagedObject extends DefaultManagedObject + implements NotificationBroadcaster +{ + private final NotificationBroadcasterSupport _broadcaster = new NotificationBroadcasterSupport(); + + private AtomicLong _notificationSequenceNumber = new AtomicLong(); + + protected AMQManagedObject(Class managementInterface, String typeName, ManagedObjectRegistry registry) + throws NotCompliantMBeanException + { + super(managementInterface, typeName, registry); + // CurrentActor will be defined as these objects are created during + // broker startup. + + } + + // notification broadcaster implementation + + public void addNotificationListener(NotificationListener listener, + NotificationFilter filter, + Object handback) + { + _broadcaster.addNotificationListener(listener, filter, handback); + } + + public void removeNotificationListener(NotificationListener listener) + throws ListenerNotFoundException + { + _broadcaster.removeNotificationListener(listener); + } + + + /** + * broadcaster support class + */ + protected NotificationBroadcasterSupport getBroadcaster() + { + return _broadcaster; + } + + protected long incrementAndGetSequenceNumber() + { + return _notificationSequenceNumber.incrementAndGet(); + } + + +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.java new file mode 100644 index 0000000000..4446f96802 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/DefaultManagedObject.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 org.apache.log4j.Logger; + +import javax.management.JMException; +import javax.management.MBeanInfo; +import javax.management.MBeanNotificationInfo; +import javax.management.MalformedObjectNameException; +import javax.management.NotCompliantMBeanException; +import javax.management.ObjectName; +import javax.management.StandardMBean; + +/** + * Provides implementation of the boilerplate ManagedObject interface. Most managed objects should find it useful + * to extend this class rather than implementing ManagedObject from scratch. + * + */ +public abstract class DefaultManagedObject extends StandardMBean implements ManagedObject +{ + private static final Logger LOGGER = Logger.getLogger(DefaultManagedObject.class); + + private final Class _managementInterface; + + private final String _typeName; + + private final MBeanInfo _mbeanInfo; + + private ManagedObjectRegistry _registry; + + 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() + { + return _mbeanInfo; + } + + public String getType() + { + return _typeName; + } + + public Class getManagementInterface() + { + return _managementInterface; + } + + public abstract ManagedObject getParentObject(); + + + public void register() throws JMException + { + _registry.registerObject(this); + } + + public void unregister() throws JMException + { + try + { + if(_registry != null) + { + _registry.unregisterObject(this); + } + } + finally + { + _registry = null; + } + } + + public String toString() + { + return getObjectInstanceName() + "[" + getType() + "]"; + } + + /** + * Created the ObjectName as per the JMX Specs + * @return ObjectName + * @throws javax.management.MalformedObjectNameException + */ + public ObjectName getObjectName() throws MalformedObjectNameException + { + String name = getObjectInstanceName(); + StringBuffer objectName = new StringBuffer(ManagedObject.DOMAIN); + + objectName.append(":type="); + objectName.append(getHierarchicalType(this)); + + objectName.append(","); + objectName.append(getHierarchicalName(this)); + objectName.append("name=").append(name); + + return new ObjectName(objectName.toString()); + } + + protected ObjectName getObjectNameForSingleInstanceMBean() throws MalformedObjectNameException + { + StringBuffer objectName = new StringBuffer(ManagedObject.DOMAIN); + + objectName.append(":type="); + objectName.append(getHierarchicalType(this)); + + String hierarchyName = getHierarchicalName(this); + if (hierarchyName != null) + { + objectName.append(","); + objectName.append(hierarchyName.substring(0, hierarchyName.lastIndexOf(","))); + } + + return new ObjectName(objectName.toString()); + } + + protected String getHierarchicalType(ManagedObject obj) + { + if (obj.getParentObject() != null) + { + String parentType = getHierarchicalType(obj.getParentObject()).toString(); + return parentType + "." + obj.getType(); + } + else + { + return obj.getType(); + } + } + + protected String getHierarchicalName(ManagedObject obj) + { + if (obj.getParentObject() != null) + { + String parentName = obj.getParentObject().getType() + "=" + + obj.getParentObject().getObjectInstanceName() + ","+ + getHierarchicalName(obj.getParentObject()); + + return parentName; + } + else + { + return ""; + } + } + + private MBeanInfo buildMBeanInfo() throws NotCompliantMBeanException + { + return new MBeanInfo(this.getClass().getName(), + MBeanIntrospector.getMBeanDescription(this.getClass()), + MBeanIntrospector.getMBeanAttributesInfo(getManagementInterface()), + MBeanIntrospector.getMBeanConstructorsInfo(this.getClass()), + MBeanIntrospector.getMBeanOperationsInfo(getManagementInterface()), + this.getNotificationInfo()); + } + + public MBeanNotificationInfo[] getNotificationInfo() + { + return null; + } +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java new file mode 100644 index 0000000000..c588b40de7 --- /dev/null +++ b/java/broker-plugins/management-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 _registeredServices; + + + public void start(final BundleContext ctx) throws Exception + { + boolean jmxManagementEnabled = ApplicationRegistry.getInstance().getConfiguration().getJMXManagementEnabled(); + + if (jmxManagementEnabled) + { + _jmxService = new JMXService(); + startJmsService(_jmxService); + + _bundleName = ctx.getBundle().getSymbolicName(); + + _registeredServices = registerServices(ctx); + } + else + { + LOGGER.debug("Skipping registration of JMX plugin as JMX Management disabled in config. "); + } + } + + public void stop(final BundleContext bundleContext) throws Exception + { + try + { + if (_jmxService != null) + { + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Stopping jmx plugin: " + _bundleName); + } + _jmxService.close(); + } + + if (_registeredServices != null) + { + unregisterServices(); + } + } + finally + { + _jmxService = null; + _registeredServices = null; + } + } + + + private List registerServices(BundleContext ctx) + { + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Registering jmx plugin: " + _bundleName); + } + + List serviceRegistrations = new ArrayList(); + + ServiceRegistration jmxServiceRegistration = ctx.registerService(JMXService.class.getName(), _jmxService, null); + ServiceRegistration jmxConfigFactoryRegistration = ctx.registerService(ConfigurationPluginFactory.class.getName(), JMXConfiguration.FACTORY, null); + + serviceRegistrations.add(jmxServiceRegistration); + serviceRegistrations.add(jmxConfigFactoryRegistration); + return serviceRegistrations; + } + + private void startJmsService(JMXService jmxService) throws Exception + { + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Starting JMX service"); + } + boolean startedSuccessfully = false; + try + { + jmxService.start(); + startedSuccessfully = true; + } + finally + { + if (!startedSuccessfully) + { + LOGGER.error("JMX failed to start normally, closing service"); + jmxService.close(); + } + } + } + + private void unregisterServices() + { + for (Iterator iterator = _registeredServices.iterator(); iterator.hasNext();) + { + ServiceRegistration service = iterator.next(); + service.unregister(); + } + } +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java new file mode 100644 index 0000000000..dc9a712f90 --- /dev/null +++ b/java/broker-plugins/management-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 getParentPaths() + { + return Arrays.asList("jmx"); + } + }; + + public String[] getElementsProcessed() + { + return new String[] { "" }; + } + + public Configuration getConfiguration() + { + return _finalConfig; + } + + + @Override + public void validateConfiguration() throws ConfigurationException + { + // Valid Configuration either has xml links to new files + _finalConfig = new CompositeConfiguration(getConfig()); + List subFiles = getConfig().getList("xml[@fileName]"); + for (Object subFile : subFiles) + { + _finalConfig.addConfiguration(new XMLConfiguration((String) subFile)); + } + + } + +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java new file mode 100644 index 0000000000..0648235077 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java @@ -0,0 +1,499 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.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; +import java.lang.management.ManagementFactory; +import java.lang.reflect.Proxy; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.UnknownHostException; +import java.rmi.AlreadyBoundException; +import java.rmi.NoSuchObjectException; +import java.rmi.NotBoundException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.RMIClientSocketFactory; +import java.rmi.server.RMIServerSocketFactory; +import java.rmi.server.UnicastRemoteObject; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * This class starts up an MBeanserver. If out of the box agent has been enabled then there are no + * security features implemented like user authentication and authorisation. + */ +public class JMXManagedObjectRegistry implements ManagedObjectRegistry +{ + private static final Logger _log = Logger.getLogger(JMXManagedObjectRegistry.class); + + private final MBeanServer _mbeanServer; + private JMXConnectorServer _cs; + private Registry _rmiRegistry; + private boolean _useCustomSocketFactory; + + private final int _jmxPortRegistryServer; + private final int _jmxPortConnectorServer; + + public JMXManagedObjectRegistry() throws AMQException + { + _log.info("Initialising managed object registry using platform MBean server"); + IApplicationRegistry appRegistry = ApplicationRegistry.getInstance(); + + // Retrieve the config parameters + _useCustomSocketFactory = appRegistry.getConfiguration().getUseCustomRMISocketFactory(); + boolean platformServer = appRegistry.getConfiguration().getPlatformMbeanserver(); + + _mbeanServer = + platformServer ? ManagementFactory.getPlatformMBeanServer() + : MBeanServerFactory.createMBeanServer(ManagedObject.DOMAIN); + + _jmxPortRegistryServer = appRegistry.getConfiguration().getJMXPortRegistryServer(); + _jmxPortConnectorServer = appRegistry.getConfiguration().getJMXConnectorServerPort(); + + } + + public void start() throws IOException, ConfigurationException + { + + CurrentActor.get().message(ManagementConsoleMessages.STARTUP()); + + //check if system properties are set to use the JVM's out-of-the-box JMXAgent + if (areOutOfTheBoxJMXOptionsSet()) + { + CurrentActor.get().message(ManagementConsoleMessages.READY(true)); + return; + } + + IApplicationRegistry appRegistry = ApplicationRegistry.getInstance(); + + + //Socket factories for the RMIConnectorServer, either default or SLL depending on configuration + RMIClientSocketFactory csf; + RMIServerSocketFactory ssf; + + //check ssl enabled option in config, default to true if option is not set + boolean sslEnabled = appRegistry.getConfiguration().getManagementSSLEnabled(); + + if (sslEnabled) + { + //set the SSL related system properties used by the SSL RMI socket factories to the values + //given in the configuration file, unless command line settings have already been specified + String keyStorePath; + + if(System.getProperty("javax.net.ssl.keyStore") != null) + { + keyStorePath = System.getProperty("javax.net.ssl.keyStore"); + } + else + { + keyStorePath = appRegistry.getConfiguration().getManagementKeyStorePath(); + } + + //check the keystore path value is valid + if (keyStorePath == null) + { + throw new ConfigurationException("JMX management SSL keystore path not defined, " + + "unable to start SSL protected JMX ConnectorServer"); + } + else + { + //ensure the system property is set + System.setProperty("javax.net.ssl.keyStore", keyStorePath); + + //check the file is usable + File ksf = new File(keyStorePath); + + if (!ksf.exists()) + { + throw new FileNotFoundException("Cannot find JMX management SSL keystore file: " + ksf); + } + if (!ksf.canRead()) + { + throw new FileNotFoundException("Cannot read JMX management SSL keystore file: " + + ksf + ". Check permissions."); + } + + CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(ksf.getAbsolutePath())); + } + + //check the key store password is set + if (System.getProperty("javax.net.ssl.keyStorePassword") == null) + { + + if (appRegistry.getConfiguration().getManagementKeyStorePassword() == null) + { + throw new ConfigurationException("JMX management SSL keystore password not defined, " + + "unable to start requested SSL protected JMX server"); + } + else + { + System.setProperty("javax.net.ssl.keyStorePassword", + appRegistry.getConfiguration().getManagementKeyStorePassword()); + } + } + + //create the SSL RMI socket factories + csf = new SslRMIClientSocketFactory(); + ssf = new SslRMIServerSocketFactory(); + } + else + { + //Do not specify any specific RMI socket factories, resulting in use of the defaults. + csf = null; + ssf = null; + } + + //add a JMXAuthenticator implementation the env map to authenticate the RMI based JMX connector server + RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator(new InetSocketAddress(_jmxPortRegistryServer)); + HashMap env = new HashMap(); + env.put(JMXConnectorServer.AUTHENTICATOR, rmipa); + + /* + * Start a RMI registry on the management port, to hold the JMX RMI ConnectorServer stub. + * Using custom socket factory to prevent anyone (including us unfortunately) binding to the registry using RMI. + * As a result, only binds made using the object reference will succeed, thus securing it from external change. + */ + System.setProperty("java.rmi.server.randomIDs", "true"); + if(_useCustomSocketFactory) + { + _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, new CustomRMIServerSocketFactory()); + } + else + { + _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, null); + } + + CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", _jmxPortRegistryServer)); + + /* + * We must now create the RMI ConnectorServer manually, as the JMX Factory methods use RMI calls + * to bind the ConnectorServer to the registry, which will now fail as for security we have + * locked it from any RMI based modifications, including our own. Instead, we will manually bind + * the RMIConnectorServer stub to the registry using its object reference, which will still succeed. + * + * The registry is exported on the defined management port 'port'. We will export the RMIConnectorServer + * on 'port +1'. Use of these two well-defined ports will ease any navigation through firewall's. + */ + final Map connectionIdUsernameMap = new ConcurrentHashMap(); + final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(_jmxPortConnectorServer, csf, ssf, env) + { + + /** + * Override makeClient so we can cache the username of the client in a Map keyed by connectionId. + * ConnectionId is guaranteed to be unique per client connection, according to the JMS spec. + * An instance of NotificationListener (mapCleanupListener) will be responsible for removing these Map + * entries. + * + * @see javax.management.remote.rmi.RMIJRMPServerImpl#makeClient(String, javax.security.auth.Subject) + */ + @Override + protected RMIConnection makeClient(String connectionId, Subject subject) throws IOException + { + final RMIConnection makeClient = super.makeClient(connectionId, subject); + final UsernamePrincipal usernamePrincipalFromSubject = UsernamePrincipal.getUsernamePrincipalFromSubject(subject); + connectionIdUsernameMap.put(connectionId, usernamePrincipalFromSubject.getName()); + return makeClient; + } + }; + + // Create a Listener responsible for removing the map entries add by the #makeClient entry above. + final NotificationListener mapCleanupListener = new NotificationListener() + { + + public void handleNotification(Notification notification, Object handback) + { + final String connectionId = ((JMXConnectionNotification) notification).getConnectionId(); + connectionIdUsernameMap.remove(connectionId); + } + }; + + String localHost; + try + { + localHost = InetAddress.getLocalHost().getHostName(); + } + catch(UnknownHostException ex) + { + localHost="127.0.0.1"; + } + final String hostname = localHost; + final JMXServiceURL externalUrl = new JMXServiceURL( + "service:jmx:rmi://"+hostname+":"+(_jmxPortConnectorServer)+"/jndi/rmi://"+hostname+":"+_jmxPortRegistryServer+"/jmxrmi"); + + final JMXServiceURL internalUrl = new JMXServiceURL("rmi", hostname, _jmxPortConnectorServer); + _cs = new RMIConnectorServer(internalUrl, env, rmiConnectorServerStub, _mbeanServer) + { + @Override + public synchronized void start() throws IOException + { + try + { + //manually bind the connector server to the registry at key 'jmxrmi', like the out-of-the-box agent + _rmiRegistry.bind("jmxrmi", rmiConnectorServerStub); + } + catch (AlreadyBoundException abe) + { + //key was already in use. shouldnt happen here as its a new registry, unbindable by normal means. + + //IOExceptions are the only checked type throwable by the method, wrap and rethrow + IOException ioe = new IOException(abe.getMessage()); + ioe.initCause(abe); + throw ioe; + } + + //now do the normal tasks + super.start(); + } + + @Override + public synchronized void stop() throws IOException + { + try + { + if (_rmiRegistry != null) + { + _rmiRegistry.unbind("jmxrmi"); + } + } + catch (NotBoundException nbe) + { + // TODO consider if we want to keep new logging + _log.error("Failed to unbind jmxrmi", nbe); + //ignore + } + + //now do the normal tasks + super.stop(); + } + + @Override + public JMXServiceURL getAddress() + { + //must return our pre-crafted url that includes the full details, inc JNDI details + return externalUrl; + } + + }; + + + //Add the custom invoker as an MBeanServerForwarder, and start the RMIConnectorServer. + MBeanServerForwarder mbsf = MBeanInvocationHandlerImpl.newProxyInstance(); + _cs.setMBeanServerForwarder(mbsf); + + + // Get the handler that is used by the above MBInvocationHandler Proxy. + // which is the MBeanInvocationHandlerImpl and so also a NotificationListener. + final NotificationListener invocationHandler = (NotificationListener) Proxy.getInvocationHandler(mbsf); + + // Install a notification listener on OPENED, CLOSED, and FAILED, + // passing the map of connection-ids to usernames as hand-back data. + final NotificationFilterSupport invocationHandlerFilter = new NotificationFilterSupport(); + invocationHandlerFilter.enableType(JMXConnectionNotification.OPENED); + invocationHandlerFilter.enableType(JMXConnectionNotification.CLOSED); + invocationHandlerFilter.enableType(JMXConnectionNotification.FAILED); + _cs.addNotificationListener(invocationHandler, invocationHandlerFilter, connectionIdUsernameMap); + + // Install a second notification listener on CLOSED AND FAILED only to remove the entry from the + // Map. Here we rely on the fact that JMX will call the listeners in the order in which they are + // installed. + final NotificationFilterSupport mapCleanupHandlerFilter = new NotificationFilterSupport(); + mapCleanupHandlerFilter.enableType(JMXConnectionNotification.CLOSED); + mapCleanupHandlerFilter.enableType(JMXConnectionNotification.FAILED); + _cs.addNotificationListener(mapCleanupListener, mapCleanupHandlerFilter, null); + + _cs.start(); + + String connectorServer = (sslEnabled ? "SSL " : "") + "JMX RMIConnectorServer"; + CurrentActor.get().message(ManagementConsoleMessages.LISTENING(connectorServer, _jmxPortConnectorServer)); + + CurrentActor.get().message(ManagementConsoleMessages.READY(false)); + } + + /* + * Custom RMIServerSocketFactory class, used to prevent updates to the RMI registry. + * Supplied to the registry at creation, this will prevent RMI-based operations on the + * registry such as attempting to bind a new object, thereby securing it from tampering. + * This is accomplished by always returning null when attempting to determine the address + * of the caller, thus ensuring the registry will refuse the attempt. Calls to bind etc + * made using the object reference will not be affected and continue to operate normally. + */ + + private static class CustomRMIServerSocketFactory implements RMIServerSocketFactory + { + + public ServerSocket createServerSocket(int port) throws IOException + { + return new NoLocalAddressServerSocket(port); + } + + private static class NoLocalAddressServerSocket extends ServerSocket + { + NoLocalAddressServerSocket(int port) throws IOException + { + super(port); + } + + @Override + public Socket accept() throws IOException + { + Socket s = new NoLocalAddressSocket(); + super.implAccept(s); + return s; + } + } + + private static class NoLocalAddressSocket extends Socket + { + @Override + public InetAddress getInetAddress() + { + return null; + } + } + } + + + public void registerObject(ManagedObject managedObject) throws JMException + { + _mbeanServer.registerMBean(managedObject, managedObject.getObjectName()); + } + + public void unregisterObject(ManagedObject managedObject) throws JMException + { + _mbeanServer.unregisterMBean(managedObject.getObjectName()); + } + + // checks if the system properties are set which enable the JVM's out-of-the-box JMXAgent. + private boolean areOutOfTheBoxJMXOptionsSet() + { + if (System.getProperty("com.sun.management.jmxremote") != null) + { + return true; + } + + if (System.getProperty("com.sun.management.jmxremote.port") != null) + { + return true; + } + + return false; + } + + //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 + try + { + CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("JMX RMIConnectorServer", _cs.getAddress().getPort())); + _cs.stop(); + } + catch (IOException e) + { + _log.error("Exception while closing the JMX ConnectorServer: ", e); + } + } + + if (_rmiRegistry != null) + { + // Stopping the RMI registry + CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _jmxPortRegistryServer)); + try + { + 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); + } + } + + //ObjectName query to gather all Qpid related MBeans + ObjectName mbeanNameQuery = null; + try + { + mbeanNameQuery = new ObjectName(ManagedObject.DOMAIN + ":*"); + } + catch (Exception e1) + { + _log.warn("Unable to generate MBean ObjectName query for close operation"); + } + + for (ObjectName name : _mbeanServer.queryNames(mbeanNameQuery, null)) + { + try + { + _mbeanServer.unregisterMBean(name); + } + catch (JMException e) + { + _log.error("Exception unregistering MBean '"+ name +"': " + e.getMessage()); + } + } + + CurrentActor.get().message(ManagementConsoleMessages.STOPPED()); + } + +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java new file mode 100644 index 0000000000..7a232d2584 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java @@ -0,0 +1,193 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.jmx; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.ServiceLoader; + +import javax.management.JMException; +import javax.management.StandardMBean; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.log4j.Logger; +import org.apache.qpid.AMQException; +import org.apache.qpid.server.jmx.mbeans.LoggingManagementMBean; +import org.apache.qpid.server.jmx.mbeans.UserManagementMBean; +import org.apache.qpid.server.jmx.mbeans.ConfigurationManagementMBean; +import org.apache.qpid.server.jmx.mbeans.ServerInformationMBean; +import org.apache.qpid.server.jmx.mbeans.Shutdown; +import org.apache.qpid.server.jmx.mbeans.VirtualHostMBean; +import org.apache.qpid.server.logging.log4j.LoggingFacade; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfigurationChangeListener; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.registry.ApplicationRegistry; + + +public class JMXService implements ConfigurationChangeListener +{ + private static final ClassLoader BUNDLE_CLASSLOADER = JMXService.class.getClassLoader(); + + private static final Logger LOGGER = Logger.getLogger(JMXService.class); + + private final Broker _broker; + private final JMXManagedObjectRegistry _objectRegistry; + private final Shutdown _shutdown; + private final ServerInformationMBean _serverInfo; + private final ConfigurationManagementMBean _configManagement; + private final LoggingManagementMBean _loggingManagement; + + private final Map _children = new HashMap(); + + public JMXService() throws AMQException, JMException + { + _broker = ApplicationRegistry.getInstance().getBroker(); + _objectRegistry = new JMXManagedObjectRegistry(); + + _broker.addChangeListener(this); + synchronized (_children) + { + for(VirtualHost virtualHost : _broker.getVirtualHosts()) + { + if(!_children.containsKey(virtualHost)) + { + _children.put(virtualHost, new VirtualHostMBean(virtualHost, _objectRegistry)); + } + } + } + _shutdown = new Shutdown(_objectRegistry); + _serverInfo = new ServerInformationMBean(_objectRegistry, _broker); + _configManagement = new ConfigurationManagementMBean(_objectRegistry); + _loggingManagement = new LoggingManagementMBean(LoggingFacade.getCurrentInstance(), _objectRegistry); + } + + public void start() throws IOException, ConfigurationException + { + _objectRegistry.start(); + } + + public void close() + { + _broker.removeChangeListener(this); + + _objectRegistry.close(); + } + + public void stateChanged(ConfiguredObject object, State oldState, State newState) + { + + } + + public void childAdded(ConfiguredObject object, ConfiguredObject child) + { + synchronized (_children) + { + try + { + AMQManagedObject mbean; + if(child instanceof VirtualHost) + { + VirtualHost vhostChild = (VirtualHost)child; + mbean = new VirtualHostMBean(vhostChild, _objectRegistry); + } + else if(child instanceof PasswordCredentialManagingAuthenticationProvider) + { + mbean = new UserManagementMBean((PasswordCredentialManagingAuthenticationProvider) child, _objectRegistry); + } + else + { + mbean = null; + } + + if (mbean != null) + { + createAdditionalMBeansFromProviders(child, mbean); + } + } + catch(JMException e) + { + LOGGER.error("Error creating mbean", e); + // TODO - Implement error reporting on mbean creation + } + } + } + + + public void childRemoved(ConfiguredObject object, ConfiguredObject child) + { + // TODO - implement vhost removal (possibly just removing the instanceof check below) + + synchronized (_children) + { + if(child instanceof PasswordCredentialManagingAuthenticationProvider) + { + AMQManagedObject mbean = _children.remove(child); + if(mbean != null) + { + try + { + mbean.unregister(); + } + catch(JMException e) + { + LOGGER.error("Error creating mbean", e); + //TODO - report error on removing child MBean + } + } + } + + } + } + + private void createAdditionalMBeansFromProviders(ConfiguredObject child, AMQManagedObject mbean) throws JMException + { + _children.put(child, mbean); + + for (Iterator iterator = getMBeanProviderIterator(); iterator.hasNext();) + { + MBeanProvider provider = iterator.next(); + LOGGER.debug("Consulting mbean provider : " + provider + " for child : " + child); + if (provider.isChildManageableByMBean(child)) + { + LOGGER.debug("Provider will create mbean "); + StandardMBean bean = provider.createMBean(child, mbean); + // TODO track the mbeans that have been created on behalf of a child in a map, then + // if the child is ever removed, destroy these beans too. + } + } + } + + /** + * Finds all classes implementing the {@link MBeanProvider} interface. This will find + * only those classes which are visible to the classloader of this OSGI bundle. + */ + private Iterator getMBeanProviderIterator() + { + return ServiceLoader.load(MBeanProvider.class, BUNDLE_CLASSLOADER).iterator(); + } +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java new file mode 100644 index 0000000000..79ddc8cfc0 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanIntrospector.java @@ -0,0 +1,400 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.jmx; + +import org.apache.qpid.management.common.mbeans.annotations.MBeanAttribute; +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.MBeanOperation; +import org.apache.qpid.management.common.mbeans.annotations.MBeanOperationParameter; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanConstructorInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; +import javax.management.NotCompliantMBeanException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +/** + * This class is a utility class to introspect the MBean class and the management + * interface class for various purposes. + * @author Bhupendra Bhardwaj + * @version 0.1 + */ +class MBeanIntrospector +{ + + private static final String _defaultAttributeDescription = "Management attribute"; + private static final String _defaultOerationDescription = "Management operation"; + private static final String _defaultConstructorDescription = "MBean constructor"; + private static final String _defaultMbeanDescription = "Management interface of the MBean"; + + private MBeanIntrospector() + { + } + + /** + * Introspects the management interface class for MBean attributes. + * @param interfaceClass + * @return MBeanAttributeInfo[] + * @throws javax.management.NotCompliantMBeanException + */ + static MBeanAttributeInfo[] getMBeanAttributesInfo(Class interfaceClass) + throws NotCompliantMBeanException + { + List attributesList = new ArrayList(); + + /** + * Using reflection, all methods of the managemetn interface will be analysed, + * and MBeanInfo will be created. + */ + for (Method method : interfaceClass.getMethods()) + { + String name = method.getName(); + Class resultType = method.getReturnType(); + MBeanAttributeInfo attributeInfo = null; + + if (isAttributeGetterMethod(method)) + { + String desc = getAttributeDescription(method); + attributeInfo = new MBeanAttributeInfo(name.substring(3), + resultType.getName(), + desc, + true, + false, + false); + int index = getIndexIfAlreadyExists(attributeInfo, attributesList); + if (index == -1) + { + attributesList.add(attributeInfo); + } + else + { + attributeInfo = new MBeanAttributeInfo(name.substring(3), + resultType.getName(), + desc, + true, + true, + false); + attributesList.set(index, attributeInfo); + } + } + else if (isAttributeSetterMethod(method)) + { + String desc = getAttributeDescription(method); + attributeInfo = new MBeanAttributeInfo(name.substring(3), + method.getParameterTypes()[0].getName(), + desc, + false, + true, + false); + int index = getIndexIfAlreadyExists(attributeInfo, attributesList); + if (index == -1) + { + attributesList.add(attributeInfo); + } + else + { + attributeInfo = new MBeanAttributeInfo(name.substring(3), + method.getParameterTypes()[0].getName(), + desc, + true, + true, + false); + attributesList.set(index, attributeInfo); + } + } + else if (isAttributeBoolean(method)) + { + attributeInfo = new MBeanAttributeInfo(name.substring(2), + resultType.getName(), + getAttributeDescription(method), + true, + false, + true); + attributesList.add(attributeInfo); + } + } + + return attributesList.toArray(new MBeanAttributeInfo[0]); + } + + /** + * Introspects the management interface class for management operations. + * @param interfaceClass + * @return MBeanOperationInfo[] + */ + static MBeanOperationInfo[] getMBeanOperationsInfo(Class interfaceClass) + { + List operationsList = new ArrayList(); + + for (Method method : interfaceClass.getMethods()) + { + if (!isAttributeGetterMethod(method) && + !isAttributeSetterMethod(method) && + !isAttributeBoolean(method)) + { + operationsList.add(getOperationInfo(method)); + } + } + + return operationsList.toArray(new MBeanOperationInfo[0]); + } + + /** + * Checks if the method is an attribute getter method. + * @param method + * @return true if the method is an attribute getter method. + */ + private static boolean isAttributeGetterMethod(Method method) + { + if (!(method.getName().equals("get")) && + method.getName().startsWith("get") && + method.getParameterTypes().length == 0 && + !method.getReturnType().equals(void.class)) + { + return true; + } + + return false; + } + + /** + * Checks if the method is an attribute setter method. + * @param method + * @return true if the method is an attribute setter method. + */ + private static boolean isAttributeSetterMethod(Method method) + { + if (!(method.getName().equals("set")) && + method.getName().startsWith("set") && + method.getParameterTypes().length == 1 && + method.getReturnType().equals(void.class)) + { + return true; + } + + return false; + } + + /** + * Checks if the attribute is a boolean and the method is a isX kind og method. + * @param method + * @return true if the method is an attribute isX type of method + */ + private static boolean isAttributeBoolean(Method method) + { + if (!(method.getName().equals("is")) && + method.getName().startsWith("is") && + method.getParameterTypes().length == 0 && + method.getReturnType().equals(boolean.class)) + { + return true; + } + + return false; + } + + /** + * Helper method to retrieve the attribute index from the list of attributes. + * @param attribute + * @param list + * @return attribute index no. -1 if attribtue doesn't exist + * @throws javax.management.NotCompliantMBeanException + */ + private static int getIndexIfAlreadyExists(MBeanAttributeInfo attribute, + List list) + throws NotCompliantMBeanException + { + String exceptionMsg = "Conflicting attribute methods for attribute " + attribute.getName(); + + for (MBeanAttributeInfo memberAttribute : list) + { + if (attribute.getName().equals(memberAttribute.getName())) + { + if (!attribute.getType().equals(memberAttribute.getType())) + { + throw new NotCompliantMBeanException(exceptionMsg); + } + if (attribute.isReadable() && memberAttribute.isReadable()) + { + if (attribute.isIs() != memberAttribute.isIs()) + { + throw new NotCompliantMBeanException(exceptionMsg); + } + } + + return list.indexOf(memberAttribute); + } + } + + return -1; + } + + /** + * Retrieves the attribute description from annotation + * @param attributeMethod + * @return attribute description + */ + private static String getAttributeDescription(Method attributeMethod) + { + MBeanAttribute anno = attributeMethod.getAnnotation(MBeanAttribute.class); + if (anno != null) + { + return anno.description(); + } + return _defaultAttributeDescription; + } + + /** + * Introspects the method to retrieve the operation information. + * @param operation + * @return MBeanOperationInfo + */ + private static MBeanOperationInfo getOperationInfo(Method operation) + { + MBeanOperationInfo operationInfo = null; + Class returnType = operation.getReturnType(); + + MBeanParameterInfo[] paramsInfo = getParametersInfo(operation.getParameterAnnotations(), + operation.getParameterTypes()); + + String operationDesc = _defaultOerationDescription; + int impact = MBeanOperationInfo.UNKNOWN; + + if (operation.getAnnotation(MBeanOperation.class) != null) + { + operationDesc = operation.getAnnotation(MBeanOperation.class).description(); + impact = operation.getAnnotation(MBeanOperation.class).impact(); + } + operationInfo = new MBeanOperationInfo(operation.getName(), + operationDesc, + paramsInfo, + returnType.getName(), + impact); + + return operationInfo; + } + + /** + * Constructs the parameter info. + * @param paramsAnno + * @param paramTypes + * @return MBeanParameterInfo[] + */ + private static MBeanParameterInfo[] getParametersInfo(Annotation[][] paramsAnno, + Class[] paramTypes) + { + int noOfParams = paramsAnno.length; + + MBeanParameterInfo[] paramsInfo = new MBeanParameterInfo[noOfParams]; + + for (int i = 0; i < noOfParams; i++) + { + MBeanParameterInfo paramInfo = null; + String type = paramTypes[i].getName(); + for (Annotation anno : paramsAnno[i]) + { + String name,desc; + if (MBeanOperationParameter.class.isInstance(anno)) + { + name = MBeanOperationParameter.class.cast(anno).name(); + desc = MBeanOperationParameter.class.cast(anno).description(); + paramInfo = new MBeanParameterInfo(name, type, desc); + } + } + + + if (paramInfo == null) + { + paramInfo = new MBeanParameterInfo("p " + (i + 1), type, "parameter " + (i + 1)); + } + if (paramInfo != null) + { + paramsInfo[i] = paramInfo; + } + } + + return paramsInfo; + } + + /** + * Introspects the MBean class for constructors + * @param implClass + * @return MBeanConstructorInfo[] + */ + static MBeanConstructorInfo[] getMBeanConstructorsInfo(Class implClass) + { + List constructors = new ArrayList(); + + for (Constructor cons : implClass.getConstructors()) + { + MBeanConstructorInfo constructorInfo = getMBeanConstructorInfo(cons); + if (constructorInfo != null) + { + constructors.add(constructorInfo); + } + } + + return constructors.toArray(new MBeanConstructorInfo[0]); + } + + /** + * Retrieves the constructor info from given constructor. + * @param cons + * @return MBeanConstructorInfo + */ + private static MBeanConstructorInfo getMBeanConstructorInfo(Constructor cons) + { + String desc = _defaultConstructorDescription; + Annotation anno = cons.getAnnotation(MBeanConstructor.class); + if (anno != null && MBeanConstructor.class.isInstance(anno)) + { + desc = MBeanConstructor.class.cast(anno).value(); + if(desc == null) + { + desc = _defaultConstructorDescription; + } + } + + return new MBeanConstructorInfo(cons.getName(), desc, null); + } + + /** + * Retrieves the description from the annotations of given class + * @param annotatedClass + * @return class description + */ + static String getMBeanDescription(Class annotatedClass) + { + Annotation anno = annotatedClass.getAnnotation(MBeanDescription.class); + if (anno != null && MBeanDescription.class.isInstance(anno)) + { + return MBeanDescription.class.cast(anno).value(); + } + return _defaultMbeanDescription; + } + +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java new file mode 100644 index 0000000000..49f06d5121 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java @@ -0,0 +1,382 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.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; +import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.access.Operation; + +import javax.management.Attribute; +import javax.management.JMException; +import javax.management.MBeanInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanServer; +import javax.management.Notification; +import javax.management.NotificationListener; +import javax.management.ObjectName; +import javax.management.remote.JMXConnectionNotification; +import javax.management.remote.JMXPrincipal; +import javax.management.remote.MBeanServerForwarder; +import javax.security.auth.Subject; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.util.Map; +import java.util.Set; + +/** + * This class can be used by the JMXConnectorServer as an InvocationHandler for the mbean operations. It delegates + * JMX access decisions to the SecurityPlugin. + */ +public class MBeanInvocationHandlerImpl implements InvocationHandler, NotificationListener +{ + private static final Logger _logger = Logger.getLogger(MBeanInvocationHandlerImpl.class); + + private final IApplicationRegistry _appRegistry = ApplicationRegistry.getInstance(); + private final static String DELEGATE = "JMImplementation:type=MBeanServerDelegate"; + private MBeanServer _mbs; + private final ManagementActor _logActor = new ManagementActor(_appRegistry.getRootMessageLogger()); + private final boolean _managementRightsInferAllAccess = + _appRegistry.getConfiguration().getManagementRightsInferAllAccess(); + + public static MBeanServerForwarder newProxyInstance() + { + final InvocationHandler handler = new MBeanInvocationHandlerImpl(); + final Class[] interfaces = new Class[] { MBeanServerForwarder.class }; + + Object proxy = Proxy.newProxyInstance(MBeanServerForwarder.class.getClassLoader(), interfaces, handler); + return MBeanServerForwarder.class.cast(proxy); + } + + private boolean invokeDirectly(String methodName, Object[] args, Subject subject) + { + // Allow operations performed locally on behalf of the connector server itself + if (subject == null) + { + return true; + } + + if (args == null || DELEGATE.equals(args[0])) + { + return true; + } + + // Allow querying available object names and mbeans + if (methodName.equals("queryNames") || methodName.equals("queryMBeans")) + { + return true; + } + + if (args[0] instanceof ObjectName) + { + ObjectName mbean = (ObjectName) args[0]; + + if(!DefaultManagedObject.DOMAIN.equalsIgnoreCase(mbean.getDomain())) + { + return true; + } + } + + return false; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable + { + String methodName = method.getName(); + + if (methodName.equals("getMBeanServer")) + { + return _mbs; + } + + if (methodName.equals("setMBeanServer")) + { + if (args[0] == null) + { + throw new IllegalArgumentException("Null MBeanServer"); + } + if (_mbs != null) + { + throw new IllegalArgumentException("MBeanServer object already initialized"); + } + _mbs = (MBeanServer) args[0]; + return null; + } + + // Restrict access to "createMBean" and "unregisterMBean" to any user + if (methodName.equals("createMBean") || methodName.equals("unregisterMBean")) + { + _logger.debug("User trying to create or unregister an MBean"); + throw new SecurityException("Access denied: " + methodName); + } + + // Retrieve Subject from current AccessControlContext + AccessControlContext acc = AccessController.getContext(); + Subject subject = Subject.getSubject(acc); + + try + { + if(invokeDirectly(methodName, args, subject)) + { + return method.invoke(_mbs, args); + } + + // Retrieve JMXPrincipal from Subject + Set principals = subject.getPrincipals(JMXPrincipal.class); + if (principals == null || principals.isEmpty()) + { + throw new SecurityException("Access denied: no JMX principal"); + } + + // Save the subject + SecurityManager.setThreadSubject(subject); + + // Get the component, type and impact, which may be null + String type = getType(method, args); + String vhost = getVirtualHost(method, args); + int impact = getImpact(method, args); + + // Get the security manager for the virtual host (if set) + SecurityManager security; + if (vhost == null) + { + security = _appRegistry.getSecurityManager(); + } + else + { + security = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhost).getSecurityManager(); + } + + methodName = getMethodName(method, args); + 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 + { + return doInvokeWrappingWithManagementActor(method, args); + } + finally + { + if(_managementRightsInferAllAccess) + { + SecurityManager.setAccessChecksDisabled(oldAccessChecksDisabled); + } + } + } + catch (InvocationTargetException e) + { + throw e.getTargetException(); + } + } + + 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; + } + + 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 + { + //if the name is quoted in the ObjectName, unquote it + vhost = ObjectName.unquote(vhost); + } + catch(IllegalArgumentException e) + { + //ignore, this just means the name is not quoted + //and can be left unchanged + } + } + + return vhost; + } + return null; + } + + private String getMethodName(Method method, Object[] args) + { + String methodName = method.getName(); + + // if arguments are set, try and work out real method name + if (args != null && args.length >= 1 && args[0] instanceof ObjectName) + { + if (methodName.equals("getAttribute")) + { + methodName = "get" + (String) args[1]; + } + else if (methodName.equals("setAttribute")) + { + methodName = "set" + ((Attribute) args[1]).getName(); + } + else if (methodName.equals("invoke")) + { + methodName = (String) args[1]; + } + } + + return methodName; + } + + private int getImpact(Method method, Object[] args) + { + //handle invocation of other methods on mbeans + if ((args[0] instanceof ObjectName) && (method.getName().equals("invoke"))) + { + //get invoked method name + String mbeanMethod = (args.length > 1) ? (String) args[1] : null; + if (mbeanMethod == null) + { + return -1; + } + + try + { + //Get the impact attribute + MBeanInfo mbeanInfo = _mbs.getMBeanInfo((ObjectName) args[0]); + if (mbeanInfo != null) + { + MBeanOperationInfo[] opInfos = mbeanInfo.getOperations(); + for (MBeanOperationInfo opInfo : opInfos) + { + if (opInfo.getName().equals(mbeanMethod)) + { + return opInfo.getImpact(); + } + } + } + } + catch (JMException ex) + { + _logger.error("Unable to determine mbean impact for method : " + mbeanMethod, ex); + } + } + + return -1; + } + + private boolean isAccessMethod(String methodName) + { + //handle standard get/query/is methods from MBeanServer + return (methodName.startsWith("query") || methodName.startsWith("get") || methodName.startsWith("is")); + } + + /** + * Receives notifications from the MBeanServer. + */ + public void handleNotification(final Notification notification, final Object handback) + { + assert notification instanceof JMXConnectionNotification; + + final String connectionId = ((JMXConnectionNotification) notification).getConnectionId(); + final String type = notification.getType(); + + if (_logger.isDebugEnabled()) + { + _logger.debug("Notification connectionId : " + connectionId + " type : " + type + + " Notification handback : " + handback); + } + + // Normally JMXManagedObjectRegistry provides a Map as handback data containing a map + // between connection id and username. + String user = null; + if (handback instanceof Map) + { + final Map connectionIdUsernameMap = (Map) handback; + user = connectionIdUsernameMap.get(connectionId); + } + + // If user is still null, fallback to an unordered list of Principals from the connection id. + if (user == null) + { + final String[] splitConnectionId = connectionId.split(" "); + user = splitConnectionId[1]; + } + + if (JMXConnectionNotification.OPENED.equals(type)) + { + _logActor.message(ManagementConsoleMessages.OPEN(user)); + } + else if (JMXConnectionNotification.CLOSED.equals(type) || + JMXConnectionNotification.FAILED.equals(type)) + { + _logActor.message(ManagementConsoleMessages.CLOSE(user)); + } + } +} + diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java new file mode 100644 index 0000000000..83909dbe72 --- /dev/null +++ b/java/broker-plugins/management-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 child 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/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java new file mode 100644 index 0000000000..40b778fd93 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObject.java @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.jmx; + +import javax.management.JMException; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; + +/** + * This should be implemented by all Managable objects. + */ +public interface ManagedObject +{ + static final String DOMAIN = "org.apache.qpid"; + + /** + * @return the name that uniquely identifies this object instance. It must be + * unique only among objects of this type at this level in the hierarchy so + * the uniqueness should not be too difficult to ensure. + */ + String getObjectInstanceName(); + + String getType(); + + Class getManagementInterface(); + + ManagedObject getParentObject(); + + void register() throws JMException; + + void unregister() throws JMException; + + /** + * Returns the ObjectName required for the mbeanserver registration. + * @return ObjectName + * @throws javax.management.MalformedObjectNameException + */ + ObjectName getObjectName() throws MalformedObjectNameException; +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java new file mode 100644 index 0000000000..2ae0ac7052 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagedObjectRegistry.java @@ -0,0 +1,48 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.jmx; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.common.Closeable; + +import javax.management.JMException; +import java.io.IOException; + +/** + * Handles the registration (and unregistration and so on) of managed objects. + * + * Managed objects are responsible for exposting attributes, operations and notifications. They will expose + * these outside the JVM therefore it is important not to use implementation objects directly as managed objects. + * Instead, creating inner classes and exposing those is an effective way of exposing internal state in a + * controlled way. + * + * Although we do not explictly use them while targetting Java 5, the enhanced MXBean approach in Java 6 will + * be the obvious choice for managed objects. + * + */ +public interface ManagedObjectRegistry extends Closeable +{ + void start() throws IOException, ConfigurationException; + + void registerObject(ManagedObject managedObject) throws JMException; + + void unregisterObject(ManagedObject managedObject) throws JMException; +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java new file mode 100644 index 0000000000..6ab7db3629 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/AbstractStatisticsGatheringMBean.java @@ -0,0 +1,200 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.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; + +abstract class AbstractStatisticsGatheringMBean 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/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java new file mode 100644 index 0000000000..beffb4eaa9 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java @@ -0,0 +1,56 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.jmx.mbeans; + +import org.apache.qpid.management.common.mbeans.ConfigurationManagement; +import org.apache.qpid.server.jmx.AMQManagedObject; +import org.apache.qpid.server.jmx.ManagedObject; +import org.apache.qpid.server.jmx.ManagedObjectRegistry; +import org.apache.qpid.server.registry.ApplicationRegistry; + +import javax.management.JMException; +import javax.management.NotCompliantMBeanException; + +public class ConfigurationManagementMBean extends AMQManagedObject implements ConfigurationManagement +{ + + public ConfigurationManagementMBean(ManagedObjectRegistry registry) throws JMException + { + super(ConfigurationManagement.class, ConfigurationManagement.TYPE, registry); + register(); + } + + public String getObjectInstanceName() + { + return ConfigurationManagement.TYPE; + } + + public void reloadSecurityConfiguration() throws Exception + { + ApplicationRegistry.getInstance().getConfiguration().reparseConfigFileSecuritySections(); + } + + @Override + public ManagedObject getParentObject() + { + return null; + } +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java new file mode 100644 index 0000000000..d0c0d5e73f --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java @@ -0,0 +1,182 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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 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 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) + { + 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/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java new file mode 100644 index 0000000000..56802d0403 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBean.java @@ -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. + * + */ + +package org.apache.qpid.server.jmx.mbeans; + +import org.apache.qpid.management.common.mbeans.ManagedExchange; +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.OperationsException; +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 +{ + + public static final String FANOUT_EXCHANGE_TYPE = "fanout"; + public static final String HEADERS_EXCHANGE_TYPE = "headers"; + + 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()]); + + 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 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 headerMappings = binding.getArguments(); + + final List mappingList = new ArrayList(); + + if(headerMappings != null) + { + for(Map.Entry 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 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> bindingMap = new HashMap>(); + + for (Binding binding : bindings) + { + String key = FANOUT_EXCHANGE_TYPE.equals(_exchange.getExchangeType()) ? "*" : binding.getName(); + List queueList = bindingMap.get(key); + if(queueList == null) + { + queueList = new ArrayList(); + bindingMap.put(key, queueList); + } + queueList.add(binding.getParent(Queue.class).getName()); + + } + + for(Map.Entry> 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 arguments = new HashMap(); + + 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 \"=,=\""); + } + + 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]); + } + } + } + + VirtualHost virtualHost = _exchange.getParent(VirtualHost.class); + Queue queue = MBeanUtils.findQueueFromQueueName(virtualHost, queueName); + _exchange.createBinding(binding, queue, arguments, Collections.EMPTY_MAP); + } + + public void removeBinding(String queueName, String bindingKey) + throws IOException, JMException + { + VirtualHost virtualHost = _exchange.getParent(VirtualHost.class); + Queue queue = MBeanUtils.findQueueFromQueueName(virtualHost, queueName);; + + boolean deleted = false; + for(Binding binding : _exchange.getBindings()) + { + if(queue.equals(binding.getParent(Queue.class)) && bindingKey.equals(binding.getName())) + { + binding.delete(); + deleted = true; + } + } + + if (!deleted) + { + throw new OperationsException("No such binding \"" + bindingKey + "\" on queue \"" + queueName + "\""); + } + } +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java new file mode 100644 index 0000000000..0dac8ebe37 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java @@ -0,0 +1,324 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * + */ +package org.apache.qpid.server.jmx.mbeans; + +import org.apache.log4j.Logger; +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.apache.qpid.server.logging.log4j.LoggingFacade; +import org.apache.qpid.server.logging.log4j.LoggingFacadeException; + +import javax.management.JMException; +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.List; +import java.util.Map; + + +/** MBean class for LoggingManagement. It implements all the management features exposed for managing logging. */ +@MBeanDescription("Logging Management Interface") +public class LoggingManagementMBean extends AMQManagedObject implements LoggingManagement +{ + public static final String INHERITED_PSUEDO_LOG_LEVEL = "INHERITED"; + private static final Logger LOGGER = Logger.getLogger(LoggingManagementMBean.class); + private static final TabularType LOGGER_LEVEL_TABULAR_TYE; + private static final CompositeType LOGGER_LEVEL_COMPOSITE_TYPE; + + private final LoggingFacade _configurator; + + static + { + try + { + OpenType[] loggerLevelItemTypes = new OpenType[]{SimpleType.STRING, SimpleType.STRING}; + + LOGGER_LEVEL_COMPOSITE_TYPE = new CompositeType("LoggerLevelList", "Logger Level Data", + COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), + COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]), + loggerLevelItemTypes); + + LOGGER_LEVEL_TABULAR_TYE = new TabularType("LoggerLevel", "List of loggers with levels", + LOGGER_LEVEL_COMPOSITE_TYPE, + TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()])); + } + catch (OpenDataException e) + { + throw new ExceptionInInitializerError(e); + } + } + + public LoggingManagementMBean(LoggingFacade configurator, ManagedObjectRegistry registry) throws JMException + { + super(LoggingManagement.class, LoggingManagement.TYPE, registry); + register(); + _configurator = configurator; + } + + @Override + public String getObjectInstanceName() + { + return LoggingManagement.TYPE; + } + + @Override + public ManagedObject getParentObject() + { + return null; + } + + @Override + public Integer getLog4jLogWatchInterval() + { + return _configurator.getLog4jLogWatchInterval(); + } + + @Override + public String[] getAvailableLoggerLevels() + { + List levels = _configurator.getAvailableLoggerLevels(); + List mbeanLevels = new ArrayList(levels); + mbeanLevels.add(INHERITED_PSUEDO_LOG_LEVEL); + + return mbeanLevels.toArray(new String[mbeanLevels.size()]); + } + + @Override + public TabularData viewEffectiveRuntimeLoggerLevels() + { + Map levels = _configurator.retrieveRuntimeLoggersLevels(); + return createTabularDataFromLevelsMap(levels); + } + + @Override + public String getRuntimeRootLoggerLevel() + { + return _configurator.retrieveRuntimeRootLoggerLevel(); + } + + @Override + public boolean setRuntimeRootLoggerLevel(String level) + { + try + { + validateLevelNotAllowingInherited(level); + } + catch (IllegalArgumentException iae) + { + LOGGER.warn(level + " is not a known level"); + return false; + } + + _configurator.setRuntimeRootLoggerLevel(level); + return true; + } + + @Override + public boolean setRuntimeLoggerLevel(String logger, String level) + { + String validatedLevel; + try + { + validatedLevel = getValidateLevelAllowingInherited(level); + } + catch (IllegalArgumentException iae) + { + LOGGER.warn(level + " is not a known level"); + return false; + } + + try + { + _configurator.setRuntimeLoggerLevel(logger, validatedLevel); + } + catch (LoggingFacadeException e) + { + LOGGER.error("Cannot set runtime logging level", e); + return false; + } + return true; + } + + @Override + public TabularData viewConfigFileLoggerLevels() + { + Map levels; + try + { + levels = _configurator.retrieveConfigFileLoggersLevels(); + } + catch (LoggingFacadeException e) + { + LOGGER.error("Cannot determine logging levels", e); + return null; + } + + return createTabularDataFromLevelsMap(levels); + } + + @Override + public String getConfigFileRootLoggerLevel()throws IOException + { + try + { + return _configurator.retrieveConfigFileRootLoggerLevel().toUpperCase(); + } + catch (LoggingFacadeException e) + { + LOGGER.warn("The log4j configuration get config request was aborted: ", e); + throw new IOException("The log4j configuration get config request was aborted: " + e.getMessage()); + } + } + + @Override + public boolean setConfigFileLoggerLevel(String logger, String level) + { + String validatedLevel; + try + { + validatedLevel = getValidateLevelAllowingInherited(level); + } + catch (IllegalArgumentException iae) + { + LOGGER.warn(level + " is not a known level"); + return false; + } + + try + { + _configurator.setConfigFileLoggerLevel(logger, validatedLevel); + } + catch (LoggingFacadeException e) + { + LOGGER.warn("The log4j configuration set config request was aborted: ", e); + return false; + } + return true; + } + + @Override + public boolean setConfigFileRootLoggerLevel(String level) + { + try + { + validateLevelNotAllowingInherited(level); + } + catch (IllegalArgumentException iae) + { + LOGGER.warn(level + " is not a known level"); + return false; + } + + try + { + _configurator.setConfigFileRootLoggerLevel(level); + return true; + } + catch (LoggingFacadeException e) + { + LOGGER.warn("The log4j configuration set config request was aborted: ", e); + return false; + } + } + + @Override + public void reloadConfigFile() throws IOException + { + try + { + + _configurator.reload(); + } + catch (LoggingFacadeException e) + { + LOGGER.warn("The log4j configuration reload request was aborted: ", e); + throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage()); + } + } + + private String getValidateLevelAllowingInherited(String level) + { + if(level == null + || "null".equalsIgnoreCase(level) + || INHERITED_PSUEDO_LOG_LEVEL.equalsIgnoreCase(level)) + { + //the string "null" or "inherited" signals to inherit from a parent logger, + //using a null Level reference for the logger. + return null; + } + + validateLevelNotAllowingInherited(level); + return level; + } + + private void validateLevelNotAllowingInherited(String level) + { + final List availableLoggerLevels = _configurator.getAvailableLoggerLevels(); + if (!availableLoggerLevels.contains(level) + && !availableLoggerLevels.contains(String.valueOf(level).toUpperCase())) + { + throw new IllegalArgumentException(level + " not known"); + } + } + + private TabularData createTabularDataFromLevelsMap(Map levels) + { + TabularData loggerLevelList = new TabularDataSupport(LOGGER_LEVEL_TABULAR_TYE); + for (Map.Entry entry : levels.entrySet()) + { + String loggerName = entry.getKey(); + String level = entry.getValue(); + + CompositeData loggerData = createRow(loggerName, level); + loggerLevelList.put(loggerData); + } + return loggerLevelList; + } + + + private CompositeData createRow(String loggerName, String level) + { + Object[] itemData = {loggerName, level.toUpperCase()}; + try + { + CompositeData loggerData = new CompositeDataSupport(LOGGER_LEVEL_COMPOSITE_TYPE, + COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), itemData); + return loggerData; + } + catch (OpenDataException ode) + { + // Should not happen + throw new RuntimeException(ode); + } + } +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/MBeanUtils.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/MBeanUtils.java new file mode 100644 index 0000000000..97e84d4796 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/MBeanUtils.java @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.jmx.mbeans; + +import javax.management.OperationsException; + +import org.apache.qpid.server.model.ConfiguredObjectFinder; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.VirtualHost; + +public class MBeanUtils +{ + public static 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; + } + } + + public static 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/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java new file mode 100644 index 0000000000..1416cfdd89 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java @@ -0,0 +1,663 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.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(); + } + + 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 = MBeanUtils.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 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 = MBeanUtils.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 = MBeanUtils.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 getMessages(final long first, final long last) + { + final List messages = new ArrayList((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 Number getStatisticValue(String name) + { + final Number statistic = (Number) _queue.getStatistics().getStatistic(name); + return statistic == null ? Integer.valueOf(0) : statistic; + } +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java new file mode 100644 index 0000000000..67d5861dec --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBean.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.jmx.mbeans; + +import java.io.IOException; + +import javax.management.JMException; +import javax.management.NotCompliantMBeanException; + +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 implements ServerInformation +{ + private final Broker _broker; + + public ServerInformationMBean(ManagedObjectRegistry registry, Broker broker) + throws NotCompliantMBeanException, JMException + { + super(ServerInformation.class, ServerInformation.TYPE, registry, broker); + _broker = broker; + + 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 (String) _broker.getAttribute(Broker.BUILD_VERSION); + } + + @Override + public String getProductVersion() throws IOException + { + return (String) _broker.getAttribute(Broker.PRODUCT_VERSION); + } + + @Override + public boolean isStatisticsEnabled() + { + return true; + } + + @Override + public ManagedObject getParentObject() + { + // does not have a parent + return null; + } +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java new file mode 100644 index 0000000000..62733168ef --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/Shutdown.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.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; +import java.util.Date; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * Implementation of the JMX broker shutdown plugin. + */ +public class Shutdown extends DefaultManagedObject implements ShutdownMBean +{ + + private static final Logger _logger = Logger.getLogger(Shutdown.class); + + private static final String FORMAT = "yyyy/MM/dd HH:mm:ss"; + private static final int THREAD_COUNT = 1; + private static final ScheduledExecutorService EXECUTOR = new ScheduledThreadPoolExecutor(THREAD_COUNT); + + private final Runnable _shutdown = new SystemExiter(); + + public Shutdown(ManagedObjectRegistry registry) throws JMException + { + super(ShutdownMBean.class, ShutdownMBean.TYPE, registry); + register(); + } + + /** @see ShutdownMBean#shutdown() */ + public void shutdown() + { + _logger.info("Shutting down at user's request"); + shutdownBroker(0); + } + + /** @see ShutdownMBean#shutdown(long) */ + public void shutdown(final long delay) + { + if (delay < 0) + { + _logger.info("Shutting down at user's request"); + shutdownBroker(0); + } + else + { + _logger.info("Scheduled broker shutdown after " + delay + "ms"); + shutdownBroker(delay); + } + } + + /** @see ShutdownMBean#shutdownAt(String) */ + public void shutdownAt(final String when) + { + Date date; + DateFormat df = new SimpleDateFormat(FORMAT); + try + { + date = df.parse(when); + } + catch (ParseException e) + { + _logger.error("Invalid date \"" + when + "\": expecting " + FORMAT, e); + return; + } + _logger.info("Scheduled broker shutdown at " + when); + long now = System.currentTimeMillis(); + long time = date.getTime(); + if (time > now) + { + shutdownBroker(time - now); + } + else + { + shutdownBroker(0); + } + } + + /** + * Submits the {@link SystemExiter} job to shutdown the broker. + */ + private void shutdownBroker(long delay) + { + 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. + */ + class SystemExiter implements Runnable + { + public void run() + { + System.exit(0); + } + } + + /** + * @see ManagedObject#getObjectInstanceName() + */ + public String getObjectInstanceName() + { + return "Shutdown"; + } +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java new file mode 100644 index 0000000000..ed69c351f7 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ShutdownMBean.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.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. + * + * Shuts the Qpid broker down via JMX. + */ +public interface ShutdownMBean +{ + static final String TYPE = "Shutdown"; + + /** + * Broker will be shut down immediately. + */ + @MBeanOperation(name="shutdown", description="Shut down immediately", impact = MBeanOperationInfo.ACTION) + public void shutdown(); + + /** + * Broker will be shutdown after the specified delay + * + * @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); + + /** + * Broker will be shutdown at the specified date and time. + * + * @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); +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java new file mode 100644 index 0000000000..c7aade34b4 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBean.java @@ -0,0 +1,179 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.log4j.Logger; + +import org.apache.qpid.management.common.mbeans.UserManagement; +import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; +import org.apache.qpid.server.jmx.AMQManagedObject; +import org.apache.qpid.server.jmx.ManagedObject; +import org.apache.qpid.server.jmx.ManagedObjectRegistry; +import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider; + +import javax.management.JMException; +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 javax.security.auth.login.AccountNotFoundException; + +import java.io.IOException; +import java.util.Map; + +@MBeanDescription("User Management Interface") +public class UserManagementMBean extends AMQManagedObject implements UserManagement +{ + private static final Logger _logger = Logger.getLogger(UserManagementMBean.class); + + private PasswordCredentialManagingAuthenticationProvider _authProvider; + + // Setup for the TabularType + private static final TabularType _userlistDataType; // Datatype for representing User Lists + private static final CompositeType _userDataType; // Composite type for representing User + + static + { + OpenType[] userItemTypes = new OpenType[4]; // User item types. + userItemTypes[0] = SimpleType.STRING; // For Username + userItemTypes[1] = SimpleType.BOOLEAN; // For Rights - Read - No longer in use + userItemTypes[2] = SimpleType.BOOLEAN; // For Rights - Write - No longer in use + userItemTypes[3] = SimpleType.BOOLEAN; // For Rights - Admin - No longer is use + + try + { + _userDataType = + new CompositeType("User", "User Data", COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), + COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]), userItemTypes); + + _userlistDataType = new TabularType("Users", "List of users", _userDataType, TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()])); + } + catch (OpenDataException e) + { + _logger.error("Tabular data setup for viewing users incorrect.", e); + throw new ExceptionInInitializerError("Tabular data setup for viewing users incorrect"); + } + } + + public UserManagementMBean(PasswordCredentialManagingAuthenticationProvider provider, ManagedObjectRegistry registry) throws JMException + { + 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 + { + _authProvider.setPassword(username, password); + } + catch (AccountNotFoundException e) + { + _logger.warn("Attempt to set password of non-existent user '" + username + "'"); + return false; + } + return true; + } + + @Override + public boolean createUser(String username, String password) + { + return _authProvider.createUser(username, password, null); + } + + @Override + public boolean deleteUser(String username) + { + try + { + _authProvider.deleteUser(username); + } + catch (AccountNotFoundException e) + { + _logger.warn("Attempt to delete user (" + username + ") that doesn't exist"); + return false; + } + + return true; + } + + @Override + public boolean reloadData() + { + try + { + _authProvider.reload(); + return true; + } + catch (IOException e) + { + _logger.error("Unable to reload user data", e); + return false; + } + } + + @Override + public TabularData viewUsers() + { + Map> users = _authProvider.getUsers(); + + TabularDataSupport userList = new TabularDataSupport(_userlistDataType); + + try + { + // Create the tabular list of message header contents + for (String user : users.keySet()) + { + // Create header attributes list + // 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); + } + } + catch (OpenDataException e) + { + _logger.warn("Unable to create user list due to :", e); + return null; + } + + return userList; + } + + @Override + public ManagedObject getParentObject() + { + return null; + } +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java new file mode 100644 index 0000000000..6990a40dee --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java @@ -0,0 +1,211 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.log4j.Logger; +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 static final Logger LOGGER = Logger.getLogger(VirtualHostMBean.class); + + private final VirtualHost _virtualHost; + + private final Map _children = + new HashMap(); + 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 + { + LOGGER.debug("Unsupported child : " + child.getName() + " type : " + child.getClass()); + } + + } + catch(JMException e) + { + LOGGER.error("Failed to add mbean for child : " + child.getName(), e); + } + } + } + + public void childRemoved(ConfiguredObject object, ConfiguredObject child) + { + synchronized (_children) + { + AMQManagedObject mbean = _children.remove(child); + if(mbean != null) + { + try + { + mbean.unregister(); + } + catch(JMException e) + { + LOGGER.error("Failed to remove mbean for child : " + child.getName(), e); + } + } + } + } + + @Override + public ManagedObject getParentObject() + { + return null; + } + + protected VirtualHost getVirtualHost() + { + return _virtualHost; + } + + public Collection getQueues() + { + Collection children; + synchronized (_children) + { + children = new ArrayList(_children.values()); + } + Collection queues = new ArrayList(); + + for(AMQManagedObject child : children) + { + if(child instanceof QueueMBean) + { + queues.add((QueueMBean) child); + } + } + + return queues; + } +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java new file mode 100644 index 0000000000..b3dbbc424a --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java @@ -0,0 +1,238 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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 javax.management.OperationsException; + +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 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(); + } + + + @Override + public String getObjectInstanceName() + { + return ObjectName.quote(_virtualHostMBean.getName()); + } + + @Override + public ManagedObject getParentObject() + { + return _virtualHostMBean; + } + + @Override + public String[] getExchangeTypes() throws IOException + { + Collection exchangeTypes = _virtualHostMBean.getVirtualHost().getExchangeTypes(); + return exchangeTypes.toArray(new String[exchangeTypes.size()]); + } + + @Override + public List retrieveQueueAttributeNames() throws IOException + { + return ManagedQueue.QUEUE_ATTRIBUTES; + } + + @Override + public List> retrieveQueueAttributeValues( + @MBeanOperationParameter(name = "attributes", description = "Attributes to retrieve") String[] attributes) + throws IOException + { + int attributesLength = attributes.length; + + List> queueAttributesList = new ArrayList>(); + + for(QueueMBean queue : _virtualHostMBean.getQueues()) + { + + if(queue == null) + { + continue; + } + + List attributeValues = new ArrayList(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; + + } + + @Override + public void createNewExchange(String name, String type, boolean durable) + throws IOException, JMException, MBeanException + { + if (!getConfiguredObject().getExchangeTypes().contains(type)) + { + throw new OperationsException("No such exchange type \""+type+"\""); + } + + try + { + getConfiguredObject().createExchange(name, State.ACTIVE, durable, + LifetimePolicy.PERMANENT, 0l, type, Collections.EMPTY_MAP); + } + catch (IllegalArgumentException iae) + { + JMException jme = new JMException(iae.toString()); + throw new MBeanException(jme, "Error in creating exchange " + name); + } + + } + + @Override + public void unregisterExchange(String exchangeName) + throws IOException, JMException, MBeanException + { + Exchange theExchange = MBeanUtils.findExchangeFromExchangeName(_virtualHostMBean.getVirtualHost(), exchangeName); + try + { + theExchange.delete(); + } + catch (IllegalStateException ex) + { + final JMException jme = new JMException(ex.toString()); + throw new MBeanException(jme, "Error in unregistering exchange " + exchangeName); + } + } + + @Override + public void createNewQueue(String queueName, String owner, boolean durable) + throws IOException, JMException, MBeanException + { + createNewQueue(queueName, owner, durable, Collections.EMPTY_MAP); + } + + @Override + public void createNewQueue(String queueName, String owner, boolean durable, Map originalArguments) + throws IOException, JMException + { + final Map 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 processNewQueueArguments(String queueName, + String owner, Map arguments) + { + final Map argumentsCopy; + if (_moveNonExclusiveQueueOwnerToDescription && owner != null) + { + argumentsCopy = new HashMap(arguments == null ? new HashMap() : 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; + } + + @Override + public void deleteQueue( + @MBeanOperationParameter(name = ManagedQueue.TYPE, description = "Queue Name") String queueName) + throws IOException, JMException, MBeanException + { + Queue theQueue = MBeanUtils.findQueueFromQueueName(_virtualHostMBean.getVirtualHost(), queueName); + theQueue.delete(); + } + + @Override + public ObjectName getObjectName() throws MalformedObjectNameException + { + return getObjectNameForSingleInstanceMBean(); + } + + public synchronized boolean isStatisticsEnabled() + { + updateStats(); + return false; //TODO - implement isStatisticsEnabled + } + +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.java new file mode 100644 index 0000000000..a2631bab7f --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/NoopManagedObjectRegistry.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.jmx; + +import javax.management.JMException; + +public class NoopManagedObjectRegistry implements ManagedObjectRegistry +{ + public NoopManagedObjectRegistry() + { + } + + public void start() + { + } + + public void registerObject(ManagedObject managedObject) throws JMException + { + } + + public void unregisterObject(ManagedObject managedObject) throws JMException + { + } + + public void close() + { + } +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java new file mode 100644 index 0000000000..0c5fb0bf1f --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBeanTest.java @@ -0,0 +1,237 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.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 testGetClientId() throws Exception + { + assertAttribute("clientId", "testClientId", Connection.CLIENT_ID); + } + + 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); + MBeanTestUtils.assertMBeanAttribute(_connectionMBean, jmxAttributeName, expectedValue); + } + + 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/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBeanTest.java new file mode 100644 index 0000000000..e350f80a25 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ExchangeMBeanTest.java @@ -0,0 +1,234 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.Mockito.never; +import static org.mockito.Matchers.isNull; +import static org.mockito.Matchers.argThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.anyMap; + + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +import javax.management.JMException; +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.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.Statistics; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.queue.NotificationCheck; +import org.mockito.ArgumentMatcher; + +import junit.framework.TestCase; + +public class ExchangeMBeanTest extends TestCase +{ + private static final String EXCHANGE_NAME = "EXCHANGE_NAME"; + private static final String EXCHANGE_TYPE = "EXCHANGE_TYPE"; + private static final String QUEUE1_NAME = "QUEUE1_NAME"; + private static final String QUEUE2_NAME = "QUEUE2_NAME"; + private static final String BINDING1 = "BINDING1"; + private static final String BINDING2 = "BINDING2"; + + private Exchange _mockExchange; + private VirtualHostMBean _mockVirtualHostMBean; + private ManagedObjectRegistry _mockManagedObjectRegistry; + private ExchangeMBean _exchangeMBean; + private Queue _mockQueue1; + private Queue _mockQueue2; + private Exchange _mockHeadersExchange; + + @Override + protected void setUp() throws Exception + { + _mockExchange = mock(Exchange.class); + when(_mockExchange.getName()).thenReturn(EXCHANGE_NAME); + when(_mockExchange.getExchangeType()).thenReturn(EXCHANGE_TYPE); + _mockVirtualHostMBean = mock(VirtualHostMBean.class); + + _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class); + when(_mockVirtualHostMBean.getRegistry()).thenReturn(_mockManagedObjectRegistry); + + _mockQueue1 = createMockQueue(QUEUE1_NAME); + _mockQueue2 = createMockQueue(QUEUE2_NAME); + + VirtualHost mockVirtualHost = mock(VirtualHost.class); + when(mockVirtualHost.getQueues()).thenReturn(Arrays.asList(new Queue[] {_mockQueue1, _mockQueue2})); + when(_mockExchange.getParent(VirtualHost.class)).thenReturn(mockVirtualHost); + + _exchangeMBean = new ExchangeMBean(_mockExchange, _mockVirtualHostMBean); + + _mockHeadersExchange = mock(Exchange.class); + when(_mockHeadersExchange.getExchangeType()).thenReturn(ExchangeMBean.HEADERS_EXCHANGE_TYPE); + when(_mockHeadersExchange.getParent(VirtualHost.class)).thenReturn(mockVirtualHost); + + } + + public void testExchangeName() + { + assertEquals(EXCHANGE_NAME, _exchangeMBean.getName()); + } + + public void testExchangeType() + { + assertEquals(EXCHANGE_TYPE, _exchangeMBean.getExchangeType()); + } + + public void testNonHeadersExchangeCreateNewBinding() throws Exception + { + _exchangeMBean.createNewBinding(QUEUE1_NAME, BINDING1); + verify(_mockExchange).createBinding(BINDING1, _mockQueue1, Collections.EMPTY_MAP, Collections.EMPTY_MAP); + } + + public void testCreateNewBindingWhereQueueIsUnknown() throws Exception + { + try + { + _exchangeMBean.createNewBinding("unknown", BINDING1); + } + catch (OperationsException oe) + { + // PASS + assertEquals("No such queue \"unknown\"", oe.getMessage()); + } + verify(_mockExchange, never()).createBinding(anyString(), any(Queue.class), anyMap(), anyMap()); + } + + public void testRemoveBinding() throws Exception + { + Binding mockBinding1 = createBindingOnQueue(BINDING1, _mockQueue1); + Binding mockBinding2 = createBindingOnQueue(BINDING2, _mockQueue1); + when(_mockExchange.getBindings()).thenReturn(Arrays.asList(new Binding[] {mockBinding1, mockBinding2})); + + _exchangeMBean.removeBinding(QUEUE1_NAME, BINDING1); + verify(mockBinding1).delete(); + } + + public void testRemoveBindingWhereQueueIsUnknown() throws Exception + { + Binding mockBinding1 = createBindingOnQueue(BINDING1, _mockQueue1); + when(_mockExchange.getBindings()).thenReturn(Arrays.asList(new Binding[] {mockBinding1})); + + try + { + _exchangeMBean.removeBinding("unknown", BINDING1); + fail("Exception not thrown"); + } + catch (OperationsException oe) + { + // PASS + assertEquals("No such queue \"unknown\"", oe.getMessage()); + } + verify(mockBinding1, never()).delete(); + } + + public void testRemoveBindingWhereBindingNameIsUnknown() throws Exception + { + Binding mockBinding1 = createBindingOnQueue(BINDING1, _mockQueue1); + when(_mockExchange.getBindings()).thenReturn(Arrays.asList(new Binding[] {mockBinding1})); + + try + { + _exchangeMBean.removeBinding(QUEUE1_NAME, "unknown"); + fail("Exception not thrown"); + } + catch (OperationsException oe) + { + // PASS + assertEquals("No such binding \"unknown\" on queue \"" + QUEUE1_NAME + "\"", oe.getMessage()); + } + verify(mockBinding1, never()).delete(); + } + + public void testHeadersExchangeCreateNewBinding() throws Exception + { + String binding = "key1=binding1,key2=binding2"; + Map expectedBindingMap = new HashMap() + {{ + put("key1", "binding1"); + put("key2", "binding2"); + }}; + _exchangeMBean = new ExchangeMBean(_mockHeadersExchange, _mockVirtualHostMBean); + + _exchangeMBean.createNewBinding(QUEUE1_NAME, binding); + verify(_mockHeadersExchange).createBinding(binding, _mockQueue1, expectedBindingMap, Collections.EMPTY_MAP); + } + + public void testHeadersExchangeCreateNewBindingWithFieldWithoutValue() throws Exception + { + String binding = "key1=binding1,key2="; + Map expectedBindingMap = new HashMap() + {{ + put("key1", "binding1"); + put("key2", ""); + }}; + _exchangeMBean = new ExchangeMBean(_mockHeadersExchange, _mockVirtualHostMBean); + + _exchangeMBean.createNewBinding(QUEUE1_NAME, binding); + verify(_mockHeadersExchange).createBinding(binding, _mockQueue1, expectedBindingMap, Collections.EMPTY_MAP); + } + + public void testHeadersExchangeCreateNewBindingMalformed() throws Exception + { + String binding = "=binding1,="; + _exchangeMBean = new ExchangeMBean(_mockHeadersExchange, _mockVirtualHostMBean); + + try + { + _exchangeMBean.createNewBinding(QUEUE1_NAME, binding); + fail("Exception not thrown"); + } + catch (JMException e) + { + assertEquals("Format for headers binding should be \"=,=\"", e.getMessage()); + } + } + + private Binding createBindingOnQueue(String bindingName, Queue queue) + { + Binding mockBinding = mock(Binding.class); + when(mockBinding.getParent(Queue.class)).thenReturn(queue); + when(mockBinding.getName()).thenReturn(bindingName); + return mockBinding; + } + + private Queue createMockQueue(String queueName) + { + Queue mockQueue = mock(Queue.class); + when(mockQueue.getName()).thenReturn(queueName); + return mockQueue; + } + +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java new file mode 100644 index 0000000000..ae1be5db00 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java @@ -0,0 +1,245 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.Matchers.anyString; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.TabularData; + +import junit.framework.TestCase; + +import org.apache.qpid.management.common.mbeans.LoggingManagement; +import org.apache.qpid.server.jmx.ManagedObjectRegistry; +import org.apache.qpid.server.logging.log4j.LoggingFacade; + +public class LoggingManagementMBeanTest extends TestCase +{ + private static final String TEST_LEVEL1 = "LEVEL1"; + private static final String TEST_LEVEL2 = "LEVEL2"; + + private LoggingManagementMBean _loggingMBean; + private LoggingFacade _mockLoggingFacade; + private ManagedObjectRegistry _mockManagedObjectRegistry; + + @Override + protected void setUp() throws Exception + { + _mockLoggingFacade = mock(LoggingFacade.class); + final List listOfLevels = new ArrayList() + {{ + add(TEST_LEVEL1); + add(TEST_LEVEL2); + }}; + when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(listOfLevels); + + _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class); + + _loggingMBean = new LoggingManagementMBean(_mockLoggingFacade, _mockManagedObjectRegistry); + } + + public void testMBeanRegistersItself() throws Exception + { + LoggingManagementMBean connectionMBean = new LoggingManagementMBean(_mockLoggingFacade, _mockManagedObjectRegistry); + verify(_mockManagedObjectRegistry).registerObject(connectionMBean); + } + + public void testLog4jLogWatchInterval() throws Exception + { + final Integer value = 5000; + when(_mockLoggingFacade.getLog4jLogWatchInterval()).thenReturn(value); + + assertEquals("Unexpected watch interval",value, _loggingMBean.getLog4jLogWatchInterval()); + } + + public void testGetAvailableLoggerLevels() throws Exception + { + String[] actualLevels = _loggingMBean.getAvailableLoggerLevels(); + assertEquals(3, actualLevels.length); + assertEquals(TEST_LEVEL1, actualLevels[0]); + assertEquals(TEST_LEVEL2, actualLevels[1]); + assertEquals(LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL, actualLevels[2]); + } + + public void testViewEffectiveRuntimeLoggerLevels() throws Exception + { + Map loggerLevels = new TreeMap(); + loggerLevels.put("a.b.D", TEST_LEVEL2); + loggerLevels.put("a.b.C", TEST_LEVEL1); + loggerLevels.put("a.b.c.E", TEST_LEVEL2); + + when(_mockLoggingFacade.retrieveRuntimeLoggersLevels()).thenReturn(loggerLevels ); + + TabularData table = _loggingMBean.viewEffectiveRuntimeLoggerLevels(); + assertEquals(3, table.size()); + + final CompositeData row1 = table.get(new String[] {"a.b.C"} ); + final CompositeData row2 = table.get(new String[] {"a.b.D"} ); + final CompositeData row3 = table.get(new String[] {"a.b.c.E"} ); + assertChannelRow(row1, "a.b.C", TEST_LEVEL1); + assertChannelRow(row2, "a.b.D", TEST_LEVEL2); + assertChannelRow(row3, "a.b.c.E", TEST_LEVEL2); + } + + public void testGetRuntimeRootLoggerLevel() throws Exception + { + when(_mockLoggingFacade.retrieveRuntimeRootLoggerLevel()).thenReturn(TEST_LEVEL1); + + assertEquals(TEST_LEVEL1, _loggingMBean.getRuntimeRootLoggerLevel()); + } + + public void testSetRuntimeRootLoggerLevel() throws Exception + { + _loggingMBean.setRuntimeRootLoggerLevel(TEST_LEVEL1); + verify(_mockLoggingFacade).setRuntimeRootLoggerLevel(TEST_LEVEL1); + } + + public void testSetRuntimeRootLoggerLevelWhenLoggingLevelUnknown() throws Exception + { + boolean result = _loggingMBean.setRuntimeRootLoggerLevel("unknown"); + assertFalse(result); + verify(_mockLoggingFacade, never()).setRuntimeRootLoggerLevel("unknown"); + } + + public void testSetRuntimeRootLoggerLevelWhenLoggingLevelInherited() throws Exception + { + boolean result = _loggingMBean.setRuntimeRootLoggerLevel(LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL); + assertFalse(result); + verify(_mockLoggingFacade, never()).setRuntimeRootLoggerLevel(anyString()); + } + + public void testSetRuntimeLoggerLevel() throws Exception + { + _loggingMBean.setRuntimeLoggerLevel("a.b.c.D", TEST_LEVEL1); + verify(_mockLoggingFacade).setRuntimeLoggerLevel("a.b.c.D", TEST_LEVEL1); + } + + public void testSetRuntimeLoggerLevelWhenLoggingLevelUnknown() throws Exception + { + boolean result = _loggingMBean.setRuntimeLoggerLevel("a.b.c.D", "unknown"); + assertFalse(result); + verify(_mockLoggingFacade, never()).setRuntimeLoggerLevel(anyString(), anyString()); + } + + public void testSetRuntimeLoggerLevelWhenLoggingLevelInherited() throws Exception + { + boolean result = _loggingMBean.setRuntimeLoggerLevel("a.b.c.D", LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL); + assertTrue(result); + verify(_mockLoggingFacade).setRuntimeLoggerLevel("a.b.c.D", null); + } + + public void testViewEffectiveConfigFileLoggerLevels() throws Exception + { + Map loggerLevels = new TreeMap(); + loggerLevels.put("a.b.D", "level2"); + loggerLevels.put("a.b.C", TEST_LEVEL1); + loggerLevels.put("a.b.c.E", "level2"); + + when(_mockLoggingFacade.retrieveConfigFileLoggersLevels()).thenReturn(loggerLevels ); + + TabularData table = _loggingMBean.viewConfigFileLoggerLevels(); + assertEquals(3, table.size()); + + final CompositeData row1 = table.get(new String[] {"a.b.C"} ); + final CompositeData row2 = table.get(new String[] {"a.b.D"} ); + final CompositeData row3 = table.get(new String[] {"a.b.c.E"} ); + assertChannelRow(row1, "a.b.C", TEST_LEVEL1); + assertChannelRow(row2, "a.b.D", TEST_LEVEL2); + assertChannelRow(row3, "a.b.c.E", TEST_LEVEL2); + } + + public void testGetConfigFileRootLoggerLevel() throws Exception + { + when(_mockLoggingFacade.retrieveConfigFileRootLoggerLevel()).thenReturn(TEST_LEVEL1); + + assertEquals(TEST_LEVEL1, _loggingMBean.getConfigFileRootLoggerLevel()); + } + + public void testSetConfigFileRootLoggerLevel() throws Exception + { + when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1)); + _loggingMBean.setConfigFileRootLoggerLevel(TEST_LEVEL1); + verify(_mockLoggingFacade).setConfigFileRootLoggerLevel(TEST_LEVEL1); + } + + public void testSetConfigFileRootLoggerLevelWhenLoggingLevelUnknown() throws Exception + { + when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1)); + boolean result = _loggingMBean.setConfigFileRootLoggerLevel("unknown"); + assertFalse(result); + verify(_mockLoggingFacade, never()).setConfigFileRootLoggerLevel("unknown"); + } + + public void testSetConfigFileRootLoggerLevelWhenLoggingLevelInherited() throws Exception + { + when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1)); + boolean result = _loggingMBean.setConfigFileRootLoggerLevel(LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL); + assertFalse(result); + verify(_mockLoggingFacade, never()).setConfigFileRootLoggerLevel(anyString()); + } + + public void testSetConfigFileLoggerLevel() throws Exception + { + when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1)); + _loggingMBean.setConfigFileLoggerLevel("a.b.c.D", TEST_LEVEL1); + verify(_mockLoggingFacade).setConfigFileLoggerLevel("a.b.c.D", TEST_LEVEL1); + } + + public void testSetConfigFileLoggerLevelWhenLoggingLevelUnknown() throws Exception + { + when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1)); + boolean result = _loggingMBean.setConfigFileLoggerLevel("a.b.c.D", "unknown"); + assertFalse(result); + verify(_mockLoggingFacade, never()).setConfigFileLoggerLevel("a.b.c.D", "unknown"); + } + + public void testSetConfigFileLoggerLevelWhenLoggingLevelInherited() throws Exception + { + when(_mockLoggingFacade.getAvailableLoggerLevels()).thenReturn(Collections.singletonList(TEST_LEVEL1)); + boolean result = _loggingMBean.setConfigFileLoggerLevel("a.b.c.D", LoggingManagementMBean.INHERITED_PSUEDO_LOG_LEVEL); + assertTrue(result); + verify(_mockLoggingFacade).setConfigFileLoggerLevel("a.b.c.D", null); + } + + public void testReloadConfigFile() throws Exception + { + _loggingMBean.reloadConfigFile(); + + verify(_mockLoggingFacade).reload(); + } + + private void assertChannelRow(final CompositeData row, String logger, String level) + { + assertNotNull("No row for " + logger, row); + assertEquals("Unexpected logger name", logger, row.get(LoggingManagement.LOGGER_NAME)); + assertEquals("Unexpected level", level, row.get(LoggingManagement.LOGGER_LEVEL)); + } +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/MBeanTestUtils.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/MBeanTestUtils.java new file mode 100644 index 0000000000..5f913e5f33 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/MBeanTestUtils.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.jmx.mbeans; + +import junit.framework.TestCase; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.qpid.server.jmx.DefaultManagedObject; + +public class MBeanTestUtils +{ + + public static void assertMBeanAttribute(DefaultManagedObject managedObject, String jmxAttributeName, Object expectedValue) throws Exception + { + Object actualValue = PropertyUtils.getSimpleProperty(managedObject, jmxAttributeName); + TestCase.assertEquals("Attribute " + jmxAttributeName + " has unexpected value", expectedValue, actualValue); + } + + public static void setMBeanAttribute(DefaultManagedObject managedObject, String jmxAttributeName, Object newValue) throws Exception + { + PropertyUtils.setSimpleProperty(managedObject, jmxAttributeName, newValue); + } +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java new file mode 100644 index 0000000000..2003c12735 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java @@ -0,0 +1,368 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.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.LifetimePolicy; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.Statistics; +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 Statistics _mockQueueStatistics; + private VirtualHostMBean _mockVirtualHostMBean; + private ManagedObjectRegistry _mockManagedObjectRegistry; + private QueueMBean _queueMBean; + + @Override + protected void setUp() throws Exception + { + _mockQueue = mock(Queue.class); + _mockQueueStatistics = mock(Statistics.class); + when(_mockQueue.getName()).thenReturn(QUEUE_NAME); + when(_mockQueue.getStatistics()).thenReturn(_mockQueueStatistics); + _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()); + } + + /********** Statistics **********/ + + public void testGetMessageCount() throws Exception + { + assertStatistic("messageCount", 1000, Queue.QUEUE_DEPTH_MESSAGES); + } + + public void testGetReceivedMessageCount() throws Exception + { + assertStatistic("receivedMessageCount", 1000l, Queue.TOTAL_ENQUEUED_MESSAGES); + } + + public void testQueueDepth() throws Exception + { + assertStatistic("queueDepth", 4096l, Queue.QUEUE_DEPTH_BYTES); + } + + public void testActiveConsumerCount() throws Exception + { + assertStatistic("activeConsumerCount", 3, Queue.CONSUMER_COUNT_WITH_CREDIT); + } + + public void testConsumerCount() throws Exception + { + assertStatistic("consumerCount", 3, Queue.CONSUMER_COUNT); + } + + /********** Simple Attributes **********/ + + public void testGetQueueDescription() throws Exception + { + assertAttribute("description", QUEUE_DESCRIPTION, Queue.DESCRIPTION); + } + + public void testSetQueueDescription() throws Exception + { + testSetAttribute("description", Queue.DESCRIPTION, "descriptionold", "descriptionnew"); + } + + public void testQueueType() throws Exception + { + assertAttribute("queueType", QUEUE_TYPE, Queue.TYPE); + } + + public void testMaximumDeliveryCount() throws Exception + { + assertAttribute("maximumDeliveryCount", 5, Queue.MAXIMUM_DELIVERY_ATTEMPTS); + } + + public void testOwner() throws Exception + { + assertAttribute("owner", "testOwner", Queue.OWNER); + } + + public void testIsDurable() throws Exception + { + when(_mockQueue.isDurable()).thenReturn(true); + assertTrue(_queueMBean.isDurable()); + } + + public void testIsNotDurable() throws Exception + { + when(_mockQueue.isDurable()).thenReturn(false); + assertFalse(_queueMBean.isDurable()); + } + + public void testIsAutoDelete() throws Exception + { + when(_mockQueue.getLifetimePolicy()).thenReturn(LifetimePolicy.AUTO_DELETE); + assertTrue(_queueMBean.isAutoDelete()); + } + + public void testIsNotAutoDelete() throws Exception + { + when(_mockQueue.getLifetimePolicy()).thenReturn(LifetimePolicy.PERMANENT); + assertFalse(_queueMBean.isAutoDelete()); + } + + public void testGetMaximumMessageAge() throws Exception + { + assertAttribute("maximumMessageAge", 10000l, Queue.ALERT_THRESHOLD_MESSAGE_AGE); + } + + public void testSetMaximumMessageAge() throws Exception + { + testSetAttribute("maximumMessageAge", Queue.ALERT_THRESHOLD_MESSAGE_AGE, 1000l, 10000l); + } + + public void testGetMaximumMessageSize() throws Exception + { + assertAttribute("maximumMessageSize", 1024l, Queue.ALERT_THRESHOLD_MESSAGE_SIZE); + } + + public void testSetMaximumMessageSize() throws Exception + { + testSetAttribute("maximumMessageSize", Queue.ALERT_THRESHOLD_MESSAGE_SIZE, 1024l, 2048l); + } + + public void testGetMaximumMessageCount() throws Exception + { + assertAttribute("maximumMessageCount", 5000l, Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES); + } + + public void testSetMaximumMessageCount() throws Exception + { + testSetAttribute("maximumMessageCount", Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 4000l, 5000l); + } + + public void testGetMaximumQueueDepth() throws Exception + { + assertAttribute("maximumQueueDepth", 1048576l, Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES); + } + + public void testSetMaximumQueueDepth() throws Exception + { + testSetAttribute("maximumQueueDepth", Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES,1048576l , 2097152l); + } + + public void testGetCapacity() throws Exception + { + assertAttribute("capacity", 1048576l, Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES); + } + + public void testSetCapacity() throws Exception + { + testSetAttribute("capacity", Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES,1048576l , 2097152l); + } + + public void testGetFlowResumeCapacity() throws Exception + { + assertAttribute("flowResumeCapacity", 1048576l, Queue.QUEUE_FLOW_RESUME_SIZE_BYTES); + } + + public void testSetFlowResumeCapacity() throws Exception + { + testSetAttribute("flowResumeCapacity", Queue.QUEUE_FLOW_RESUME_SIZE_BYTES,1048576l , 2097152l); + } + + public void testIsExclusive() throws Exception + { + assertAttribute("exclusive", Boolean.TRUE, Queue.EXCLUSIVE); + } + + public void testIsNotExclusive() throws Exception + { + assertAttribute("exclusive", Boolean.FALSE, Queue.EXCLUSIVE); + } + + public void testSetExclusive() throws Exception + { + testSetAttribute("exclusive", Queue.EXCLUSIVE, Boolean.FALSE , Boolean.TRUE); + } + + /********** Other attributes **********/ + + 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); + } + + /********** Operations **********/ + + /********** Notifications **********/ + + 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() + { + @Override + public boolean matches(Object argument) + { + Notification actual = (Notification) argument; + return actual.getMessage().endsWith(expectedMessage); + } + }); + } + + private void assertStatistic(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception + { + when(_mockQueueStatistics.getStatistic(underlyingAttributeName)).thenReturn(expectedValue); + MBeanTestUtils.assertMBeanAttribute(_queueMBean, jmxAttributeName, expectedValue); + } + + private void assertAttribute(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception + { + when(_mockQueue.getAttribute(underlyingAttributeName)).thenReturn(expectedValue); + MBeanTestUtils.assertMBeanAttribute(_queueMBean, jmxAttributeName, expectedValue); + } + + private void testSetAttribute(String jmxAttributeName, String underlyingAttributeName, Object originalAttributeValue, Object newAttributeValue) throws Exception + { + when(_mockQueue.getAttribute(underlyingAttributeName)).thenReturn(originalAttributeValue); + + MBeanTestUtils.setMBeanAttribute(_queueMBean, jmxAttributeName, newAttributeValue); + + verify(_mockQueue).setAttribute(underlyingAttributeName, originalAttributeValue, newAttributeValue); + } + +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBeanTest.java new file mode 100644 index 0000000000..86eab0245e --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/ServerInformationMBeanTest.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.jmx.mbeans; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.apache.qpid.server.jmx.ManagedObjectRegistry; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Connection; +import org.apache.qpid.server.model.Statistics; + +import junit.framework.TestCase; + +public class ServerInformationMBeanTest extends TestCase +{ + private ManagedObjectRegistry _mockManagedObjectRegistry; + private Broker _mockBroker; + private Statistics _mockBrokerStatistics; + private ServerInformationMBean _mbean; + + @Override + protected void setUp() throws Exception + { + _mockManagedObjectRegistry = mock(ManagedObjectRegistry.class); + _mockBroker = mock(Broker.class); + _mockBrokerStatistics = mock(Statistics.class); + when(_mockBroker.getStatistics()).thenReturn(_mockBrokerStatistics); + + _mbean = new ServerInformationMBean(_mockManagedObjectRegistry, _mockBroker); + } + + public void testMBeanRegistersItself() throws Exception + { + ServerInformationMBean mbean = new ServerInformationMBean(_mockManagedObjectRegistry, _mockBroker); + verify(_mockManagedObjectRegistry).registerObject(mbean); + } + + /********** Statistics **********/ + + public void testGetMessageCount() throws Exception + { + assertStatistic("totalDataDelivered", 16384l, Connection.BYTES_OUT); + } + + /********** Attributes **********/ + + public void testBuildVersion() throws Exception + { + assertAttribute("buildVersion", "0.0.1", Broker.BUILD_VERSION); + } + + public void testProductVersion() throws Exception + { + assertAttribute("productVersion", "0.0.1", Broker.PRODUCT_VERSION); + } + + /********** Other Attributes **********/ + + public void testIsStatisticsEnabled() throws Exception + { + assertTrue("isStatisticsEnabled", _mbean.isStatisticsEnabled()); + } + + private void assertStatistic(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception + { + when(_mockBrokerStatistics.getStatistic(underlyingAttributeName)).thenReturn(expectedValue); + MBeanTestUtils.assertMBeanAttribute(_mbean, jmxAttributeName, expectedValue); + } + + private void assertAttribute(String jmxAttributeName, Object expectedValue, String underlyingAttributeName) throws Exception + { + when(_mockBroker.getAttribute(underlyingAttributeName)).thenReturn(expectedValue); + MBeanTestUtils.assertMBeanAttribute(_mbean, jmxAttributeName, expectedValue); + } +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/UserManagementMBeanTest.java new file mode 100644 index 0000000000..8ca6c521eb --- /dev/null +++ b/java/broker-plugins/management-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 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/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java new file mode 100644 index 0000000000..e3fac9f711 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java @@ -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. + * + */ +package org.apache.qpid.server.jmx.mbeans; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.Map; + +import javax.management.OperationsException; + +import junit.framework.TestCase; + +import org.apache.qpid.server.jmx.ManagedObjectRegistry; +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; + +public class VirtualHostManagerMBeanTest extends TestCase +{ + private static final String TEST_QUEUE_NAME = "QUEUE_NAME"; + private static final String TEST_EXCHANGE_NAME = "EXCHANGE_NAME"; + private static final String TEST_OWNER = "OWNER"; + private static final String TEST_DESCRIPTION = "DESCRIPTION"; + private static final String TEST_EXCHANGE_TYPE = "EXCHANGE_TYPE"; + + private static final Map EMPTY_ARGUMENT_MAP = Collections.emptyMap(); + + private VirtualHost _mockVirtualHost; + private ManagedObjectRegistry _mockManagedObjectRegistry; + private VirtualHostManagerMBean _virtualHostManagerMBean; + + @Override + protected void setUp() throws Exception + { + _mockVirtualHost = mock(VirtualHost.class); + when(_mockVirtualHost.getExchangeTypes()).thenReturn(Collections.singletonList(TEST_EXCHANGE_TYPE)); + + _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 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 arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_DESCRIPTION); + _virtualHostManagerMBean.createNewQueue(TEST_QUEUE_NAME, TEST_OWNER, true, arguments); + + Map expectedArguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_DESCRIPTION); + verify(_mockVirtualHost).createQueue(TEST_QUEUE_NAME, State.ACTIVE, true, false, LifetimePolicy.PERMANENT, 0, expectedArguments); + } + + public void testDeleteQueue() throws Exception + { + Queue mockQueue = mock(Queue.class); + when(mockQueue.getName()).thenReturn("queue1"); + when(_mockVirtualHost.getQueues()).thenReturn(Collections.singletonList(mockQueue)); + + _virtualHostManagerMBean.deleteQueue("queue1"); + verify(mockQueue).delete(); + } + + public void testDeleteQueueWhenQueueDoesNotExist() throws Exception + { + Queue mockQueue = mock(Queue.class); + when(mockQueue.getName()).thenReturn("queue1"); + when(_mockVirtualHost.getQueues()).thenReturn(Collections.singletonList(mockQueue)); + + try + { + _virtualHostManagerMBean.deleteQueue("unknownqueue"); + fail("Exception not thrown"); + } + catch(OperationsException oe) + { + // PASS + assertEquals("No such queue \"unknownqueue\"", oe.getMessage()); + } + verify(mockQueue, never()).delete(); + } + + public void testCreateNewDurableExchange() throws Exception + { + _virtualHostManagerMBean.createNewExchange(TEST_EXCHANGE_NAME, TEST_EXCHANGE_TYPE, true); + verify(_mockVirtualHost).createExchange(TEST_EXCHANGE_NAME, State.ACTIVE, true, LifetimePolicy.PERMANENT, 0, TEST_EXCHANGE_TYPE, EMPTY_ARGUMENT_MAP); + } + + public void testCreateNewExchangeWithUnknownExchangeType() throws Exception + { + String exchangeType = "notknown"; + try + { + _virtualHostManagerMBean.createNewExchange(TEST_EXCHANGE_NAME, exchangeType, true); + fail("Exception not thrown"); + } + catch (OperationsException oe) + { + // PASS + } + verify(_mockVirtualHost, never()).createExchange(TEST_EXCHANGE_NAME, State.ACTIVE, true, LifetimePolicy.PERMANENT, 0, exchangeType, EMPTY_ARGUMENT_MAP); + } + + public void testUnregisterExchange() throws Exception + { + Exchange mockExchange = mock(Exchange.class); + when(mockExchange.getName()).thenReturn("exchange1"); + when(_mockVirtualHost.getExchanges()).thenReturn(Collections.singletonList(mockExchange)); + + _virtualHostManagerMBean.unregisterExchange("exchange1"); + verify(mockExchange).delete(); + } + + public void testUnregisterExchangeWhenExchangeDoesNotExist() throws Exception + { + Exchange mockExchange = mock(Exchange.class); + when(mockExchange.getName()).thenReturn("exchange1"); + when(_mockVirtualHost.getExchanges()).thenReturn(Collections.singletonList(mockExchange)); + + try + { + _virtualHostManagerMBean.unregisterExchange("unknownexchange"); + fail("Exception not thrown"); + } + catch(OperationsException oe) + { + // PASS + assertEquals("No such exchange \"unknownexchange\"", oe.getMessage()); + } + + verify(mockExchange, never()).delete(); + } +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java new file mode 100644 index 0000000000..2c341b7f2e --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.systest.management.jmx; + +import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedExchange; +import org.apache.qpid.test.utils.JMXTestUtils; +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +import javax.management.MBeanException; +import javax.management.ObjectName; + +/** + * Tests the JMX API for the Managed Broker. + * + */ +public class BrokerManagementTest extends QpidBrokerTestCase +{ + private static final String VIRTUAL_HOST = "test"; + + /** + * JMX helper. + */ + private JMXTestUtils _jmxUtils; + private ManagedBroker _managedBroker; + + public void setUp() throws Exception + { + _jmxUtils = new JMXTestUtils(this); + _jmxUtils.setUp(); + super.setUp(); + _jmxUtils.open(); + _managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); + } + + public void tearDown() throws Exception + { + if (_jmxUtils != null) + { + _jmxUtils.close(); + } + super.tearDown(); + } + + /** + * Tests queue creation/deletion also verifying the automatic binding to the default exchange. + */ + public void testCreateQueueAndDeletion() throws Exception + { + final String queueName = getTestQueueName(); + final ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString()); + + // Check that bind does not exist before queue creation + assertFalse("Binding to " + queueName + " should not exist in default exchange before queue creation", + defaultExchange.bindings().containsKey(new String[] {queueName})); + + _managedBroker.createNewQueue(queueName, "testowner", true); + + // Ensure the queue exists + assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName)); + assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName)); + + // Now verify that the default exchange has been bound. + assertTrue("Binding to " + queueName + " should exist in default exchange after queue creation", + defaultExchange.bindings().containsKey(new String[] {queueName})); + + // Now delete the queue + _managedBroker.deleteQueue(queueName); + + // Finally ensure that the binding has been removed. + assertFalse("Binding to " + queueName + " should not exist in default exchange after queue deletion", + defaultExchange.bindings().containsKey(new String[] {queueName})); + } + + /** + * Tests exchange creation/deletion via JMX API. + */ + public void testCreateExchangeAndUnregister() throws Exception + { + String exchangeName = getTestName(); + _managedBroker.createNewExchange(exchangeName, "topic", true); + + ManagedExchange exchange = _jmxUtils.getManagedExchange(exchangeName); + assertNotNull("Exchange should exist", exchange); + + _managedBroker.unregisterExchange(exchangeName); + } + + /** + * Tests that it is disallowed to unregister the default exchange. + */ + public void testUnregisterOfDefaultExchangeDisallowed() throws Exception + { + String defaultExchangeName = ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString(); + + try + { + _managedBroker.unregisterExchange(defaultExchangeName); + fail("Exception not thrown"); + } + catch (MBeanException mbe) + { + // PASS + assertEquals("Error in unregistering exchange " + defaultExchangeName, mbe.getMessage()); + assertTrue(mbe.getCause().getMessage().contains("Cannot unregister the default exchange")); + } + final ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(defaultExchangeName); + assertNotNull("Exchange should exist", defaultExchange); + } + +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java new file mode 100644 index 0000000000..28d7bf4aed --- /dev/null +++ b/java/broker-plugins/management-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 connections = getManagedConnections(); + assertNotNull("Connection MBean is not found", connections); + assertEquals("Unexpected number of connection mbeans", 1, connections.size()); + final ManagedConnection mBean = connections.get(0); + assertNotNull("Connection MBean is null", mBean); + return mBean; + } + + private List getManagedConnections() + { + return _jmxUtils.getManagedConnections(VIRTUAL_HOST_NAME); + } + + private CompositeDataSupport getTheOneChannelRow(final ManagedConnection mBean) throws Exception + { + TabularData channelsData = getChannelsDataWithRetry(mBean); + + assertEquals("Unexpected number of rows in channel table", 1, channelsData.size()); + + @SuppressWarnings("unchecked") + final Iterator rowItr = (Iterator) channelsData.values().iterator(); + final CompositeDataSupport row = rowItr.next(); + return row; + } + + private void receiveMessagesWithoutCommit(final MessageConsumer consumer, int numberOfMessages) throws Exception + { + for (int i = 0; i < numberOfMessages; i++) + { + final Message m = consumer.receive(1000l); + assertNotNull("Message " + i + " is not received", m); + } + } + + private TabularData getChannelsDataWithRetry(final ManagedConnection mBean) + throws IOException, JMException + { + TabularData channelsData = mBean.channels(); + int retries = 0; + while(channelsData.size() == 0 && retries < 5) + { + sleep(); + channelsData = mBean.channels(); + retries++; + } + return channelsData; + } + + private void sleep() + { + try + { + Thread.sleep(50); + } + catch (InterruptedException ie) + { + Thread.currentThread().interrupt(); + } + }} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java new file mode 100644 index 0000000000..ac6730638e --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.systest.management.jmx; + +import java.io.File; +import java.util.List; + +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.TabularData; + +import org.apache.qpid.management.common.mbeans.LoggingManagement; +import org.apache.qpid.server.jmx.mbeans.LoggingManagementMBeanTest; +import org.apache.qpid.server.logging.log4j.LoggingFacadeTest; +import org.apache.qpid.test.utils.JMXTestUtils; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.util.FileUtils; +import org.apache.qpid.util.LogMonitor; + +/** + * System test for Logging Management. These tests rely on value set within + * test-profiles/log4j-test.xml. + * + * @see LoggingManagementMBeanTest + * @see LoggingFacadeTest + * + */ +public class LoggingManagementTest extends QpidBrokerTestCase +{ + private JMXTestUtils _jmxUtils; + private LoggingManagement _loggingManagement; + private LogMonitor _monitor; + + public void setUp() throws Exception + { + _jmxUtils = new JMXTestUtils(this); + _jmxUtils.setUp(); + + // System test normally run with log for4j test config from beneath test-profiles. We need to + // copy it as some of our tests write to this file. + + File tmpLogFile = File.createTempFile("log4j" + "." + getName(), ".xml"); + tmpLogFile.deleteOnExit(); + FileUtils.copy(_logConfigFile, tmpLogFile); + + _logConfigFile = tmpLogFile; + + super.setUp(); + _jmxUtils.open(); + + _loggingManagement = _jmxUtils.getLoggingManagement(); + _monitor = new LogMonitor(_outputFile); + } + + public void tearDown() throws Exception + { + try + { + if (_jmxUtils != null) + { + _jmxUtils.close(); + } + } + finally + { + super.tearDown(); + } + } + + public void testViewEffectiveRuntimeLoggerLevels() throws Exception + { + final String qpidMainLogger = "org.apache.qpid"; + + TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels(); + final CompositeData row = table.get(new String[] {qpidMainLogger} ); + assertChannelRow(row, qpidMainLogger, "DEBUG"); + } + + public void testViewConfigFileLoggerLevels() throws Exception + { + final String operationalLoggingLogger = "qpid.message"; + + TabularData table = _loggingManagement.viewConfigFileLoggerLevels(); + final CompositeData row = table.get(new String[] {operationalLoggingLogger} ); + assertChannelRow(row, operationalLoggingLogger, "INFO"); + } + + public void testTurnOffOrgApacheQpidAtRuntime() throws Exception + { + final String logger = "org.apache.qpid"; + _monitor.markDiscardPoint(); + _loggingManagement.setRuntimeLoggerLevel(logger, "OFF"); + + List matches = _monitor.findMatches("Setting level to OFF for logger 'org.apache.qpid'"); + assertEquals(1, matches.size()); + + TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels(); + final CompositeData row1 = table.get(new String[] {logger} ); + assertChannelRow(row1, logger, "OFF"); + } + + public void testChangesToConfigFileBecomeEffectiveAfterReload() throws Exception + { + final String operationalLoggingLogger = "qpid.message"; + assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO"); + + _monitor.markDiscardPoint(); + _loggingManagement.setConfigFileLoggerLevel(operationalLoggingLogger, "OFF"); + + List matches = _monitor.findMatches("Setting level to OFF for logger 'qpid.message'"); + assertEquals(1, matches.size()); + + assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO"); + + _loggingManagement.reloadConfigFile(); + + assertEffectiveLoggingLevel(operationalLoggingLogger, "OFF"); + } + + private void assertEffectiveLoggingLevel(String operationalLoggingLogger, String expectedLevel) + { + TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels(); + final CompositeData row1 = table.get(new String[] {operationalLoggingLogger} ); + assertChannelRow(row1, operationalLoggingLogger, expectedLevel); + } + + private void assertChannelRow(final CompositeData row, String logger, String level) + { + assertNotNull("No row for " + logger, row); + assertEquals("Unexpected logger name", logger, row.get(LoggingManagement.LOGGER_NAME)); + assertEquals("Unexpected level", level, row.get(LoggingManagement.LOGGER_LEVEL)); + } + +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java new file mode 100644 index 0000000000..47b38381c5 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java @@ -0,0 +1,480 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.systest.management.jmx; + +import org.apache.qpid.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedConnection; +import org.apache.qpid.management.common.mbeans.ManagedExchange; +import org.apache.qpid.server.logging.AbstractTestLogging; +import org.apache.qpid.server.logging.subjects.AbstractTestLogSubject; +import org.apache.qpid.test.utils.JMXTestUtils; + +import javax.jms.Connection; +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import javax.management.JMException; +import java.io.IOException; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Test class to test if any change in the broker JMX code is affesting the management console + * There are some hardcoding of management feature names and parameter names to create a customized + * look in the console. + */ +public class ManagementActorLoggingTest extends AbstractTestLogging +{ + private JMXTestUtils _jmxUtils; + private boolean _closed = false; + + @Override + public void setUp() throws Exception + { + _jmxUtils = new JMXTestUtils(this); + _jmxUtils.setUp(); + super.setUp(); + _jmxUtils.open(); + } + + @Override + public void tearDown() throws Exception + { + if(!_closed) + { + _jmxUtils.close(); + } + super.tearDown(); + } + + /** + * Description: + * When a connected client has its connection closed via the Management Console this will be logged as a CON-1002 message. + * Input: + * + * 1. Running Broker + * 2. Connected Client + * 3. Connection is closed via Management Console + * Output: + * + * CON-1002 : Close + * + * Validation Steps: + * 4. The CON ID is correct + * 5. This must be the last CON message for the Connection + * 6. It must be preceded by a CON-1001 for this Connection + * + * @throws Exception - {@see ManagedConnection.closeConnection and #getConnection} + * @throws java.io.IOException - if there is a problem reseting the log monitor + */ + public void testConnectionCloseViaManagement() throws IOException, Exception + { + //Create a connection to the broker + Connection connection = getConnection(); + + // Monitor the connection for an exception being thrown + // this should be a DisconnectionException but it is not this tests + // job to valiate that. Only use the exception as a synchronisation + // to check the log file for the Close message + final CountDownLatch exceptionReceived = new CountDownLatch(1); + connection.setExceptionListener(new ExceptionListener() + { + public void onException(JMSException e) + { + //Failover being attempted. + exceptionReceived.countDown(); + } + }); + + //Remove the connection close from any 0-10 connections + _monitor.markDiscardPoint(); + + // Get a managedConnection + ManagedConnection mangedConnection = _jmxUtils.getManagedObject(ManagedConnection.class, "org.apache.qpid:type=VirtualHost.Connection,*"); + + //Close the connection + mangedConnection.closeConnection(); + + //Wait for the connection to close + assertTrue("Timed out waiting for conneciton to report close", + exceptionReceived.await(2, TimeUnit.SECONDS)); + + //Validate results + List results = waitAndFindMatches("CON-1002"); + + assertEquals("Unexpected Connection Close count", 1, results.size()); + } + + /** + * Description: + * Exchange creation is possible from the Management Console. + * When an exchanged is created in this way then a EXH-1001 create message + * is expected to be logged. + * Input: + * + * 1. Running broker + * 2. Connected Management Console + * 3. Exchange Created via Management Console + * Output: + * + * EXH-1001 : Create : [Durable] Type: Name: + * + * Validation Steps: + * 4. The EXH ID is correct + * 5. The correct tags are present in the message based on the create options + * + * @throws java.io.IOException - if there is a problem reseting the log monitor + * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue} + */ + public void testCreateExchangeDirectTransientViaManagementConsole() throws IOException, JMException + { + _monitor.markDiscardPoint(); + + _jmxUtils.createExchange("test", getName(), "direct", false); + + // Validate + + //1 - ID is correct + List results = waitAndFindMatches("EXH-1001"); + + assertEquals("More than one exchange creation found", 1, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct exchange name + assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + } + + public void testCreateExchangeTopicTransientViaManagementConsole() throws IOException, JMException + { + //Remove any previous exchange declares + _monitor.markDiscardPoint(); + + _jmxUtils.createExchange("test", getName(), "topic", false); + + // Validate + + //1 - ID is correct + List results = waitAndFindMatches("EXH-1001"); + + assertEquals("More than one exchange creation found", 1, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct exchange name + assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + + } + + public void testCreateExchangeFanoutTransientViaManagementConsole() throws IOException, JMException + { + //Remove any previous exchange declares + _monitor.markDiscardPoint(); + + _jmxUtils.createExchange("test", getName(), "fanout", false); + + // Validate + + //1 - ID is correct + List results = waitAndFindMatches("EXH-1001"); + + assertEquals("More than one exchange creation found", 1, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct exchange name + assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + + } + + public void testCreateExchangeHeadersTransientViaManagementConsole() throws IOException, JMException + { + //Remove any previous exchange declares + _monitor.markDiscardPoint(); + + _jmxUtils.createExchange("test", getName(), "headers", false); + + // Validate + + //1 - ID is correct + List results = waitAndFindMatches("EXH-1001"); + + assertEquals("More than one exchange creation found", 1, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct exchange name + assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + + } + + /** + * Description: + * Queue creation is possible from the Management Console. When a queue is created in this way then a QUE-1001 create message is expected to be logged. + * Input: + * + * 1. Running broker + * 2. Connected Management Console + * 3. Queue Created via Management Console + * Output: + * + * QUE-1001 : Create : Transient Owner: + * + * Validation Steps: + * 4. The QUE ID is correct + * 5. The correct tags are present in the message based on the create options + * + * @throws java.io.IOException - if there is a problem reseting the log monitor + * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue} + */ + public void testCreateQueueTransientViaManagementConsole() throws IOException, JMException + { + //Remove any previous queue declares + _monitor.markDiscardPoint(); + + _jmxUtils.createQueue("test", getName(), null, false); + + // Validate + + List results = waitAndFindMatches("QUE-1001"); + + assertEquals("More than one queue creation found", 1, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct queue name + String subject = fromSubject(log); + assertEquals("Incorrect queue name created", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + } + + /** + * Description: + * The ManagementConsole can be used to delete a queue. When this is done a QUE-1002 Deleted message must be logged. + * Input: + * + * 1. Running Broker + * 2. Queue created on the broker with no subscribers + * 3. Management Console connected + * 4. Queue is deleted via Management Console + * Output: + * + * QUE-1002 : Deleted + * + * Validation Steps: + * 5. The QUE ID is correct + * + * @throws java.io.IOException - if there is a problem reseting the log monitor + * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue} + */ + public void testQueueDeleteViaManagementConsole() throws IOException, JMException + { + //Remove any previous queue declares + _monitor.markDiscardPoint(); + + _jmxUtils.createQueue("test", getName(), null, false); + + ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test"); + + managedBroker.deleteQueue(getName()); + + List results = waitAndFindMatches("QUE-1002"); + + assertEquals("More than one queue deletion found", 1, results.size()); + + String log = getLog(results.get(0)); + + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect queue named in delete", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + + } + + /** + * Description: + * The binding of a Queue and an Exchange is done via a Binding. When this Binding is created via the Management Console a BND-1001 Create message will be logged. + * Input: + * + * 1. Running Broker + * 2. Connected Management Console + * 3. Use Management Console to perform binding + * Output: + * + * BND-1001 : Create + * + * Validation Steps: + * 4. The BND ID is correct + * 5. This will be the first message for the given binding + * + * @throws java.io.IOException - if there is a problem reseting the log monitor + * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.createNewBinding} + */ + public void testBindingCreateOnDirectViaManagementConsole() throws IOException, JMException + { + //Remove any previous queue declares + _monitor.markDiscardPoint(); + + _jmxUtils.createQueue("test", getName(), null, false); + + ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.direct"); + + managedExchange.createNewBinding(getName(), getName()); + + List results = waitAndFindMatches("BND-1001"); + + assertEquals("Unexpected number of bindings logged", 2, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + } + + public void testBindingCreateOnTopicViaManagementConsole() throws IOException, JMException + { + //Remove any previous queue declares + _monitor.markDiscardPoint(); + + _jmxUtils.createQueue("test", getName(), null, false); + + ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.topic"); + + managedExchange.createNewBinding(getName(), getName()); + + List results = waitAndFindMatches("BND-1001"); + + assertEquals("Unexpected number of bindings logged", 2, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + } + + public void testBindingCreateOnFanoutViaManagementConsole() throws IOException, JMException + { + //Remove any previous queue declares + _monitor.markDiscardPoint(); + + _jmxUtils.createQueue("test", getName(), null, false); + + ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.fanout"); + + managedExchange.createNewBinding(getName(), getName()); + + List results = waitAndFindMatches("BND-1001"); + + assertEquals("Unexpected number of bindings logged", 2, results.size()); + + String log = getLogMessage(results, 0); + + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); + assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + } + + /** + * Description: + * Bindings can be deleted so that a queue can be rebound with a different set of values. This can be performed via the Management Console + * Input: + * + * 1. Running Broker + * 2. Management Console connected + * 3. Management Console is used to perform unbind. + * Output: + * + * BND-1002 : Deleted + * + * Validation Steps: + * 4. The BND ID is correct + * 5. There must have been a BND-1001 Create message first. + * 6. This will be the last message for the given binding + * + * @throws java.io.IOException - if there is a problem reseting the log monitor or an issue with the JMX Connection + * @throws javax.management.JMException - {@see #createExchange and ManagedBroker.unregisterExchange} + */ + public void testUnRegisterExchangeViaManagementConsole() throws IOException, JMException + { + //Remove any previous queue declares + _monitor.markDiscardPoint(); + + _jmxUtils.createExchange("test", getName(), "direct", false); + + ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test"); + + managedBroker.unregisterExchange(getName()); + + List results = waitAndFindMatches("EXH-1002"); + + assertEquals("More than one exchange deletion found", 1, results.size()); + + String log = getLog(results.get(0)); + + // Validate correct binding + String subject = fromSubject(log); + assertEquals("Incorrect exchange named in delete", "direct/" + getName(), AbstractTestLogSubject.getSlice("ex", subject)); + + // Validate it was a management actor. + String actor = fromActor(log); + assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); + } + +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java new file mode 100644 index 0000000000..6100d5a23e --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java @@ -0,0 +1,317 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.systest.management.jmx; + + +import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.logging.AbstractTestLogging; +import org.apache.qpid.test.utils.JMXTestUtils; +import org.apache.qpid.util.LogMonitor; + +import java.io.File; +import java.util.List; + +/** + * Management Console Test Suite + * + * The Management Console test suite validates that the follow log messages as specified in the Functional Specification. + * + * This suite of tests validate that the management console messages occur correctly and according to the following format: + * + * MNG-1001 : Startup + * MNG-1002 : Starting : : Listening on port + * MNG-1003 : Shutting down : : port + * MNG-1004 : Ready + * MNG-1005 : Stopped + * MNG-1006 : Using SSL Keystore : + * MNG-1007 : Open : User + * MNG-1008 : Close : User + */ +public class ManagementLoggingTest extends AbstractTestLogging +{ + private static final String MNG_PREFIX = "MNG-"; + + public void setUp() throws Exception + { + setLogMessagePrefix(); + + // We either do this here or have a null check in tearDown. + // As when this test is run against profiles other than java it will NPE + _monitor = new LogMonitor(_outputFile); + //We explicitly do not call super.setUp as starting up the broker is + //part of the test case. + + } + + /** + * Description: + * Using the startup configuration validate that the management startup + * message is logged correctly. + * Input: + * Standard configuration with management enabled + * Output: + * + * MNG-1001 : Startup + * + * Constraints: + * This is the FIRST message logged by MNG + * Validation Steps: + * + * 1. The BRK ID is correct + * 2. This is the FIRST message logged by MNG + */ + public void testManagementStartupEnabled() throws Exception + { + // This test only works on java brokers + if (isJavaBroker()) + { + startBrokerAndCreateMonitor(true, false); + + // Ensure we have received the MNG log msg. + waitForMessage("MNG-1001"); + + List results = findMatches(MNG_PREFIX); + // Validation + + assertTrue("MNGer message not logged", results.size() > 0); + + String log = getLogMessage(results, 0); + + //1 + validateMessageID("MNG-1001", log); + + //2 + //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J) + results = findMatches("MNG-1001"); + assertEquals("Unexpected startup message count.", + 2, results.size()); + + //3 + assertEquals("Startup log message is not 'Startup'.", "Startup", + getMessageString(log)); + } + } + + /** + * Description: + * Verify that when management is disabled in the configuration file the + * startup message is not logged. + * Input: + * Standard configuration with management disabled + * Output: + * NO MNG messages + * Validation Steps: + * + * 1. Validate that no MNG messages are produced. + */ + public void testManagementStartupDisabled() throws Exception + { + if (isJavaBroker()) + { + startBrokerAndCreateMonitor(false, false); + + List results = findMatches(MNG_PREFIX); + // Validation + + assertEquals("MNGer messages logged", 0, results.size()); + } + } + + /** + * The two MNG-1002 messages are logged at the same time so lets test them + * at the same time. + * + * Description: + * Using the default configuration validate that the RMI Registry socket is + * correctly reported as being opened + * + * Input: + * The default configuration file + * Output: + * + * MESSAGE MNG-1002 : Starting : RMI Registry : Listening on port 8999 + * + * Constraints: + * The RMI ConnectorServer and Registry log messages do not have a prescribed order + * Validation Steps: + * + * 1. The MNG ID is correct + * 2. The specified port is the correct '8999' + * + * Description: + * Using the default configuration validate that the RMI ConnectorServer + * socket is correctly reported as being opened + * + * Input: + * The default configuration file + * Output: + * + * MESSAGE MNG-1002 : Starting : RMI ConnectorServer : Listening on port 9099 + * + * Constraints: + * The RMI ConnectorServer and Registry log messages do not have a prescribed order + * Validation Steps: + * + * 1. The MNG ID is correct + * 2. The specified port is the correct '9099' + */ + public void testManagementStartupRMIEntries() throws Exception + { + if (isJavaBroker()) + { + startBrokerAndCreateMonitor(true, false); + + List results = waitAndFindMatches("MNG-1002"); + // Validation + + //There will be 4 startup messages (two via SystemOut, and two via Log4J) + assertEquals("Unexpected MNG-1002 message count", 4, results.size()); + + String log = getLogMessage(results, 0); + + //1 + validateMessageID("MNG-1002", log); + + //Check the RMI Registry port is as expected + int mPort = getManagementPort(getPort()); + assertTrue("RMI Registry port not as expected(" + mPort + ").:" + getMessageString(log), + getMessageString(log).endsWith(String.valueOf(mPort))); + + log = getLogMessage(results, 2); + + //1 + validateMessageID("MNG-1002", log); + + // We expect the RMI Registry port (the defined 'management port') to be + // 100 lower than the JMX RMIConnector Server Port (the actual JMX server) + int jmxPort = mPort + ServerConfiguration.JMXPORT_CONNECTORSERVER_OFFSET; + assertTrue("JMX RMIConnectorServer port not as expected(" + jmxPort + ").:" + getMessageString(log), + getMessageString(log).endsWith(String.valueOf(jmxPort))); + } + } + + /** + * Description: + * Using the default configuration with SSL enabled for the management port the SSL Keystore path should be reported via MNG-1006 + * Input: + * Management SSL enabled default configuration. + * Output: + * + * MESSAGE MNG-1006 : Using SSL Keystore : test_resources/ssl/keystore.jks + * + * Validation Steps: + * + * 1. The MNG ID is correct + * 2. The keystore path is as specified in the configuration + */ + public void testManagementStartupSSLKeystore() throws Exception + { + if (isJavaBroker()) + { + startBrokerAndCreateMonitor(true, true); + + List results = waitAndFindMatches("MNG-1006"); + + assertTrue("MNGer message not logged", results.size() > 0); + + String log = getLogMessage(results, 0); + + //1 + validateMessageID("MNG-1006", log); + + // Validate we only have two MNG-1002 (one via stdout, one via log4j) + results = findMatches("MNG-1006"); + assertEquals("Upexpected SSL Keystore message count", + 2, results.size()); + + // Validate the keystore path is as expected + assertTrue("SSL Keystore entry expected.:" + getMessageString(log), + getMessageString(log).endsWith(new File(getConfigurationStringProperty("management.ssl.keyStorePath")).getName())); + } + } + + /** + * Description: Tests the management connection open/close are logged correctly. + * + * Output: + * + * MESSAGE MNG-1007 : Open : User + * MESSAGE MNG-1008 : Close : User + * + * Validation Steps: + * + * 1. The MNG ID is correct + * 2. The message and username are correct + */ + public void testManagementUserOpenClose() throws Exception + { + if (isJavaBroker()) + { + startBrokerAndCreateMonitor(true, false); + + final JMXTestUtils jmxUtils = new JMXTestUtils(this); + List openResults = null; + List closeResults = null; + try + { + jmxUtils.setUp(); + jmxUtils.open(); + openResults = waitAndFindMatches("MNG-1007"); + } + finally + { + if (jmxUtils != null) + { + jmxUtils.close(); + closeResults = waitAndFindMatches("MNG-1008"); + } + } + + assertNotNull("Management Open results null", openResults.size()); + assertEquals("Management Open logged unexpected number of times", 1, openResults.size()); + + assertNotNull("Management Close results null", closeResults.size()); + assertEquals("Management Close logged unexpected number of times", 1, closeResults.size()); + + final String openMessage = getMessageString(getLogMessage(openResults, 0)); + assertTrue("Unexpected open message " + openMessage, openMessage.endsWith("Open : User admin")); + final String closeMessage = getMessageString(getLogMessage(closeResults, 0)); + assertTrue("Unexpected close message " + closeMessage, closeMessage.endsWith("Close : User admin")); + } + } + + private void startBrokerAndCreateMonitor(boolean managementEnabled, boolean useManagementSSL) throws Exception + { + //Ensure management is on + setConfigurationProperty("management.enabled", String.valueOf(managementEnabled)); + + if(useManagementSSL) + { + // This test requires we have an ssl connection + setConfigurationProperty("management.ssl.enabled", "true"); + } + + startBroker(); + + // Now we can create the monitor as _outputFile will now be defined + _monitor = new LogMonitor(_outputFile); + } +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java new file mode 100644 index 0000000000..8ae4fec975 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java @@ -0,0 +1,614 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.systest.management.jmx; + +import org.apache.commons.lang.time.FastDateFormat; + +import org.apache.log4j.Logger; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.configuration.ClientProperties; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedQueue; +import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.NotificationCheckTest; +import org.apache.qpid.server.queue.SimpleAMQQueueTest; +import org.apache.qpid.test.client.destination.AddressBasedDestinationTest; +import org.apache.qpid.test.utils.JMXTestUtils; +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.Queue; +import javax.jms.Session; +import javax.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; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Tests the JMX API for the Managed Queue. + * + */ +public class QueueManagementTest extends QpidBrokerTestCase +{ + + private static final Logger LOGGER = Logger.getLogger(QueueManagementTest.class); + + private static final String VIRTUAL_HOST = "test"; + private static final String TEST_QUEUE_DESCRIPTION = "my description"; + + private JMXTestUtils _jmxUtils; + private Connection _connection; + private Session _session; + + private String _sourceQueueName; + private String _destinationQueueName; + private Destination _sourceQueue; + private Destination _destinationQueue; + private ManagedQueue _managedSourceQueue; + private ManagedQueue _managedDestinationQueue; + + + public void setUp() throws Exception + { + _jmxUtils = new JMXTestUtils(this); + _jmxUtils.setUp(); + + super.setUp(); + _sourceQueueName = getTestQueueName() + "_src"; + _destinationQueueName = getTestQueueName() + "_dest"; + + _connection = getConnection(); + _connection.start(); + + _session = _connection.createSession(true, Session.SESSION_TRANSACTED); + _sourceQueue = _session.createQueue(_sourceQueueName); + _destinationQueue = _session.createQueue(_destinationQueueName); + createQueueOnBroker(_sourceQueue); + createQueueOnBroker(_destinationQueue); + + _jmxUtils.open(); + + _managedSourceQueue = _jmxUtils.getManagedQueue(_sourceQueueName); + _managedDestinationQueue = _jmxUtils.getManagedQueue(_destinationQueueName); + } + + public void tearDown() throws Exception + { + if (_jmxUtils != null) + { + _jmxUtils.close(); + } + super.tearDown(); + } + + public void testQueueAttributes() throws Exception + { + Queue queue = _session.createQueue(getTestQueueName()); + createQueueOnBroker(queue); + + final String queueName = queue.getQueueName(); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals("Unexpected name", queueName, managedQueue.getName()); + assertEquals("Unexpected queue type", "standard", managedQueue.getQueueType()); + } + + public void testExclusiveQueueHasJmsClientIdAsOwner() throws Exception + { + Queue tmpQueue = _session.createTemporaryQueue(); + + final String queueName = tmpQueue.getQueueName(); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertNotNull(_connection.getClientID()); + assertEquals("Unexpected owner", _connection.getClientID(), managedQueue.getOwner()); + } + + public void testNonExclusiveQueueHasNoOwner() throws Exception + { + Queue nonExclusiveQueue = _session.createQueue(getTestQueueName()); + createQueueOnBroker(nonExclusiveQueue); + + final String queueName = nonExclusiveQueue.getQueueName(); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertNull("Unexpected owner", managedQueue.getOwner()); + } + + public void testSetNewQueueDescriptionOnExistingQueue() throws Exception + { + Queue queue = _session.createQueue(getTestQueueName()); + createQueueOnBroker(queue); + + final String queueName = queue.getQueueName(); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertNull("Unexpected description", managedQueue.getDescription()); + + managedQueue.setDescription(TEST_QUEUE_DESCRIPTION); + assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); + } + + public void testNewQueueWithDescription() throws Exception + { + String queueName = getTestQueueName(); + Map arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION); + ((AMQSession)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); + } + + /** + * Requires persistent store. + */ + public void testQueueDescriptionSurvivesRestart() throws Exception + { + String queueName = getTestQueueName(); + Map arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION); + + ((AMQSession)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments); + + ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); + + restartBroker(); + + managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); + } + + /** + * Tests queue creation with {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument. Also tests + * that the attribute is exposed correctly through {@link ManagedQueue#getMaximumDeliveryCount()}. + */ + public void testCreateQueueWithMaximumDeliveryCountSet() throws Exception + { + final String queueName = getName(); + final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); + + final Integer deliveryCount = 1; + final Map arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, (Object)deliveryCount); + managedBroker.createNewQueue(queueName, null, true, arguments); + + // Ensure the queue exists + assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName("test", queueName)); + assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName)); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals("Unexpected maximum delivery count", deliveryCount, managedQueue.getMaximumDeliveryCount()); + } + + /** + * Requires 0-10 as relies on ADDR addresses. + * @see AddressBasedDestinationTest for the testing of message routing to the alternate exchange + */ + public void testGetSetAlternateExchange() throws Exception + { + String queueName = getTestQueueName(); + String altExchange = "amq.fanout"; + String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange); + Queue queue = _session.createQueue(addrWithAltExch); + + createQueueOnBroker(queue); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange()); + + String newAltExch = "amq.topic"; + managedQueue.setAlternateExchange(newAltExch); + assertEquals("Unexpected alternate exchange after set", newAltExch, managedQueue.getAlternateExchange()); + } + + /** + * Requires 0-10 as relies on ADDR addresses. + */ + public void testRemoveAlternateExchange() throws Exception + { + String queueName = getTestQueueName(); + String altExchange = "amq.fanout"; + String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange); + Queue queue = _session.createQueue(addrWithAltExch); + + createQueueOnBroker(queue); + + final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange()); + + managedQueue.setAlternateExchange(""); + assertNull("Unexpected alternate exchange after set", managedQueue.getAlternateExchange()); + } + + /** + * Requires persistent store + * Requires 0-10 as relies on ADDR addresses. + */ + public void testAlternateExchangeSurvivesRestart() throws Exception + { + String nonMandatoryExchangeName = "exch" + getName(); + + final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); + managedBroker.createNewExchange(nonMandatoryExchangeName, "fanout", true); + + String queueName1 = getTestQueueName() + "1"; + String altExchange1 = "amq.fanout"; + String addr1WithAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName1, altExchange1); + Queue queue1 = _session.createQueue(addr1WithAltExch); + + String queueName2 = getTestQueueName() + "2"; + String addr2WithoutAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue}}", queueName2); + Queue queue2 = _session.createQueue(addr2WithoutAltExch); + + createQueueOnBroker(queue1); + createQueueOnBroker(queue2); + + ManagedQueue managedQueue1 = _jmxUtils.getManagedQueue(queueName1); + assertEquals("Newly created queue1 does not have expected alternate exchange", altExchange1, managedQueue1.getAlternateExchange()); + + ManagedQueue managedQueue2 = _jmxUtils.getManagedQueue(queueName2); + assertNull("Newly created queue2 does not have expected alternate exchange", managedQueue2.getAlternateExchange()); + + String altExchange2 = nonMandatoryExchangeName; + managedQueue2.setAlternateExchange(altExchange2); + + restartBroker(); + + managedQueue1 = _jmxUtils.getManagedQueue(queueName1); + assertEquals("Queue1 does not have expected alternate exchange after restart", altExchange1, managedQueue1.getAlternateExchange()); + + managedQueue2 = _jmxUtils.getManagedQueue(queueName2); + assertEquals("Queue2 does not have expected updated alternate exchange after restart", altExchange2, managedQueue2.getAlternateExchange()); + } + + /** + * Tests the ability to receive queue alerts as JMX notifications. + * + * @see NotificationCheckTest + * @see SimpleAMQQueueTest#testNotificationFiredAsync() + * @see SimpleAMQQueueTest#testNotificationFiredOnEnqueue() + */ + public void testQueueNotification() throws Exception + { + final String queueName = getName(); + final long maximumMessageCount = 3; + + Queue queue = _session.createQueue(queueName); + createQueueOnBroker(queue); + + ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); + managedQueue.setMaximumMessageCount(maximumMessageCount); + + RecordingNotificationListener listener = new RecordingNotificationListener(1); + + _jmxUtils.addNotificationListener(_jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName), listener, null, null); + + // Send two messages - this should *not* trigger the notification + sendMessage(_session, queue, 2); + + assertEquals("Premature notification received", 0, listener.getNumberOfNotificationsReceived()); + + // A further message should trigger the message count alert + sendMessage(_session, queue, 1); + + listener.awaitExpectedNotifications(5, TimeUnit.SECONDS); + + assertEquals("Unexpected number of JMX notifications received", 1, listener.getNumberOfNotificationsReceived()); + + Notification notification = listener.getLastNotification(); + assertEquals("Unexpected notification message", "MESSAGE_COUNT_ALERT 3: Maximum count on queue threshold (3) breached.", notification.getMessage()); + } + + /** + * Tests {@link ManagedQueue#viewMessages(long, long)} interface. + */ + public void testViewSingleMessage() throws Exception + { + final List sentMessages = sendMessage(_session, _sourceQueue, 1); + syncSession(_session); + final Message sentMessage = sentMessages.get(0); + + assertEquals("Unexpected queue depth", 1, _managedSourceQueue.getMessageCount().intValue()); + + // Check the contents of the message + final TabularData tab = _managedSourceQueue.viewMessages(1l, 1l); + assertEquals("Unexpected number of rows in table", 1, tab.size()); + final Iterator rowItr = (Iterator) tab.values().iterator(); + + final CompositeData row1 = rowItr.next(); + assertNotNull("Message should have AMQ message id", row1.get(ManagedQueue.MSG_AMQ_ID)); + assertEquals("Unexpected queue position", 1l, row1.get(ManagedQueue.MSG_QUEUE_POS)); + assertEquals("Unexpected redelivered flag", Boolean.FALSE, row1.get(ManagedQueue.MSG_REDELIVERED)); + + // Check the contents of header (encoded in a string array) + final String[] headerArray = (String[]) row1.get(ManagedQueue.MSG_HEADER); + assertNotNull("Expected message header array", headerArray); + final Map headers = headerArrayToMap(headerArray); + + final String expectedJMSMessageID = isBroker010() ? sentMessage.getJMSMessageID().replace("ID:", "") : sentMessage.getJMSMessageID(); + final String expectedFormattedJMSTimestamp = FastDateFormat.getInstance(ManagedQueue.JMSTIMESTAMP_DATETIME_FORMAT).format(sentMessage.getJMSTimestamp()); + assertEquals("Unexpected JMSMessageID within header", expectedJMSMessageID, headers.get("JMSMessageID")); + assertEquals("Unexpected JMSPriority within header", String.valueOf(sentMessage.getJMSPriority()), headers.get("JMSPriority")); + assertEquals("Unexpected JMSTimestamp within header", expectedFormattedJMSTimestamp, headers.get("JMSTimestamp")); + } + + /** + * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface. + */ + public void testMoveMessagesBetweenQueues() throws Exception + { + final int numberOfMessagesToSend = 10; + + sendMessage(_session, _sourceQueue, numberOfMessagesToSend); + syncSession(_session); + assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); + + // Move first three messages to destination + long fromMessageId = amqMessagesIds.get(0); + long toMessageId = amqMessagesIds.get(2); + _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); + + assertEquals("Unexpected queue depth on destination queue after first move", 3, _managedDestinationQueue.getMessageCount().intValue()); + assertEquals("Unexpected queue depth on source queue after first move", 7, _managedSourceQueue.getMessageCount().intValue()); + + // Now move a further two messages to destination + fromMessageId = amqMessagesIds.get(7); + toMessageId = amqMessagesIds.get(8); + _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); + assertEquals("Unexpected queue depth on destination queue after second move", 5, _managedDestinationQueue.getMessageCount().intValue()); + assertEquals("Unexpected queue depth on source queue after second move", 5, _managedSourceQueue.getMessageCount().intValue()); + + assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8); + } + + /** + * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface. + */ + public void testCopyMessagesBetweenQueues() throws Exception + { + final int numberOfMessagesToSend = 10; + sendMessage(_session, _sourceQueue, numberOfMessagesToSend); + syncSession(_session); + assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); + + // Copy first three messages to destination + long fromMessageId = amqMessagesIds.get(0); + long toMessageId = amqMessagesIds.get(2); + _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName); + + assertEquals("Unexpected queue depth on destination queue after first copy", 3, _managedDestinationQueue.getMessageCount().intValue()); + assertEquals("Unexpected queue depth on source queue after first copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + // Now copy a further two messages to destination + fromMessageId = amqMessagesIds.get(7); + toMessageId = amqMessagesIds.get(8); + _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName); + assertEquals("Unexpected queue depth on destination queue after second copy", 5, _managedDestinationQueue.getMessageCount().intValue()); + assertEquals("Unexpected queue depth on source queue after second copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8); + } + + public void testMoveMessagesBetweenQueuesWithActiveConsumerOnSourceQueue() throws Exception + { + setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString()); + Connection asyncConnection = getConnection(); + asyncConnection.start(); + + final int numberOfMessagesToSend = 50; + sendMessage(_session, _sourceQueue, numberOfMessagesToSend); + syncSession(_session); + assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); + + long fromMessageId = amqMessagesIds.get(0); + long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1); + + CountDownLatch consumerReadToHalfwayLatch = new CountDownLatch(numberOfMessagesToSend / 2); + AtomicInteger totalConsumed = new AtomicInteger(0); + startAsyncConsumerOn(_sourceQueue, asyncConnection, consumerReadToHalfwayLatch, totalConsumed); + + boolean halfwayPointReached = consumerReadToHalfwayLatch.await(5000, TimeUnit.MILLISECONDS); + assertTrue("Did not read half of messages within time allowed", halfwayPointReached); + + _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); + + asyncConnection.stop(); + + // The exact number of messages moved will be non deterministic, as the number of messages processed + // by the consumer cannot be predicted. There is also the possibility that a message can remain + // on the source queue. This situation will arise if a message has been acquired by the consumer, but not + // yet delivered to the client application (i.e. MessageListener#onMessage()) when the Connection#stop() occurs. + // + // The number of messages moved + the number consumed + any messages remaining on source should + // *always* be equal to the number we originally sent. + + int numberOfMessagesReadByConsumer = totalConsumed.intValue(); + int numberOfMessagesOnDestinationQueue = _managedDestinationQueue.getMessageCount().intValue(); + int numberOfMessagesRemainingOnSourceQueue = _managedSourceQueue.getMessageCount().intValue(); + + LOGGER.debug("Async consumer read : " + numberOfMessagesReadByConsumer + + " Number of messages moved to destination : " + numberOfMessagesOnDestinationQueue + + " Number of messages remaining on source : " + numberOfMessagesRemainingOnSourceQueue); + assertEquals("Unexpected number of messages after move", numberOfMessagesToSend, numberOfMessagesReadByConsumer + numberOfMessagesOnDestinationQueue + numberOfMessagesRemainingOnSourceQueue); + } + + public void testMoveMessagesBetweenQueuesWithActiveConsumerOnDestinationQueue() throws Exception + { + setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString()); + Connection asyncConnection = getConnection(); + asyncConnection.start(); + + final int numberOfMessagesToSend = 50; + sendMessage(_session, _sourceQueue, numberOfMessagesToSend); + syncSession(_session); + assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); + + List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); + long fromMessageId = amqMessagesIds.get(0); + long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1); + + AtomicInteger totalConsumed = new AtomicInteger(0); + CountDownLatch allMessagesConsumedLatch = new CountDownLatch(numberOfMessagesToSend); + startAsyncConsumerOn(_destinationQueue, asyncConnection, allMessagesConsumedLatch, totalConsumed); + + _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); + + allMessagesConsumedLatch.await(5000, TimeUnit.MILLISECONDS); + assertEquals("Did not consume all messages from destination queue", numberOfMessagesToSend, totalConsumed.intValue()); + } + + private void startAsyncConsumerOn(Destination queue, Connection asyncConnection, + final CountDownLatch requiredNumberOfMessagesRead, final AtomicInteger totalConsumed) throws Exception + { + Session session = asyncConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + MessageConsumer consumer = session.createConsumer(queue); + consumer.setMessageListener(new MessageListener() + { + + @Override + public void onMessage(Message arg0) + { + totalConsumed.incrementAndGet(); + requiredNumberOfMessagesRead.countDown(); + } + }); + } + + private void assertMessageIndicesOn(Destination queue, int... expectedIndices) throws Exception + { + MessageConsumer consumer = _session.createConsumer(queue); + + for (int i : expectedIndices) + { + Message message = consumer.receive(1000); + assertNotNull("Expected message with index " + i, message); + assertEquals("Expected message with index " + i, i, message.getIntProperty(INDEX)); + } + + assertNull("Unexpected message encountered", consumer.receive(1000)); + } + + private List getAMQMessageIdsOn(ManagedQueue managedQueue, long startIndex, long endIndex) throws Exception + { + final SortedSet messageIds = new TreeSet(); + + final TabularData tab = managedQueue.viewMessages(startIndex, endIndex); + final Iterator rowItr = (Iterator) tab.values().iterator(); + while(rowItr.hasNext()) + { + final CompositeData row = rowItr.next(); + long amqMessageId = (Long)row.get(ManagedQueue.MSG_AMQ_ID); + messageIds.add(amqMessageId); + } + + return new ArrayList(messageIds); + } + + /** + * + * Utility method to convert array of Strings in the form x = y into a + * map with key/value x => y. + * + */ + private Map headerArrayToMap(final String[] headerArray) + { + final Map headerMap = new HashMap(); + final List headerList = Arrays.asList(headerArray); + for (Iterator iterator = headerList.iterator(); iterator.hasNext();) + { + final String nameValuePair = iterator.next(); + final String[] nameValue = nameValuePair.split(" *= *", 2); + headerMap.put(nameValue[0], nameValue[1]); + } + return headerMap; + } + + private void createQueueOnBroker(Destination destination) throws JMSException + { + _session.createConsumer(destination).close(); // Create a consumer only to cause queue creation + } + + private void syncSession(Session session) throws Exception + { + ((AMQSession)session).sync(); + } + + private final class RecordingNotificationListener implements NotificationListener + { + private final CountDownLatch _notificationReceivedLatch; + private final AtomicInteger _numberOfNotifications; + private final AtomicReference _lastNotification; + + private RecordingNotificationListener(int expectedNumberOfNotifications) + { + _notificationReceivedLatch = new CountDownLatch(expectedNumberOfNotifications); + _numberOfNotifications = new AtomicInteger(0); + _lastNotification = new AtomicReference(); + } + + @Override + public void handleNotification(Notification notification, Object handback) + { + _lastNotification.set(notification); + _numberOfNotifications.incrementAndGet(); + _notificationReceivedLatch.countDown(); + } + + public int getNumberOfNotificationsReceived() + { + return _numberOfNotifications.get(); + } + + public Notification getLastNotification() + { + return _lastNotification.get(); + } + + public void awaitExpectedNotifications(long timeout, TimeUnit timeunit) throws InterruptedException + { + _notificationReceivedLatch.await(timeout, timeunit); + } + } + +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java new file mode 100644 index 0000000000..c3fff94923 --- /dev/null +++ b/java/broker-plugins/management-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 managedConnections = _jmxUtils.getManagedConnections(vHostName); + assertEquals(1, managedConnections.size()); + + ManagedConnection managedConnection = managedConnections.get(0); + + assertEquals(messagesSent, managedConnection.getTotalMessagesReceived()); + assertEquals(messagesReceived, managedConnection.getTotalMessagesDelivered()); + + assertEquals(dataSent, managedConnection.getTotalDataReceived()); + assertEquals(dataReceived, managedConnection.getTotalDataDelivered()); + } + + private void checkVHostStatistics(String vHostName, long messagesSent, long messagesReceived, long dataSent, long dataReceived) + { + ManagedBroker vhost = _jmxUtils.getManagedBroker(vHostName); + + assertEquals(messagesSent, vhost.getTotalMessagesReceived()); + assertEquals(messagesReceived, vhost.getTotalMessagesDelivered()); + + assertEquals(dataSent, vhost.getTotalDataReceived()); + assertEquals(dataReceived, vhost.getTotalDataDelivered()); + } + + private void checkBrokerStatistics(long messagesSent, long messagesReceived, long dataSent, long dataReceived) + { + ServerInformation broker = _jmxUtils.getServerInformation(); + + assertEquals(messagesSent, broker.getTotalMessagesReceived()); + assertEquals(messagesReceived, broker.getTotalMessagesDelivered()); + + assertEquals(dataSent, broker.getTotalDataReceived()); + assertEquals(dataReceived, broker.getTotalDataDelivered()); + } +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java new file mode 100644 index 0000000000..62b1b554a9 --- /dev/null +++ b/java/broker-plugins/management-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 getPrincipalDatabaseImplClass() + { + return PlainPasswordFilePrincipalDatabase.class; + } + + private File createTemporaryPasswordFileWithJmxAdminUser() throws Exception + { + File passwordFile = File.createTempFile("passwd", "pwd"); + passwordFile.deleteOnExit(); + writePasswordFile(passwordFile, JMXTestUtils.DEFAULT_USERID, JMXTestUtils.DEFAULT_PASSWORD); + return passwordFile; + } + + private void writePasswordFile(File passwordFile, String... userNamePasswordPairs) throws Exception + { + FileWriter writer = null; + try + { + writer = new FileWriter(passwordFile); + for (int i = 0; i < userNamePasswordPairs.length; i=i+2) + { + String username = userNamePasswordPairs[i]; + String password = userNamePasswordPairs[i+1]; + writer.append(_passwd.getOutput(username, password) + "\n"); + } + } + finally + { + writer.close(); + } + } + + + private void assertFileContainsPasswordForUser(String username) throws IOException + { + assertTrue("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username)); + } + + private void assertFileDoesNotContainsPasswordForUser(String username) throws IOException + { + assertFalse("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username)); + } + + private boolean passwordFileContainsUser(String username) throws IOException + { + BufferedReader reader = null; + try + { + reader = new BufferedReader(new FileReader(_passwordFile)); + String line = reader.readLine(); + while(line != null) + { + if (line.startsWith(username)) + { + return true; + } + line = reader.readLine(); + } + + return false; + } + finally + { + reader.close(); + } + } + + private void assertJmsConnectionSucceeds(String username, String password) throws Exception + { + Connection connection = getConnection(username, password); + assertNotNull(connection); + } + + private void assertJmsConnectionFails(String username, String password) throws Exception + { + try + { + getConnection(username, password); + fail("Exception not thrown"); + } + catch (JMSException e) + { + // PASS + } + } +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java new file mode 100644 index 0000000000..84a66232ce --- /dev/null +++ b/java/broker-plugins/management-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 getPrincipalDatabaseImplClass() + { + return Base64MD5PasswordFilePrincipalDatabase.class; + } + +} diff --git a/java/broker-plugins/management/MANIFEST.MF b/java/broker-plugins/management/MANIFEST.MF deleted file mode 100644 index d817ac5302..0000000000 --- a/java/broker-plugins/management/MANIFEST.MF +++ /dev/null @@ -1,66 +0,0 @@ -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/java/broker-plugins/management/build.xml b/java/broker-plugins/management/build.xml deleted file mode 100644 index daa361b7a2..0000000000 --- a/java/broker-plugins/management/build.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/Management.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/Management.java deleted file mode 100644 index 589f46749d..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/Management.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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 _servers = new ArrayList(); - - - public Management() - { - _broker = ApplicationRegistry.getInstance().getBroker(); - - Collection 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... 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/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java deleted file mode 100644 index 2600d8a7bf..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.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/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java deleted file mode 100644 index 3866da8f89..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.management.plugin; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; - -import java.util.Arrays; -import java.util.List; - -public class ManagementConfiguration extends ConfigurationPlugin -{ - CompositeConfiguration _finalConfig; - - public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() - { - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException - { - ConfigurationPlugin instance = new ManagementConfiguration(); - instance.setConfiguration(path, config); - return instance; - } - - public List getParentPaths() - { - return Arrays.asList("management"); - } - }; - - public String[] getElementsProcessed() - { - return new String[] { "" }; - } - - public Configuration getConfiguration() - { - return _finalConfig; - } - - - @Override - public void validateConfiguration() throws ConfigurationException - { - // Valid Configuration either has xml links to new files - _finalConfig = new CompositeConfiguration(getConfig()); - List subFiles = getConfig().getList("xml[@fileName]"); - for (Object subFile : subFiles) - { - _finalConfig.addConfiguration(new XMLConfiguration((String) subFile)); - } - - } - -} diff --git a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java deleted file mode 100644 index d8a8395550..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.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; - -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/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java deleted file mode 100644 index f8ca082d79..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.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.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 CONTENT_TYPES; - - static - { - - Map contentTypes = new HashMap(); - 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/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java deleted file mode 100644 index a3c5ec68a2..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.management.plugin.servlet.api; - -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.map.ObjectReader; - -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.Exchange; -import org.apache.qpid.server.model.LifetimePolicy; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.registry.ApplicationRegistry; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -public class ExchangesServlet extends HttpServlet -{ - - - private Broker _broker; - - public ExchangesServlet() - { - super(); - _broker = ApplicationRegistry.getInstance().getBroker(); - } - - public ExchangesServlet(Broker broker) - { - _broker = broker; - } - - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException - { - response.setContentType("application/json"); - response.setStatus(HttpServletResponse.SC_OK); - - Collection vhosts = _broker.getVirtualHosts(); - Collection exchanges = new ArrayList(); - Collection> outputObject = new ArrayList>(); - - final PrintWriter writer = response.getWriter(); - - ObjectMapper mapper = new ObjectMapper(); - String vhostName = null; - String exchangeName = null; - - if(request.getPathInfo() != null && request.getPathInfo().length()>0) - { - String path = request.getPathInfo().substring(1); - String[] parts = path.split("/"); - vhostName = parts.length == 0 ? "" : parts[0]; - if(parts.length > 1) - { - exchangeName = parts[1]; - } - } - - for(VirtualHost vhost : vhosts) - { - if(vhostName == null || vhostName.equals(vhost.getName())) - { - for(Exchange exchange : vhost.getExchanges()) - { - if(exchangeName == null || exchangeName.equals(exchange.getName())) - { - outputObject.add(convertToObject(exchange)); - if(exchangeName != null) - { - break; - } - } - } - if(vhostName != null) - { - break; - } - } - } - - mapper.writeValue(writer, outputObject); - - } - - private Map convertToObject(final Exchange exchange) - { - Map object = new LinkedHashMap(); - object.put("name",exchange.getName()); - object.put("type", exchange.getExchangeType()); - object.put("durable", exchange.isDurable()); - object.put("auto-delete", exchange.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE); - - Map arguments = new HashMap(); - for(String key : exchange.getAttributeNames()) - { - if(!key.equals(Exchange.TYPE)) - { - arguments.put(key, exchange.getAttribute(key)); - } - } - object.put("arguments", arguments); - return object; - } - - protected void doPut(final HttpServletRequest request, final HttpServletResponse response) - throws ServletException, IOException - { - - response.setContentType("application/json"); - - - String vhostName = null; - String exchangeName = null; - if(request.getPathInfo() != null && request.getPathInfo().length()>0) - { - String path = request.getPathInfo().substring(1); - String[] parts = path.split("/"); - vhostName = parts.length == 0 ? "" : parts[0]; - if(parts.length > 1) - { - exchangeName = parts[1]; - } - } - if(vhostName == null) - { - response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED); - } - else if (exchangeName == null) - { - response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED); - } - else - { - VirtualHost vhost = null; - for(VirtualHost host : _broker.getVirtualHosts()) - { - if(host.getName().equals(vhostName)) - { - vhost = host; - } - } - if(vhost == null) - { - response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED); - } - else - { - response.setStatus(HttpServletResponse.SC_NO_CONTENT); - ObjectMapper mapper = new ObjectMapper(); - Map exchangeObject = mapper.readValue(request.getInputStream(), LinkedHashMap.class); - - final boolean isDurable = exchangeObject.get("durable") instanceof Boolean - && ((Boolean)exchangeObject.get("durable")); - final boolean isAutoDelete = exchangeObject.get("auto_delete") instanceof Boolean - && ((Boolean)exchangeObject.get("auto_delete")); - - final String type = (String) exchangeObject.get("type"); - final Map attributes = new HashMap(exchangeObject); - attributes.remove("durable"); - attributes.remove("auto_delete"); - attributes.remove("type"); - - vhost.createExchange(exchangeName, State.ACTIVE, isDurable, - isAutoDelete ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT, - 0l, - type, - attributes); - } - - - - } - - - - } -} diff --git a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java deleted file mode 100644 index b2c0fcfe52..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.management.plugin.servlet.api; - -import org.codehaus.jackson.map.ObjectMapper; - -import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.LifetimePolicy; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.protocol.AMQConnectionModel; -import org.apache.qpid.server.registry.ApplicationRegistry; - - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.*; - -public class VhostsServlet extends HttpServlet -{ - - - private Broker _broker; - - public VhostsServlet() - { - super(); - _broker = ApplicationRegistry.getInstance().getBroker(); - } - - public VhostsServlet(Broker broker) - { - _broker = broker; - } - - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException - { -System.out.println("Get /api/vhosts"); - response.setContentType("application/json"); - response.setStatus(HttpServletResponse.SC_OK); - - Collection vhosts = _broker.getVirtualHosts(); - - - - final PrintWriter writer = response.getWriter(); - - ObjectMapper mapper = new ObjectMapper(); - - if(request.getPathInfo() == null || request.getPathInfo().length()==0) - { - - LinkedHashMap vhostObject = new LinkedHashMap(); - List vhostList = new ArrayList(); - - for(VirtualHost vhost : vhosts) - { - vhostList.add(Collections.singletonMap("name", vhost.getName())); - } - mapper.writeValue(writer, vhostList); - } - else - { - LinkedHashMap vhostObject = new LinkedHashMap(); - String vhostName = request.getPathInfo().substring(1); - - for(VirtualHost vhost : vhosts) - { - if(vhostName.equals(vhost.getName())) - { - vhostObject.put("name", vhost.getName()); - break; - } - } - mapper.writeValue(writer, vhostObject); - } - } - - - protected void doPut(final HttpServletRequest request, final HttpServletResponse response) - throws ServletException, IOException - { - - response.setContentType("application/json"); - response.setStatus(HttpServletResponse.SC_NO_CONTENT); - - if(request.getPathInfo() != null && request.getPathInfo().length()>0) - { - String vhostName = request.getPathInfo().substring(1); - _broker.createVirtualHost(vhostName, State.ACTIVE, true, LifetimePolicy.PERMANENT, 0L, Collections.EMPTY_MAP); - } - - - } -} diff --git a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java deleted file mode 100644 index 123f352ec1..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.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.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/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.java deleted file mode 100644 index 3d862ce321..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/KeyComparator.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.management.plugin.servlet.rest; - -import java.util.Comparator; -import java.util.Map; - -class KeyComparator implements Comparator -{ - 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/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java deleted file mode 100644 index 7a4b92f907..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.qpid.server.management.plugin.servlet.rest; - -import java.io.IOException; -import java.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> logRecords = new ArrayList>(); - - 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 logRecordToObject(LogRecorder.Record record) - { - Map recordMap = new LinkedHashMap(); - 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/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.java deleted file mode 100644 index 84d987813b..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MapComparator.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.management.plugin.servlet.rest; - -import java.util.Collections; -import java.util.Comparator; -import java.util.Map; - -class MapComparator implements Comparator -{ - private Comparator[] _sortKeys; - - public MapComparator(final String[] sortKeys) - { - _sortKeys = parseKeys(sortKeys); - } - - private static Comparator[] parseKeys(final String[] sortKeys) - { - Comparator[] 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/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java deleted file mode 100644 index 4d58a9f3b0..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.qpid.server.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 names = new ArrayList(); - // 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/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java deleted file mode 100644 index b47dc8b28e..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java +++ /dev/null @@ -1,503 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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> 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 names = new ArrayList(); - // 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 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 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 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> _messages = new ArrayList>(); - - 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 messageObject = convertToObject(entry, false); - messageObject.put("position", _position); - _messages.add(messageObject); - } - return _last != -1 && _position > _last; - } - - public List> getMessages() - { - return _messages; - } - } - - - private class MessageFinder implements QueueEntryVisitor - { - private final long _messageNumber; - private Map _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 getMessageObject() - { - return _messageObject; - } - } - - private Map convertToObject(QueueEntry entry, boolean includeContent) - { - Map object = new LinkedHashMap(); - 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 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 object, String name, Object property) - { - if(property != null) - { - object.put(name, property); - } - } - - private void convertMessageHeaders(Map object, ServerMessage message) - { - final AMQMessageHeader messageHeader = message.getMessageHeader(); - if(messageHeader != null) - { - Map headers = new HashMap(); - 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 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 messageIds = new ArrayList(); - 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/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java deleted file mode 100644 index dbf9f9b48d..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java +++ /dev/null @@ -1,577 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY 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.*; -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; - - -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 RESERVED_PARAMS = new HashSet(Arrays.asList(DEPTH_PARAM, SORT_PARAM)); - - private Class[] _hierarchy; - - private volatile boolean initializationRequired = false; - - public RestServlet() - { - super(); - initializationRequired = true; - } - - public RestServlet(Broker broker, SocketAddress socketaddress, Class... 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> classes = new ArrayList>(); - 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 clazz = (Class)itemClass; - classes.add(clazz); - } - Class[] hierachyClasses = (Class[])new Class[classes.size()]; - _hierarchy = classes.toArray(hierachyClasses); - } - else - { - _hierarchy = (Class[])new Class[0]; - } - } - - protected Collection getObjects(HttpServletRequest request) - { - List names = new ArrayList(); - 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 parents = Collections.singleton((ConfiguredObject) getBroker()); - Collection children = new ArrayList(); - - Map, String> filters = - new HashMap, 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(); - } - - if(!filters.isEmpty()) - { - Collection potentials = parents; - parents = new ArrayList(); - - for(ConfiguredObject o : potentials) - { - - boolean match = true; - - for(Map.Entry, String> entry : filters.entrySet()) - { - Collection 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 filter(Collection objects, HttpServletRequest request) - { - - - Map> filters = new HashMap>(); - - for(String param : (Collection) Collections.list(request.getParameterNames())) - { - if(!RESERVED_PARAMS.contains(param)) - { - filters.put(param, Arrays.asList(request.getParameterValues(param))); - } - } - - if(filters.isEmpty()) - { - return objects; - } - - Collection filteredObj = new ArrayList(objects); - - Iterator iter = filteredObj.iterator(); - - while(iter.hasNext()) - { - ConfiguredObject obj = iter.next(); - for(Map.Entry> entry : filters.entrySet()) - { - Object value = obj.getAttribute(entry.getKey()); - if(!entry.getValue().contains(String.valueOf(value))) - { - iter.remove(); - } - } - - } - - return filteredObj; - } - - private Collection getAncestors(Class childType, - Class ancestorType, - ConfiguredObject child) - { - Collection ancestors = new HashSet(); - Collection> parentTypes = Model.getParentTypes(childType); - - for(Class 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 convertObjectToMap(final ConfiguredObject confObject, - Class clazz, - int depth) - { - Map object = new LinkedHashMap(); - - for(String name : confObject.getAttributeNames()) - { - Object value = confObject.getAttribute(name); - if(value != null) - { - object.put(name, value); - } - } - - Statistics statistics = confObject.getStatistics(); - Map statMap = new HashMap(); - 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 childClass : Model.getChildTypes(clazz)) - { - Collection children = confObject.getChildren(childClass); - if(children != null) - { - List> childObjects = new ArrayList>(); - - 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 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> output = new ArrayList>(); - - // 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 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 providedObject = mapper.readValue(request.getInputStream(), LinkedHashMap.class); - - - List names = new ArrayList(); - 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[] 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(); - 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 parents = new ArrayList(); - Class objClass = getConfiguredClass(); - Collection> 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 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 providedObject) - { - for(Map.Entry 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 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/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java deleted file mode 100644 index 0787e7ec1d..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * 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.log4j.Logger; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; - -import 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 Logger LOGGER = Logger.getLogger(SaslServlet.class); - - 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 outputObject = new LinkedHashMap(); - 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) - { - LOGGER.error("Error processing SASL request", e); - throw e; - } - catch(RuntimeException e) - { - LOGGER.error("Error processing SASL request", e); - 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 outputObject = new LinkedHashMap(); - 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/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java b/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java deleted file mode 100644 index 6295d74b42..0000000000 --- a/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.qpid.server.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 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 generateStructure(ConfiguredObject object, Class clazz) - { - Map structure = new LinkedHashMap(); - structure.put("id", object.getId()); - structure.put("name", object.getName()); - - for(Class childClass : Model.getChildTypes(clazz)) - { - Collection children = object.getChildren(childClass); - if(children != null) - { - List> childObjects = new ArrayList>(); - - for(ConfiguredObject child : children) - { - childObjects.add(generateStructure(child, childClass)); - } - - if(!childObjects.isEmpty()) - { - structure.put(pluralize(childClass),childObjects); - } - } - } - - return structure; - } - - private String pluralize(Class childClass) - { - String name = childClass.getSimpleName().toLowerCase(); - return name + (name.endsWith("s") ? "es" : "s"); - } -} diff --git a/java/broker-plugins/management/src/main/java/resources/addBinding.html b/java/broker-plugins/management/src/main/java/resources/addBinding.html deleted file mode 100644 index 8dbd219c8d..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/addBinding.html +++ /dev/null @@ -1,42 +0,0 @@ - -

-
-
- - - - - - - - - - - - - -
Exchange Name*:
Queue Name*:
Binding Key*:
-
- - - - -
-
-
diff --git a/java/broker-plugins/management/src/main/java/resources/addExchange.html b/java/broker-plugins/management/src/main/java/resources/addExchange.html deleted file mode 100644 index cccdfbd00c..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/addExchange.html +++ /dev/null @@ -1,53 +0,0 @@ - -
-
-
- - - - - - - - - - - - - -
Exchange Name*:
Durable?
Exchange Type: - -
-
- - - - -
-
-
diff --git a/java/broker-plugins/management/src/main/java/resources/addQueue.html b/java/broker-plugins/management/src/main/java/resources/addQueue.html deleted file mode 100644 index 8154f053cd..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/addQueue.html +++ /dev/null @@ -1,174 +0,0 @@ - -
-
-
- - - - - - - - - - - - - -
Queue Name*:
Durable?
Queue Type: - - -    - - -    - - -    - - -
-
- - - - - - - - -
-
- - - - - - - - - - - - -
Capacity:
Resume Capacity:
-
-
-
- - - - - - - - - - - - - - - - - - - - -
Maximum Message Age:
Maximum Message Size:
Maximum Number in Queue:
Gap between alerts:
-
-
-
- - - - - - - - - -
Maximum Delivery Retries:
-
-
- - - -
-
-
diff --git a/java/broker-plugins/management/src/main/java/resources/authenticationprovider/addUser.html b/java/broker-plugins/management/src/main/java/resources/authenticationprovider/addUser.html deleted file mode 100644 index 785605f694..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/authenticationprovider/addUser.html +++ /dev/null @@ -1,42 +0,0 @@ - -
-
-
- - - - - - - - - -
User Name*:
Password*
-
- - - - -
-
-
diff --git a/java/broker-plugins/management/src/main/java/resources/authenticationprovider/setPassword.html b/java/broker-plugins/management/src/main/java/resources/authenticationprovider/setPassword.html deleted file mode 100644 index 3d67463abd..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/authenticationprovider/setPassword.html +++ /dev/null @@ -1,42 +0,0 @@ - -
-
-
- - - - - - - - - -
User Name:
Password*
-
- - - - -
-
-
diff --git a/java/broker-plugins/management/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html b/java/broker-plugins/management/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html deleted file mode 100644 index baadc8c35f..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html +++ /dev/null @@ -1,29 +0,0 @@ - -
-
-
- - - -
- -
diff --git a/java/broker-plugins/management/src/main/java/resources/css/common.css b/java/broker-plugins/management/src/main/java/resources/css/common.css deleted file mode 100644 index 78780edcd9..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/css/common.css +++ /dev/null @@ -1,92 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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/java/broker-plugins/management/src/main/java/resources/footer.html b/java/broker-plugins/management/src/main/java/resources/footer.html deleted file mode 100644 index fa84825e80..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/footer.html +++ /dev/null @@ -1,28 +0,0 @@ - - - \ No newline at end of file diff --git a/java/broker-plugins/management/src/main/java/resources/images/qpid-logo.png b/java/broker-plugins/management/src/main/java/resources/images/qpid-logo.png deleted file mode 100644 index 95d49ea469..0000000000 Binary files a/java/broker-plugins/management/src/main/java/resources/images/qpid-logo.png and /dev/null differ diff --git a/java/broker-plugins/management/src/main/java/resources/js/qpid/authorization/sasl.js b/java/broker-plugins/management/src/main/java/resources/js/qpid/authorization/sasl.js deleted file mode 100644 index 152504da86..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/js/qpid/authorization/sasl.js +++ /dev/null @@ -1,213 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -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>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: - '' + - '

' + - '' + - '

' + - '' - }); - - button = new DropDownButton({ - label: "Login", - dropDown: dialog - }); - - usernameSpan = domConstruct.create("span", { innerHTML: 'User: ', - 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/java/broker-plugins/management/src/main/java/resources/js/qpid/common/UpdatableStore.js b/java/broker-plugins/management/src/main/java/resources/js/qpid/common/UpdatableStore.js deleted file mode 100644 index f7ede1a7f7..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/js/qpid/common/UpdatableStore.js +++ /dev/null @@ -1,110 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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/java/broker-plugins/management/src/main/java/resources/js/qpid/common/footer.js b/java/broker-plugins/management/src/main/java/resources/js/qpid/common/footer.js deleted file mode 100644 index ea13b1fc53..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/js/qpid/common/footer.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -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/java/broker-plugins/management/src/main/java/resources/js/qpid/common/formatter.js b/java/broker-plugins/management/src/main/java/resources/js/qpid/common/formatter.js deleted file mode 100644 index 2f8683ee1c..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/js/qpid/common/formatter.js +++ /dev/null @@ -1,99 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -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/java/broker-plugins/management/src/main/java/resources/js/qpid/common/properties.js b/java/broker-plugins/management/src/main/java/resources/js/qpid/common/properties.js deleted file mode 100644 index 8d85345b74..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/js/qpid/common/properties.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -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/java/broker-plugins/management/src/main/java/resources/js/qpid/common/updater.js b/java/broker-plugins/management/src/main/java/resources/js/qpid/common/updater.js deleted file mode 100644 index 86bbaa46ba..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/js/qpid/common/updater.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -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/java/broker-plugins/management/src/main/java/resources/js/qpid/common/util.js b/java/broker-plugins/management/src/main/java/resources/js/qpid/common/util.js deleted file mode 100644 index d7917b640e..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/js/qpid/common/util.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -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/java/broker-plugins/management/src/main/java/resources/js/qpid/management/AuthenticationProvider.js b/java/broker-plugins/management/src/main/java/resources/js/qpid/management/AuthenticationProvider.js deleted file mode 100644 index 7613fd5d71..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/js/qpid/management/AuthenticationProvider.js +++ /dev/null @@ -1,122 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -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/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Broker.js b/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Broker.js deleted file mode 100644 index dcf6711073..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Broker.js +++ /dev/null @@ -1,205 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -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/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Connection.js b/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Connection.js deleted file mode 100644 index 01f9a325c5..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Connection.js +++ /dev/null @@ -1,213 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -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/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Exchange.js b/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Exchange.js deleted file mode 100644 index 0450ef53ac..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Exchange.js +++ /dev/null @@ -1,229 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Queue.js b/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Queue.js deleted file mode 100644 index 1eb0bfdd79..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/js/qpid/management/Queue.js +++ /dev/null @@ -1,438 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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"; - tableStr += ""+encode(val[ name ])+""; - } - field.innerHTML = tableStr; - } - tableStr += ""; - } 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 = "Download"; - } - 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/java/broker-plugins/management/src/main/java/resources/js/qpid/management/treeView.js b/java/broker-plugins/management/src/main/java/resources/js/qpid/management/treeView.js deleted file mode 100644 index b1d4abf8c1..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/js/qpid/management/treeView.js +++ /dev/null @@ -1,313 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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/java/broker-plugins/management/src/main/java/resources/management.html b/java/broker-plugins/management/src/main/java/resources/management.html deleted file mode 100644 index a8345a8503..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/management.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - Qpid Management - - - - - - - - - - - - - - -
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
- - - \ No newline at end of file diff --git a/java/broker-plugins/management/src/main/java/resources/moveCopyMessages.html b/java/broker-plugins/management/src/main/java/resources/moveCopyMessages.html deleted file mode 100644 index f188c3001c..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/moveCopyMessages.html +++ /dev/null @@ -1,36 +0,0 @@ - - -
-
-
- - - - - -
Queue:
-
- - - - - - -
-
-
diff --git a/java/broker-plugins/management/src/main/java/resources/showAuthProvider.html b/java/broker-plugins/management/src/main/java/resources/showAuthProvider.html deleted file mode 100644 index c5d4e48a75..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/showAuthProvider.html +++ /dev/null @@ -1,25 +0,0 @@ - -
- Name: -
- Type: -
\ No newline at end of file diff --git a/java/broker-plugins/management/src/main/java/resources/showBroker.html b/java/broker-plugins/management/src/main/java/resources/showBroker.html deleted file mode 100644 index cb2f4a4b9a..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/showBroker.html +++ /dev/null @@ -1,25 +0,0 @@ -
- Broker: -
- -
-
-
-
-
-
-
-
-
- -
-
-
-
-
- diff --git a/java/broker-plugins/management/src/main/java/resources/showConnection.html b/java/broker-plugins/management/src/main/java/resources/showConnection.html deleted file mode 100644 index 84854daf47..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/showConnection.html +++ /dev/null @@ -1,47 +0,0 @@ - -
- Name: -
- State: - Pre-fetched: -
- Durable: - Inbound: - - msg/s - - -
- Lifespan: - Outbound: - - msg/s - - -
-
-
-
-
-
- -
diff --git a/java/broker-plugins/management/src/main/java/resources/showExchange.html b/java/broker-plugins/management/src/main/java/resources/showExchange.html deleted file mode 100644 index 64f351d218..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/showExchange.html +++ /dev/null @@ -1,46 +0,0 @@ - -
- Exchange: -
- State: -
- Durable: - Inbound: - - msg/s - - -
- Lifespan: - Dropped: - - msg/s - - -
-
-
-
- -
-
-
diff --git a/java/broker-plugins/management/src/main/java/resources/showMessage.html b/java/broker-plugins/management/src/main/java/resources/showMessage.html deleted file mode 100644 index 0dea508c60..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/showMessage.html +++ /dev/null @@ -1,73 +0,0 @@ - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Message Number:
Message Id:
State:
Persistent:
Priority:
Arrival Time: -
Expiration:
MIME Type:
User:
Headers:
Content:
-
- - -
-
- diff --git a/java/broker-plugins/management/src/main/java/resources/showQueue.html b/java/broker-plugins/management/src/main/java/resources/showQueue.html deleted file mode 100644 index c87a462760..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/showQueue.html +++ /dev/null @@ -1,97 +0,0 @@ - -
- Queue: - Size: - - msgs - ( - ) -
- State: - Pre-fetched: - - msgs - - -
- Durable: - Inbound: - - msg/s - - -
- Lifespan: - Outbound: - - msg/s - - -
-
-
-
- -
-
-
-
-
-
-
-
- - - -
-
-
- Max. Queue Size: - - msgs - - - -
- Max. Message Age: - - - - Size: - - -
-
- Alert frequency: - - - - - -
-
- diff --git a/java/broker-plugins/management/src/main/java/resources/showVirtualHost.html b/java/broker-plugins/management/src/main/java/resources/showVirtualHost.html deleted file mode 100644 index 9d16d523d6..0000000000 --- a/java/broker-plugins/management/src/main/java/resources/showVirtualHost.html +++ /dev/null @@ -1,84 +0,0 @@ - - - -
- Name: -
- State: -
- Durable: - Inbound: - - msg/s - - -
- Lifespan: - Outbound: - - msg/s - - -
-
-
-
- -
-
-
-
- -
-
-
-
-
-
-
- Max. Queue Size: - - msgs - - - -
- Max. Message Age: - - - - Size: - - -
-
- Alert frequency: - - -
-
- diff --git a/java/build.deps b/java/build.deps index 9c55a410e6..4c2920544c 100644 --- a/java/build.deps +++ b/java/build.deps @@ -79,7 +79,7 @@ broker.libs=${commons-cli} ${commons-logging} ${log4j} ${slf4j-log4j} \ ${xalan} ${felix.libs} ${derby-db} ${commons-configuration.libs} \ ${jackson-core} ${jackson-mapper} ${jetty} ${jetty-continuation} ${jetty-security} ${jetty-http} ${jetty-io} ${jetty-servlet} ${jetty-util} ${servlet-api} ${jetty-websocket} -broker-plugins-management.libs=${jetty} ${jetty-continuation} ${jetty-security} ${jetty-http} ${jetty-io} ${jetty-servlet} ${jetty-util} ${servlet-api} ${jackson-core} ${jackson-mapper} +broker-plugins-management-http.libs=${jetty} ${jetty-continuation} ${jetty-security} ${jetty-http} ${jetty-io} ${jetty-servlet} ${jetty-util} ${servlet-api} ${jackson-core} ${jackson-mapper} broker-plugins.libs=${felix.libs} ${log4j} ${commons-configuration.libs} test.libs=${slf4j-log4j} ${log4j} ${junit} ${slf4j-api} ${mockito-all} diff --git a/java/systests/build.xml b/java/systests/build.xml index d8ca018ca0..0ad5d3295c 100644 --- a/java/systests/build.xml +++ b/java/systests/build.xml @@ -32,7 +32,7 @@ nn - or more contributor license agreements. See the NOTICE file - + -- cgit v1.2.1