summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Godfrey <rgodfrey@apache.org>2013-04-23 20:54:19 +0000
committerRobert Godfrey <rgodfrey@apache.org>2013-04-23 20:54:19 +0000
commit985af562e1c232940251fc75c199ad9a51e356bb (patch)
treef0d8abd3367deb87ca9095b4e4e84be2f6870b92
parent917a1f26f8f26730528dd538ab817a340cdd8715 (diff)
downloadqpid-python-985af562e1c232940251fc75c199ad9a51e356bb.tar.gz
Merged up to r1465457
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-4659@1471141 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java263
-rw-r--r--qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SaslServerProvider.java2
-rw-r--r--qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java46
-rw-r--r--qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java66
-rw-r--r--qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/FileAccessControlProviderAttributeDescriptions.properties19
-rw-r--r--qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java34
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java41
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java38
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java225
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/ForbiddingAuthorisationFilter.java73
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/RedirectingAuthorisationFilter.java83
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java239
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java9
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogoutServlet.java4
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java38
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListAccessControlProviderAttributes.java76
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListGroupProviderAttributes.java76
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListMessageStoreTypes.java2
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/showAclFile.html (renamed from qpid/java/systests/etc/config-systests.xml)12
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/addAuthenticationProvider.html10
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/addBinding.html5
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/addExchange.html5
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html59
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html8
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHost.html3
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css1
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html2
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/index.html7
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/checkUser.js36
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js161
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js74
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AccessControlProvider.js131
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js329
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js46
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/KeyStore.js160
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Port.js205
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/TrustStore.js160
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/AclFile.js95
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js177
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAuthenticationProvider.js2
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addGroupProvider.js177
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addKeystore.js164
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js271
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js9
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js14
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js7
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/login.html120
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/showAccessControlProvider.html31
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html51
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html8
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/showKeyStore.html47
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/showPort.html77
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/showTrustStore.html47
-rw-r--r--qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java105
-rw-r--r--qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java61
-rw-r--r--qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/QpidSslRMIServerSocketFactory.java105
-rw-r--r--qpid/java/broker/etc/md5passwd1
-rw-r--r--qpid/java/broker/etc/virtualhosts.xml165
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java58
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java95
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreator.java11
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AccessControlProviderRecoverer.java54
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java1
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java144
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java25
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java35
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreUtil.java91
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStore.java57
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java13
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/MemoryConfigurationEntryStore.java47
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/JsonConfigurationStoreFactory.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/MemoryConfigurationStoreFactory.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java27
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java39
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java56
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java62
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java22
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java1
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java16
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java8
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java49
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java51
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderAdapter.java283
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderFactory.java90
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java14
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java547
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java143
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderFactory.java118
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java175
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java116
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java14
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java151
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/AccessControlFactory.java23
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/ConfigurationStoreFactory.java5
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.java23
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0.java8
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java18
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java1
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java5
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java9
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/AccessControl.java21
-rwxr-xr-xqpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java190
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/SubjectCreator.java6
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/FileAccessControlProviderConstants.java27
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticator.java (renamed from qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java)6
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java214
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManager.java126
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java42
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupManager.java8
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java2041
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java2046
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java396
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java41
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java6
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/util/StringUtil.java44
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java2
-rw-r--r--qpid/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory3
-rw-r--r--qpid/java/broker/src/main/resources/initial-config.json (renamed from qpid/java/broker/src/main/resources/initial-store.json)18
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java31
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/MainTest.java51
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreatorTest.java50
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java96
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java8
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java8
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/KeyStoreRecovererTest.java59
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/TrustStoreRecovererTest.java50
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java6
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStoreTest.java8
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java20
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/filter/JMSSelectorFilterTest.java56
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java3
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java97
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java160
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticatorTest.java (renamed from qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java)25
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java140
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java109
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslUtil.java85
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java8
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerTest.java37
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupProviderAttributeDescriptions.properties19
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java8
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/util/StringUtilTest.java38
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java4
-rw-r--r--qpid/java/build.deps18
-rw-r--r--qpid/java/client/example/src/main/java/org/apache/qpid/example/hello.properties2
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java2
-rw-r--r--qpid/java/common/src/test/java/org/apache/qpid/test/utils/TestSSLConstants.java (renamed from qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestSSLConstants.java)6
-rw-r--r--qpid/java/ivy.retrieve.xml18
-rw-r--r--qpid/java/lib/poms/jetty-continuation-7.6.10.v20130312.xml (renamed from qpid/java/lib/poms/jetty-continuation-7.6.3.v20120416.xml)2
-rw-r--r--qpid/java/lib/poms/jetty-http-7.6.10.v20130312.xml (renamed from qpid/java/lib/poms/jetty-http-7.6.3.v20120416.xml)2
-rw-r--r--qpid/java/lib/poms/jetty-io-7.6.10.v20130312.xml (renamed from qpid/java/lib/poms/jetty-io-7.6.3.v20120416.xml)2
-rw-r--r--qpid/java/lib/poms/jetty-security-7.6.10.v20130312.xml (renamed from qpid/java/lib/poms/jetty-security-7.6.3.v20120416.xml)2
-rw-r--r--qpid/java/lib/poms/jetty-server-7.6.10.v20130312.xml (renamed from qpid/java/lib/poms/jetty-server-7.6.3.v20120416.xml)2
-rw-r--r--qpid/java/lib/poms/jetty-servlet-7.6.10.v20130312.xml (renamed from qpid/java/lib/poms/jetty-servlet-7.6.3.v20120416.xml)2
-rw-r--r--qpid/java/lib/poms/jetty-util-7.6.10.v20130312.xml (renamed from qpid/java/lib/poms/jetty-util-7.6.3.v20120416.xml)2
-rw-r--r--qpid/java/lib/poms/jetty-websocket-7.6.10.v20130312.xml (renamed from qpid/java/lib/poms/jetty-websocket-7.6.3.v20120416.xml)2
-rw-r--r--qpid/java/systests/etc/config-systests.json22
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java89
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java29
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java4
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java7
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java141
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java2
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java4
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java4
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java4
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java7
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java2
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AccessControlProviderRestTest.java256
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AnonymousAccessRestTest.java95
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java4
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java11
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java5
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java49
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java190
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java16
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java270
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java47
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java14
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java6
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java73
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java2
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java262
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserRestTest.java1
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java625
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java7
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java2
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java146
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java10
-rwxr-xr-xqpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java11
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java86
-rwxr-xr-xqpid/java/test-profiles/CPPExcludes1
-rw-r--r--qpid/java/test-profiles/Excludes12
-rwxr-xr-xqpid/java/test-profiles/Java010Excludes1
206 files changed, 11565 insertions, 4658 deletions
diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java
index cdb2007b4a..0ef286e89e 100644
--- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java
+++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java
@@ -21,7 +21,8 @@
package org.apache.qpid.amqp_1_0.transport;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
import org.apache.qpid.amqp_1_0.codec.DescribedTypeConstructorRegistry;
import org.apache.qpid.amqp_1_0.codec.ValueWriter;
import org.apache.qpid.amqp_1_0.framing.AMQFrame;
@@ -59,12 +60,15 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
{
private static final short CONNECTION_CONTROL_CHANNEL = (short) 0;
private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.wrap(new byte[0]);
+ private static final Symbol SASL_PLAIN = Symbol.valueOf("PLAIN");
+ private static final Symbol SASL_ANONYMOUS = Symbol.valueOf("ANONYMOUS");
+ private static final Symbol SASL_EXTERNAL = Symbol.valueOf("EXTERNAL");
private final Container _container;
private Principal _user;
private static final short DEFAULT_CHANNEL_MAX = 255;
- private static final int DEFAULT_MAX_FRAME = Integer.getInteger("amqp.max_frame_size",1<<15);
+ private static final int DEFAULT_MAX_FRAME = Integer.getInteger("amqp.max_frame_size", 1 << 15);
private ConnectionState _state = ConnectionState.UNOPENED;
@@ -75,20 +79,20 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
private SocketAddress _remoteAddress;
// positioned by the *outgoing* channel
- private SessionEndpoint[] _sendingSessions = new SessionEndpoint[DEFAULT_CHANNEL_MAX+1];
+ private SessionEndpoint[] _sendingSessions = new SessionEndpoint[DEFAULT_CHANNEL_MAX + 1];
// positioned by the *incoming* channel
- private SessionEndpoint[] _receivingSessions = new SessionEndpoint[DEFAULT_CHANNEL_MAX+1];
+ private SessionEndpoint[] _receivingSessions = new SessionEndpoint[DEFAULT_CHANNEL_MAX + 1];
private boolean _closedForInput;
private boolean _closedForOutput;
private long _idleTimeout;
private AMQPDescribedTypeRegistry _describedTypeRegistry = AMQPDescribedTypeRegistry.newInstance()
- .registerTransportLayer()
- .registerMessagingLayer()
- .registerTransactionLayer()
- .registerSecurityLayer();
+ .registerTransportLayer()
+ .registerMessagingLayer()
+ .registerTransactionLayer()
+ .registerSecurityLayer();
private FrameOutputHandler<FrameBody> _frameOutputHandler;
@@ -135,11 +139,11 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
public synchronized void open()
{
- if(_requiresSASLClient)
+ if (_requiresSASLClient)
{
synchronized (getLock())
{
- while(!_saslComplete)
+ while (!_saslComplete)
{
try
{
@@ -151,12 +155,12 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
}
}
}
- if(!_authenticated)
+ if (!_authenticated)
{
throw new RuntimeException("Could not connect - authentication error");
}
}
- if(_state == ConnectionState.UNOPENED)
+ if (_state == ConnectionState.UNOPENED)
{
sendOpen(DEFAULT_CHANNEL_MAX, DEFAULT_MAX_FRAME);
_state = ConnectionState.AWAITING_OPEN;
@@ -172,8 +176,8 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
{
// todo assert connection state
SessionEndpoint endpoint = new SessionEndpoint(this);
- short channel = getFirstFreeChannel();
- if(channel != -1)
+ short channel = getFirstFreeChannel();
+ if (channel != -1)
{
_sendingSessions[channel] = endpoint;
endpoint.setSendingChannel(channel);
@@ -244,8 +248,6 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
}
-
-
private void closeSender()
{
setClosedForOutput(true);
@@ -255,9 +257,9 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
short getFirstFreeChannel()
{
- for(int i = 0; i<_sendingSessions.length;i++)
+ for (int i = 0; i < _sendingSessions.length; i++)
{
- if(_sendingSessions[i]==null)
+ if (_sendingSessions[i] == null)
{
return (short) i;
}
@@ -276,22 +278,25 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
{
_channelMax = open.getChannelMax() == null ? DEFAULT_CHANNEL_MAX
- : open.getChannelMax().shortValue() < DEFAULT_CHANNEL_MAX
- ? DEFAULT_CHANNEL_MAX
- : open.getChannelMax().shortValue();
+ : open.getChannelMax().shortValue() < DEFAULT_CHANNEL_MAX
+ ? DEFAULT_CHANNEL_MAX
+ : open.getChannelMax().shortValue();
- UnsignedInteger remoteDesiredMaxFrameSize = open.getMaxFrameSize() == null ? UnsignedInteger.valueOf(DEFAULT_MAX_FRAME) : open.getMaxFrameSize();
+ UnsignedInteger remoteDesiredMaxFrameSize =
+ open.getMaxFrameSize() == null ? UnsignedInteger.valueOf(DEFAULT_MAX_FRAME) : open.getMaxFrameSize();
- _maxFrameSize = (remoteDesiredMaxFrameSize.compareTo(_desiredMaxFrameSize) < 0 ? remoteDesiredMaxFrameSize : _desiredMaxFrameSize).intValue();
+ _maxFrameSize = (remoteDesiredMaxFrameSize.compareTo(_desiredMaxFrameSize) < 0
+ ? remoteDesiredMaxFrameSize
+ : _desiredMaxFrameSize).intValue();
_remoteContainerId = open.getContainerId();
- if(open.getIdleTimeOut() != null)
+ if (open.getIdleTimeOut() != null)
{
_idleTimeout = open.getIdleTimeOut().longValue();
}
- switch(_state)
+ switch (_state)
{
case UNOPENED:
sendOpen(_channelMax, _maxFrameSize);
@@ -313,7 +318,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
{
setClosedForInput(true);
_connectionEventListener.closeReceived();
- switch(_state)
+ switch (_state)
{
case UNOPENED:
case AWAITING_OPEN:
@@ -341,7 +346,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
{
Close close = new Close();
close.setError(error);
- switch(_state)
+ switch (_state)
{
case UNOPENED:
_state = ConnectionState.CLOSED;
@@ -359,17 +364,17 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
}
}
- public synchronized void inputClosed()
+ public synchronized void inputClosed()
{
- if(!_closedForInput)
+ if (!_closedForInput)
{
_closedForInput = true;
- for(int i = 0; i < _receivingSessions.length; i++)
+ for (int i = 0; i < _receivingSessions.length; i++)
{
- if(_receivingSessions[i] != null)
+ if (_receivingSessions[i] != null)
{
_receivingSessions[i].end();
- _receivingSessions[i]=null;
+ _receivingSessions[i] = null;
}
}
@@ -395,8 +400,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
short myChannelId;
-
- if(begin.getRemoteChannel() != null)
+ if (begin.getRemoteChannel() != null)
{
myChannelId = begin.getRemoteChannel().shortValue();
SessionEndpoint endpoint;
@@ -404,7 +408,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
{
endpoint = _sendingSessions[myChannelId];
}
- catch(IndexOutOfBoundsException e)
+ catch (IndexOutOfBoundsException e)
{
final Error error = new Error();
error.setCondition(ConnectionError.FRAMING_ERROR);
@@ -414,9 +418,9 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
connectionError(error);
return;
}
- if(endpoint != null)
+ if (endpoint != null)
{
- if(_receivingSessions[channel] == null)
+ if (_receivingSessions[channel] == null)
{
_receivingSessions[channel] = endpoint;
endpoint.setReceivingChannel(channel);
@@ -446,16 +450,16 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
{
myChannelId = getFirstFreeChannel();
- if(myChannelId == -1)
+ if (myChannelId == -1)
{
// close any half open channel
myChannelId = getFirstFreeChannel();
}
- if(_receivingSessions[channel] == null)
+ if (_receivingSessions[channel] == null)
{
- SessionEndpoint endpoint = new SessionEndpoint(this,begin);
+ SessionEndpoint endpoint = new SessionEndpoint(this, begin);
_receivingSessions[channel] = endpoint;
_sendingSessions[myChannelId] = endpoint;
@@ -483,15 +487,13 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
}
-
}
-
public synchronized void receiveEnd(short channel, End end)
{
SessionEndpoint endpoint = _receivingSessions[channel];
- if(endpoint != null)
+ if (endpoint != null)
{
_receivingSessions[channel] = null;
@@ -551,18 +553,18 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
public synchronized int send(short channel, FrameBody body, ByteBuffer payload)
{
- if(!_closedForOutput)
+ if (!_closedForOutput)
{
ValueWriter<FrameBody> writer = _describedTypeRegistry.getValueWriter(body);
int size = writer.writeToBuffer(EMPTY_BYTE_BUFFER);
ByteBuffer payloadDup = payload == null ? null : payload.duplicate();
int payloadSent = getMaxFrameSize() - (size + 9);
- if(payloadSent < (payload == null ? 0 : payload.remaining()))
+ if (payloadSent < (payload == null ? 0 : payload.remaining()))
{
- if(body instanceof Transfer)
+ if (body instanceof Transfer)
{
- ((Transfer)body).setMore(Boolean.TRUE);
+ ((Transfer) body).setMore(Boolean.TRUE);
}
writer = _describedTypeRegistry.getValueWriter(body);
@@ -571,9 +573,9 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
try
{
- payloadDup.limit(payloadDup.position()+payloadSent);
+ payloadDup.limit(payloadDup.position() + payloadSent);
}
- catch(NullPointerException npe)
+ catch (NullPointerException npe)
{
throw npe;
}
@@ -592,7 +594,6 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
}
-
public void invalidHeaderReceived()
{
// TODO
@@ -606,7 +607,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
public synchronized void protocolHeaderReceived(final byte major, final byte minorVersion, final byte revision)
{
- if(_requiresSASLServer && _state != ConnectionState.UNOPENED)
+ if (_requiresSASLServer && _state != ConnectionState.UNOPENED)
{
// TODO - bad stuff
}
@@ -618,7 +619,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
public synchronized void handleError(final Error error)
{
- if(!closedForOutput())
+ if (!closedForOutput())
{
Close close = new Close();
close.setError(error);
@@ -631,17 +632,17 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
public synchronized void receive(final short channel, final Object frame)
{
- if(_logger.isLoggable(Level.FINE))
+ if (_logger.isLoggable(Level.FINE))
{
- _logger.fine("RECV["+ _remoteAddress + "|"+channel+"] : " + frame);
+ _logger.fine("RECV[" + _remoteAddress + "|" + channel + "] : " + frame);
}
- if(frame instanceof FrameBody)
+ if (frame instanceof FrameBody)
{
- ((FrameBody)frame).invoke(channel, this);
+ ((FrameBody) frame).invoke(channel, this);
}
- else if(frame instanceof SaslFrameBody)
+ else if (frame instanceof SaslFrameBody)
{
- ((SaslFrameBody)frame).invoke(this);
+ ((SaslFrameBody) frame).invoke(this);
}
}
@@ -674,7 +675,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
public synchronized void close()
{
- switch(_state)
+ switch (_state)
{
case AWAITING_OPEN:
case OPEN:
@@ -737,10 +738,11 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
{
_saslComplete = true;
_authenticated = true;
+ _user = _saslServerProvider.getAuthenticatedPrincipal(_saslServer);
getLock().notifyAll();
}
- if(_onSaslCompleteTask != null)
+ if (_onSaslCompleteTask != null)
{
_onSaslCompleteTask.run();
}
@@ -766,7 +768,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
_authenticated = false;
getLock().notifyAll();
}
- if(_onSaslCompleteTask != null)
+ if (_onSaslCompleteTask != null)
{
_onSaslCompleteTask.run();
}
@@ -776,19 +778,32 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
public void receiveSaslMechanisms(final SaslMechanisms saslMechanisms)
{
- if(Arrays.asList(saslMechanisms.getSaslServerMechanisms()).contains(Symbol.valueOf("PLAIN")))
+ SaslInit init = new SaslInit();
+ init.setHostname(_remoteHostname);
+
+ Set<Symbol> mechanisms = new HashSet<Symbol>(Arrays.asList(saslMechanisms.getSaslServerMechanisms()));
+ if (mechanisms.contains(SASL_PLAIN) && _password != null)
{
- SaslInit init = new SaslInit();
- init.setMechanism(Symbol.valueOf("PLAIN"));
- init.setHostname(_remoteHostname);
+
+ init.setMechanism(SASL_PLAIN);
+
byte[] usernameBytes = _user.getName().getBytes(Charset.forName("UTF-8"));
byte[] passwordBytes = _password.getBytes(Charset.forName("UTF-8"));
- byte[] initResponse = new byte[usernameBytes.length+passwordBytes.length+2];
- System.arraycopy(usernameBytes,0,initResponse,1,usernameBytes.length);
- System.arraycopy(passwordBytes,0,initResponse,usernameBytes.length+2,passwordBytes.length);
+ byte[] initResponse = new byte[usernameBytes.length + passwordBytes.length + 2];
+ System.arraycopy(usernameBytes, 0, initResponse, 1, usernameBytes.length);
+ System.arraycopy(passwordBytes, 0, initResponse, usernameBytes.length + 2, passwordBytes.length);
init.setInitialResponse(new Binary(initResponse));
- _saslFrameOutput.send(new SASLFrame(init),null);
+
+ }
+ else if (mechanisms.contains(SASL_ANONYMOUS))
+ {
+ init.setMechanism(SASL_ANONYMOUS);
+ }
+ else if (mechanisms.contains(SASL_EXTERNAL))
+ {
+ init.setMechanism(SASL_EXTERNAL);
}
+ _saslFrameOutput.send(new SASLFrame(init), null);
}
public void receiveSaslChallenge(final SaslChallenge saslChallenge)
@@ -798,65 +813,66 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
public void receiveSaslResponse(final SaslResponse saslResponse)
{
- final Binary responseBinary = saslResponse.getResponse();
- byte[] response = responseBinary == null ? new byte[0] : responseBinary.getArray();
+ final Binary responseBinary = saslResponse.getResponse();
+ byte[] response = responseBinary == null ? new byte[0] : responseBinary.getArray();
- try
- {
-
- // Process response from the client
- byte[] challenge = _saslServer.evaluateResponse(response != null ? response : new byte[0]);
+ try
+ {
- if (_saslServer.isComplete())
- {
- SaslOutcome outcome = new SaslOutcome();
-
- outcome.setCode(SaslCode.OK);
- _saslFrameOutput.send(new SASLFrame(outcome),null);
- synchronized (getLock())
- {
- _saslComplete = true;
- _authenticated = true;
- getLock().notifyAll();
- }
- if(_onSaslCompleteTask != null)
- {
- _onSaslCompleteTask.run();
- }
+ // Process response from the client
+ byte[] challenge = _saslServer.evaluateResponse(response != null ? response : new byte[0]);
- }
- else
- {
- SaslChallenge challengeBody = new SaslChallenge();
- challengeBody.setChallenge(new Binary(challenge));
- _saslFrameOutput.send(new SASLFrame(challengeBody), null);
+ if (_saslServer.isComplete())
+ {
+ SaslOutcome outcome = new SaslOutcome();
- }
+ outcome.setCode(SaslCode.OK);
+ _saslFrameOutput.send(new SASLFrame(outcome), null);
+ synchronized (getLock())
+ {
+ _saslComplete = true;
+ _authenticated = true;
+ _user = _saslServerProvider.getAuthenticatedPrincipal(_saslServer);
+ getLock().notifyAll();
}
- catch (SaslException e)
+ if (_onSaslCompleteTask != null)
{
- SaslOutcome outcome = new SaslOutcome();
+ _onSaslCompleteTask.run();
+ }
- outcome.setCode(SaslCode.AUTH);
- _saslFrameOutput.send(new SASLFrame(outcome),null);
- synchronized (getLock())
- {
- _saslComplete = true;
- _authenticated = false;
- getLock().notifyAll();
- }
- if(_onSaslCompleteTask != null)
- {
- _onSaslCompleteTask.run();
- }
+ }
+ else
+ {
+ SaslChallenge challengeBody = new SaslChallenge();
+ challengeBody.setChallenge(new Binary(challenge));
+ _saslFrameOutput.send(new SASLFrame(challengeBody), null);
- }
+ }
}
+ catch (SaslException e)
+ {
+ SaslOutcome outcome = new SaslOutcome();
+
+ outcome.setCode(SaslCode.AUTH);
+ _saslFrameOutput.send(new SASLFrame(outcome), null);
+ synchronized (getLock())
+ {
+ _saslComplete = true;
+ _authenticated = false;
+ getLock().notifyAll();
+ }
+ if (_onSaslCompleteTask != null)
+ {
+ _onSaslCompleteTask.run();
+ }
+
+ }
+ }
public void receiveSaslOutcome(final SaslOutcome saslOutcome)
{
- if(saslOutcome.getCode() == SaslCode.OK)
+ if (saslOutcome.getCode() == SaslCode.OK)
{
_saslFrameOutput.close();
synchronized (getLock())
@@ -865,7 +881,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
_authenticated = true;
getLock().notifyAll();
}
- if(_onSaslCompleteTask != null)
+ if (_onSaslCompleteTask != null)
{
_onSaslCompleteTask.run();
}
@@ -904,22 +920,13 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour
return _authenticated;
}
- public void initiateSASL()
+ public void initiateSASL(String[] mechanismNames)
{
SaslMechanisms mechanisms = new SaslMechanisms();
- final Enumeration<SaslServerFactory> saslServerFactories = Sasl.getSaslServerFactories();
-
- SaslServerFactory f;
ArrayList<Symbol> mechanismsList = new ArrayList<Symbol>();
- while(saslServerFactories.hasMoreElements())
+ for (String name : mechanismNames)
{
- f = saslServerFactories.nextElement();
- final String[] mechanismNames = f.getMechanismNames(null);
- for(String name : mechanismNames)
- {
- mechanismsList.add(Symbol.valueOf(name));
- }
-
+ mechanismsList.add(Symbol.valueOf(name));
}
mechanisms.setSaslServerMechanisms(mechanismsList.toArray(new Symbol[mechanismsList.size()]));
_saslFrameOutput.send(new SASLFrame(mechanisms), null);
diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SaslServerProvider.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SaslServerProvider.java
index 1b08488673..abc92e8acf 100644
--- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SaslServerProvider.java
+++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SaslServerProvider.java
@@ -20,10 +20,12 @@
package org.apache.qpid.amqp_1_0.transport;
+import java.security.Principal;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
public interface SaslServerProvider
{
SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException;
+ Principal getAuthenticatedPrincipal(SaslServer server);
}
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java
index 6f7885da94..451b1f9c40 100644
--- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java
+++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java
@@ -29,6 +29,7 @@ import javax.security.auth.Subject;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.lang.ObjectUtils;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.security.Result;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.AccessControl;
@@ -44,6 +45,7 @@ public class DefaultAccessControl implements AccessControl
private static final Logger _logger = Logger.getLogger(DefaultAccessControl.class);
private RuleSet _ruleSet;
+ private File _aclFile;
public DefaultAccessControl(String fileName)
{
@@ -51,10 +53,8 @@ public class DefaultAccessControl implements AccessControl
{
_logger.debug("Creating AccessControl instance using file: " + fileName);
}
- File aclFile = new File(fileName);
- ConfigurationFile configFile = new PlainConfiguration(aclFile);
- _ruleSet = configFile.load();
+ _aclFile = new File(fileName);
}
DefaultAccessControl(RuleSet rs) throws ConfigurationException
@@ -62,6 +62,45 @@ public class DefaultAccessControl implements AccessControl
_ruleSet = rs;
}
+ public void open()
+ {
+ if(_aclFile != null)
+ {
+ if (!_aclFile.exists())
+ {
+ throw new IllegalConfigurationException("ACL file '" + _aclFile + "' is not found");
+ }
+
+ ConfigurationFile configFile = new PlainConfiguration(_aclFile);
+ _ruleSet = configFile.load();
+ }
+ }
+
+ @Override
+ public void close()
+ {
+ //no-op
+ }
+
+ @Override
+ public void onDelete()
+ {
+ //no-op
+ }
+
+ @Override
+ public void onCreate()
+ {
+ //verify file exists
+ if(_aclFile != null)
+ {
+ if (!_aclFile.exists())
+ {
+ throw new IllegalConfigurationException("ACL file '" + _aclFile + "' is not found");
+ }
+ }
+ }
+
public Result getDefault()
{
return _ruleSet.getDefault();
@@ -119,4 +158,5 @@ public class DefaultAccessControl implements AccessControl
return Result.DENIED;
}
}
+
}
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java
index a3d7823caf..f4e041a8d2 100644
--- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java
+++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java
@@ -20,40 +20,60 @@
*/
package org.apache.qpid.server.security.access.plugins;
-import java.io.File;
+import static org.apache.qpid.server.security.access.FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE;
+import static org.apache.qpid.server.security.access.FileAccessControlProviderConstants.PATH;
+import static org.apache.qpid.server.util.MapValueConverter.getStringAttribute;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Map;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.plugin.AccessControlFactory;
import org.apache.qpid.server.security.AccessControl;
+import org.apache.qpid.server.util.ResourceBundleLoader;
public class DefaultAccessControlFactory implements AccessControlFactory
{
- public static final String ATTRIBUTE_ACL_FILE = "aclFile";
+ public static final String RESOURCE_BUNDLE = "org.apache.qpid.server.security.access.plugins.FileAccessControlProviderAttributeDescriptions";
+
+ public static final Collection<String> ATTRIBUTES = Collections.<String> unmodifiableList(Arrays.asList(
+ ATTRIBUTE_TYPE,
+ PATH
+ ));
- public AccessControl createInstance(Map<String, Object> aclConfiguration)
+ public AccessControl createInstance(Map<String, Object> attributes)
{
- if (aclConfiguration != null)
+ if(attributes == null || !ACL_FILE_PROVIDER_TYPE.equals(attributes.get(ATTRIBUTE_TYPE)))
+ {
+ return null;
+ }
+
+ String path = getStringAttribute(PATH, attributes, null);
+ if (path == null || "".equals(path.trim()))
{
- Object aclFile = aclConfiguration.get(ATTRIBUTE_ACL_FILE);
- if (aclFile != null)
- {
- if (aclFile instanceof String)
- {
- String aclPath = (String) aclFile;
- if (!new File(aclPath).exists())
- {
- throw new IllegalConfigurationException("ACL file '" + aclPath + "' is not found");
- }
- return new DefaultAccessControl(aclPath);
- }
- else
- {
- throw new IllegalConfigurationException("Expected '" + ATTRIBUTE_ACL_FILE + "' attribute value of type String but was " + aclFile.getClass()
- + ": " + aclFile);
- }
- }
+ throw new IllegalConfigurationException("Path to ACL was not specified!");
}
- return null;
+
+ return new DefaultAccessControl(path);
+ }
+
+ @Override
+ public String getType()
+ {
+ return ACL_FILE_PROVIDER_TYPE;
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return ATTRIBUTES;
+ }
+
+ @Override
+ public Map<String, String> getAttributeDescriptions()
+ {
+ return ResourceBundleLoader.getResources(RESOURCE_BUNDLE);
}
}
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/FileAccessControlProviderAttributeDescriptions.properties b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/FileAccessControlProviderAttributeDescriptions.properties
new file mode 100644
index 0000000000..e847e90f57
--- /dev/null
+++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/FileAccessControlProviderAttributeDescriptions.properties
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+path=File location* \ No newline at end of file
diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java
index ca1f19098f..2c55652f04 100644
--- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java
+++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java
@@ -6,7 +6,9 @@ import java.util.Map;
import java.util.regex.Pattern;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.model.GroupProvider;
import org.apache.qpid.server.security.AccessControl;
+import org.apache.qpid.server.security.access.FileAccessControlProviderConstants;
import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.test.utils.TestFileUtils;
@@ -25,8 +27,10 @@ public class DefaultAccessControlFactoryTest extends QpidTestCase
File aclFile = TestFileUtils.createTempFile(this, ".acl", "ACL ALLOW all all");
DefaultAccessControlFactory factory = new DefaultAccessControlFactory();
Map<String, Object> attributes = new HashMap<String, Object>();
- attributes.put(DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE, aclFile.getAbsolutePath());
+ attributes.put(GroupProvider.TYPE, FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE);
+ attributes.put(FileAccessControlProviderConstants.PATH, aclFile.getAbsolutePath());
AccessControl acl = factory.createInstance(attributes);
+ acl.open();
assertNotNull("ACL was not created from acl file: " + aclFile.getAbsolutePath(), acl);
}
@@ -37,33 +41,17 @@ public class DefaultAccessControlFactoryTest extends QpidTestCase
assertFalse("ACL file " + aclFile.getAbsolutePath() + " actually exists but should not", aclFile.exists());
DefaultAccessControlFactory factory = new DefaultAccessControlFactory();
Map<String, Object> attributes = new HashMap<String, Object>();
- attributes.put(DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE, aclFile.getAbsolutePath());
+ attributes.put(GroupProvider.TYPE, FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE);
+ attributes.put(FileAccessControlProviderConstants.PATH, aclFile.getAbsolutePath());
try
{
- factory.createInstance(attributes);
- fail("It should not be possible to create ACL from non existing file");
+ AccessControl control = factory.createInstance(attributes);
+ control.open();
+ fail("It should not be possible to create and initialise ACL with non existing file");
}
catch (IllegalConfigurationException e)
{
- assertTrue("Unexpected exception message", Pattern.matches("ACL file '.*' is not found", e.getMessage()));
- }
- }
-
- public void testCreateInstanceWhenAclFileIsSpecifiedAsNonString()
- {
- DefaultAccessControlFactory factory = new DefaultAccessControlFactory();
- Map<String, Object> attributes = new HashMap<String, Object>();
- Integer aclFile = new Integer(0);
- attributes.put(DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE, aclFile);
- try
- {
- factory.createInstance(attributes);
- fail("It should not be possible to create ACL from Integer");
- }
- catch (IllegalConfigurationException e)
- {
- assertEquals("Unexpected exception message", "Expected '" + DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE
- + "' attribute value of type String but was " + Integer.class + ": " + aclFile, e.getMessage());
+ assertTrue("Unexpected exception message: " + e.getMessage(), Pattern.matches("ACL file '.*' is not found", e.getMessage()));
}
}
}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
index 5f281504e9..2fc54482a4 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
@@ -22,8 +22,10 @@ package org.apache.qpid.server.management.plugin;
import java.io.File;
import java.lang.reflect.Type;
+import java.net.SocketAddress;
import java.util.Collection;
import java.util.Collections;
+import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -33,9 +35,10 @@ import org.apache.log4j.Logger;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
+import org.apache.qpid.server.management.plugin.filter.ForbiddingAuthorisationFilter;
+import org.apache.qpid.server.management.plugin.filter.RedirectingAuthorisationFilter;
import org.apache.qpid.server.management.plugin.servlet.DefinedFileServlet;
import org.apache.qpid.server.management.plugin.servlet.FileServlet;
-import org.apache.qpid.server.management.plugin.servlet.rest.AbstractServlet;
import org.apache.qpid.server.management.plugin.servlet.rest.HelperServlet;
import org.apache.qpid.server.management.plugin.servlet.rest.LogRecordsServlet;
import org.apache.qpid.server.management.plugin.servlet.rest.LogoutServlet;
@@ -44,6 +47,7 @@ import org.apache.qpid.server.management.plugin.servlet.rest.MessageServlet;
import org.apache.qpid.server.management.plugin.servlet.rest.RestServlet;
import org.apache.qpid.server.management.plugin.servlet.rest.SaslServlet;
import org.apache.qpid.server.management.plugin.servlet.rest.StructureServlet;
+import org.apache.qpid.server.model.AccessControlProvider;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Binding;
import org.apache.qpid.server.model.Broker;
@@ -60,21 +64,25 @@ import org.apache.qpid.server.model.Protocol;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.model.Session;
import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.model.User;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.model.adapter.AbstractPluginAdapter;
import org.apache.qpid.server.plugin.PluginFactory;
+import org.apache.qpid.server.security.SubjectCreator;
import org.apache.qpid.server.util.MapValueConverter;
import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.SessionManager;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
+import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
-public class HttpManagement extends AbstractPluginAdapter
+public class HttpManagement extends AbstractPluginAdapter implements HttpManagementConfiguration
{
private final Logger _logger = Logger.getLogger(HttpManagement.class);
@@ -105,8 +113,6 @@ public class HttpManagement extends AbstractPluginAdapter
add(PluginFactory.PLUGIN_TYPE);
}});
- public static final String ENTRY_POINT_PATH = "/management";
-
private static final String OPERATIONAL_LOGGING_NAME = "Web";
@@ -238,7 +244,7 @@ public class HttpManagement extends AbstractPluginAdapter
}
else if (protocols.contains(Protocol.HTTPS))
{
- KeyStore keyStore = _broker.getDefaultKeyStore();
+ KeyStore keyStore = port.getKeyStore();
if (keyStore == null)
{
throw new IllegalConfigurationException("Key store is not configured. Cannot start management on HTTPS port without keystore");
@@ -266,12 +272,19 @@ public class HttpManagement extends AbstractPluginAdapter
server.setHandler(root);
// set servlet context attributes for broker and configuration
- root.getServletContext().setAttribute(AbstractServlet.ATTR_BROKER, _broker);
- root.getServletContext().setAttribute(AbstractServlet.ATTR_MANAGEMENT, this);
+ root.getServletContext().setAttribute(HttpManagementUtil.ATTR_BROKER, _broker);
+ root.getServletContext().setAttribute(HttpManagementUtil.ATTR_MANAGEMENT_CONFIGURATION, this);
+
+ FilterHolder restAuthorizationFilter = new FilterHolder(new ForbiddingAuthorisationFilter());
+ restAuthorizationFilter.setInitParameter(ForbiddingAuthorisationFilter.INIT_PARAM_ALLOWED, "/rest/sasl");
+ root.addFilter(restAuthorizationFilter, "/rest/*", EnumSet.of(DispatcherType.REQUEST));
+ root.addFilter(new FilterHolder(new RedirectingAuthorisationFilter()), HttpManagementUtil.ENTRY_POINT_PATH, EnumSet.of(DispatcherType.REQUEST));
+ root.addFilter(new FilterHolder(new RedirectingAuthorisationFilter()), "/index.html", EnumSet.of(DispatcherType.REQUEST));
addRestServlet(root, "broker");
addRestServlet(root, "virtualhost", VirtualHost.class);
addRestServlet(root, "authenticationprovider", AuthenticationProvider.class);
+ addRestServlet(root, "accesscontrolprovider", AccessControlProvider.class);
addRestServlet(root, "user", AuthenticationProvider.class, User.class);
addRestServlet(root, "groupprovider", GroupProvider.class);
addRestServlet(root, "group", GroupProvider.class, Group.class);
@@ -282,6 +295,8 @@ public class HttpManagement extends AbstractPluginAdapter
addRestServlet(root, "binding", VirtualHost.class, Exchange.class, Queue.class, Binding.class);
addRestServlet(root, "port", Port.class);
addRestServlet(root, "session", VirtualHost.class, Connection.class, Session.class);
+ addRestServlet(root, "keystore", KeyStore.class);
+ addRestServlet(root, "truststore", TrustStore.class);
root.addServlet(new ServletHolder(new StructureServlet()), "/rest/structure");
root.addServlet(new ServletHolder(new MessageServlet()), "/rest/message/*");
@@ -291,7 +306,7 @@ public class HttpManagement extends AbstractPluginAdapter
root.addServlet(new ServletHolder(new SaslServlet()), "/rest/sasl");
- root.addServlet(new ServletHolder(new DefinedFileServlet("index.html")), ENTRY_POINT_PATH);
+ root.addServlet(new ServletHolder(new DefinedFileServlet("index.html")), HttpManagementUtil.ENTRY_POINT_PATH);
root.addServlet(new ServletHolder(new LogoutServlet()), "/logout");
root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.js");
@@ -396,24 +411,34 @@ public class HttpManagement extends AbstractPluginAdapter
return Collections.unmodifiableCollection(AVAILABLE_ATTRIBUTES);
}
+ @Override
public boolean isHttpsSaslAuthenticationEnabled()
{
return (Boolean)getAttribute(HTTPS_SASL_AUTHENTICATION_ENABLED);
}
+ @Override
public boolean isHttpSaslAuthenticationEnabled()
{
return (Boolean)getAttribute(HTTP_SASL_AUTHENTICATION_ENABLED);
}
+ @Override
public boolean isHttpsBasicAuthenticationEnabled()
{
return (Boolean)getAttribute(HTTPS_BASIC_AUTHENTICATION_ENABLED);
}
+ @Override
public boolean isHttpBasicAuthenticationEnabled()
{
return (Boolean)getAttribute(HTTP_BASIC_AUTHENTICATION_ENABLED);
}
+ @Override
+ public SubjectCreator getSubjectCreator(SocketAddress localAddress)
+ {
+ return _broker.getSubjectCreator(localAddress);
+ }
+
}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java
new file mode 100644
index 0000000000..56919e2e6b
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java
@@ -0,0 +1,38 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin;
+
+import java.net.SocketAddress;
+
+import org.apache.qpid.server.security.SubjectCreator;
+
+public interface HttpManagementConfiguration
+{
+ boolean isHttpsSaslAuthenticationEnabled();
+
+ boolean isHttpSaslAuthenticationEnabled();
+
+ boolean isHttpsBasicAuthenticationEnabled();
+
+ boolean isHttpBasicAuthenticationEnabled();
+
+ SubjectCreator getSubjectCreator(SocketAddress localAddress);
+}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java
new file mode 100644
index 0000000000..4c6e5bf63e
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java
@@ -0,0 +1,225 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.security.AccessControlException;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import javax.security.auth.Subject;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.actors.HttpManagementActor;
+import org.apache.qpid.server.management.plugin.session.LoginLogoutReporter;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.security.SubjectCreator;
+import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
+import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
+
+public class HttpManagementUtil
+{
+
+ /**
+ * Servlet context attribute holding a reference to a broker instance
+ */
+ public static final String ATTR_BROKER = "Qpid.broker";
+
+ /**
+ * Servlet context attribute holding a reference to plugin configuration
+ */
+ public static final String ATTR_MANAGEMENT_CONFIGURATION = "Qpid.managementConfiguration";
+
+ /**
+ * Default management entry URL
+ */
+ public static final String ENTRY_POINT_PATH = "/management";
+
+ private static final String ATTR_LOGIN_LOGOUT_REPORTER = "Qpid.loginLogoutReporter";
+ private static final String ATTR_SUBJECT = "Qpid.subject";
+ private static final String ATTR_LOG_ACTOR = "Qpid.logActor";
+
+ public static Broker getBroker(ServletContext servletContext)
+ {
+ return (Broker) servletContext.getAttribute(ATTR_BROKER);
+ }
+
+ public static HttpManagementConfiguration getManagementConfiguration(ServletContext servletContext)
+ {
+ return (HttpManagementConfiguration) servletContext.getAttribute(ATTR_MANAGEMENT_CONFIGURATION);
+ }
+
+ public static SocketAddress getSocketAddress(HttpServletRequest request)
+ {
+ return InetSocketAddress.createUnresolved(request.getServerName(), request.getServerPort());
+ }
+
+ public static Subject getAuthorisedSubject(HttpSession session)
+ {
+ return (Subject) session.getAttribute(ATTR_SUBJECT);
+ }
+
+ public static void checkRequestAuthenticatedAndAccessAuthorized(HttpServletRequest request, Broker broker,
+ HttpManagementConfiguration managementConfig)
+ {
+ HttpSession session = request.getSession();
+ Subject subject = getAuthorisedSubject(session);
+ if (subject == null)
+ {
+ subject = tryToAuthenticate(request, managementConfig);
+ if (subject == null)
+ {
+ throw new SecurityException("Only authenticated users can access the management interface");
+ }
+ LogActor actor = createHttpManagementActor(broker, request);
+ if (hasAccessToManagement(broker.getSecurityManager(), subject, actor))
+ {
+ saveAuthorisedSubject(session, subject, actor);
+ }
+ else
+ {
+ throw new AccessControlException("Access to the management interface denied");
+ }
+ }
+ }
+
+ public static boolean hasAccessToManagement(final SecurityManager securityManager, Subject subject, LogActor actor)
+ {
+ // TODO: We should eliminate SecurityManager.setThreadSubject in favour of Subject.doAs
+ SecurityManager.setThreadSubject(subject); // Required for accessManagement check
+ CurrentActor.set(actor);
+ try
+ {
+ try
+ {
+ return Subject.doAs(subject, new PrivilegedExceptionAction<Boolean>()
+ {
+ @Override
+ public Boolean run() throws Exception
+ {
+ return securityManager.accessManagement();
+ }
+ });
+ }
+ catch (PrivilegedActionException e)
+ {
+ throw new RuntimeException("Unable to perform access check", e);
+ }
+ }
+ finally
+ {
+ try
+ {
+ CurrentActor.remove();
+ }
+ finally
+ {
+ SecurityManager.setThreadSubject(null);
+ }
+ }
+ }
+
+ public static HttpManagementActor getOrCreateAndCacheLogActor(HttpServletRequest request, Broker broker)
+ {
+ HttpSession session = request.getSession();
+ HttpManagementActor actor = (HttpManagementActor) session.getAttribute(ATTR_LOG_ACTOR);
+ if (actor == null)
+ {
+ actor = createHttpManagementActor(broker, request);
+ session.setAttribute(ATTR_LOG_ACTOR, actor);
+ }
+ return actor;
+ }
+
+ public static void saveAuthorisedSubject(HttpSession session, Subject subject, LogActor logActor)
+ {
+ session.setAttribute(ATTR_SUBJECT, subject);
+
+ // Cause the user logon to be logged.
+ session.setAttribute(ATTR_LOGIN_LOGOUT_REPORTER, new LoginLogoutReporter(logActor, subject));
+ }
+
+ private static Subject tryToAuthenticate(HttpServletRequest request, HttpManagementConfiguration managementConfig)
+ {
+ Subject subject = null;
+ SocketAddress localAddress = getSocketAddress(request);
+ SubjectCreator subjectCreator = managementConfig.getSubjectCreator(localAddress);
+ String remoteUser = request.getRemoteUser();
+
+ if (remoteUser != null || subjectCreator.isAnonymousAuthenticationAllowed())
+ {
+ subject = authenticateUser(subjectCreator, remoteUser, null);
+ }
+ else
+ {
+ String header = request.getHeader("Authorization");
+ if (header != null)
+ {
+ String[] tokens = header.split("\\s");
+ if (tokens.length >= 2 && "BASIC".equalsIgnoreCase(tokens[0]))
+ {
+ boolean isBasicAuthSupported = false;
+ if (request.isSecure())
+ {
+ isBasicAuthSupported = managementConfig.isHttpsBasicAuthenticationEnabled();
+ }
+ else
+ {
+ isBasicAuthSupported = managementConfig.isHttpBasicAuthenticationEnabled();
+ }
+ if (isBasicAuthSupported)
+ {
+ String base64UsernameAndPassword = tokens[1];
+ String[] credentials = (new String(Base64.decodeBase64(base64UsernameAndPassword.getBytes()))).split(":", 2);
+ if (credentials.length == 2)
+ {
+ subject = authenticateUser(subjectCreator, credentials[0], credentials[1]);
+ }
+ }
+ }
+ }
+ }
+ return subject;
+ }
+
+ private static Subject authenticateUser(SubjectCreator subjectCreator, String username, String password)
+ {
+ SubjectAuthenticationResult authResult = subjectCreator.authenticate(username, password);
+ if (authResult.getStatus() == AuthenticationStatus.SUCCESS)
+ {
+ return authResult.getSubject();
+ }
+ return null;
+ }
+
+ private static HttpManagementActor createHttpManagementActor(Broker broker, HttpServletRequest request)
+ {
+ return new HttpManagementActor(broker.getRootMessageLogger(), request.getRemoteAddr(), request.getRemotePort());
+ }
+
+}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/ForbiddingAuthorisationFilter.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/ForbiddingAuthorisationFilter.java
new file mode 100644
index 0000000000..b7f4b347c7
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/ForbiddingAuthorisationFilter.java
@@ -0,0 +1,73 @@
+package org.apache.qpid.server.management.plugin.filter;
+
+import java.io.IOException;
+import java.security.AccessControlException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.qpid.server.management.plugin.HttpManagementConfiguration;
+import org.apache.qpid.server.management.plugin.HttpManagementUtil;
+import org.apache.qpid.server.model.Broker;
+
+public class ForbiddingAuthorisationFilter implements Filter
+{
+ public static String INIT_PARAM_ALLOWED = "allowed";
+ private String _allowed = null;
+
+ private Broker _broker;
+ private HttpManagementConfiguration _managementConfiguration;
+
+ @Override
+ public void destroy()
+ {
+ }
+
+ @Override
+ public void init(FilterConfig config) throws ServletException
+ {
+ String allowed = config.getInitParameter(INIT_PARAM_ALLOWED);
+ if (allowed != null)
+ {
+ _allowed = allowed;
+ }
+ ServletContext servletContext = config.getServletContext();
+ _broker = HttpManagementUtil.getBroker(servletContext);
+ _managementConfiguration = HttpManagementUtil.getManagementConfiguration(servletContext);
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
+ ServletException
+ {
+ HttpServletRequest httpRequest = (HttpServletRequest) request;
+ HttpServletResponse httpResponse = (HttpServletResponse) response;
+ String servletPath = httpRequest.getServletPath();
+ if (_allowed == null || "".equals(_allowed) || servletPath.indexOf(_allowed) == -1)
+ {
+ try
+ {
+ HttpManagementUtil.checkRequestAuthenticatedAndAccessAuthorized(httpRequest, _broker, _managementConfiguration);
+ }
+ catch(AccessControlException e)
+ {
+ httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+ catch(SecurityException e)
+ {
+ httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ return;
+ }
+ }
+ chain.doFilter(request, response);
+ }
+
+}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/RedirectingAuthorisationFilter.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/RedirectingAuthorisationFilter.java
new file mode 100644
index 0000000000..c5e9890620
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/RedirectingAuthorisationFilter.java
@@ -0,0 +1,83 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.filter;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.qpid.server.management.plugin.HttpManagementConfiguration;
+import org.apache.qpid.server.management.plugin.HttpManagementUtil;
+import org.apache.qpid.server.model.Broker;
+
+public class RedirectingAuthorisationFilter implements Filter
+{
+ public static String DEFAULT_LOGIN_URL = "login.html";
+ public static String INIT_PARAM_LOGIN_URL = "login-url";
+
+ private String _loginUrl = DEFAULT_LOGIN_URL;
+ private Broker _broker;
+ private HttpManagementConfiguration _managementConfiguration;
+
+ @Override
+ public void destroy()
+ {
+ }
+
+ @Override
+ public void init(FilterConfig config) throws ServletException
+ {
+ String loginlUrl = config.getInitParameter(INIT_PARAM_LOGIN_URL);
+ if (loginlUrl != null)
+ {
+ _loginUrl = loginlUrl;
+ }
+ ServletContext servletContext = config.getServletContext();
+ _broker = HttpManagementUtil.getBroker(servletContext);
+ _managementConfiguration = HttpManagementUtil.getManagementConfiguration(servletContext);
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
+ ServletException
+ {
+ HttpServletRequest httpRequest = (HttpServletRequest) request;
+ HttpServletResponse httpResponse = (HttpServletResponse) response;
+ try
+ {
+ HttpManagementUtil.checkRequestAuthenticatedAndAccessAuthorized(httpRequest, _broker, _managementConfiguration);
+ chain.doFilter(request, response);
+ }
+ catch(SecurityException e)
+ {
+ httpResponse.sendRedirect(_loginUrl);
+ }
+ }
+
+}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
index 689bdb50d8..9614ded3d8 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
@@ -21,9 +21,6 @@
package org.apache.qpid.server.management.plugin.servlet.rest;
import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.security.AccessControlException;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
@@ -34,44 +31,22 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.logging.LogActor;
-import org.apache.qpid.server.logging.RootMessageLogger;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.HttpManagementActor;
-import org.apache.qpid.server.management.plugin.HttpManagement;
-import org.apache.qpid.server.management.plugin.session.LoginLogoutReporter;
+import org.apache.qpid.server.management.plugin.HttpManagementConfiguration;
+import org.apache.qpid.server.management.plugin.HttpManagementUtil;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.SubjectCreator;
-import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
-import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
-import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager;
public abstract class AbstractServlet extends HttpServlet
{
private static final Logger LOGGER = Logger.getLogger(AbstractServlet.class);
- /**
- * Servlet context attribute holding a reference to a broker instance
- */
- public static final String ATTR_BROKER = "Qpid.broker";
-
- /**
- * Servlet context attribute holding a reference to plugin configuration
- */
- public static final String ATTR_MANAGEMENT = "Qpid.management";
-
- private static final String ATTR_LOGIN_LOGOUT_REPORTER = "AbstractServlet.loginLogoutReporter";
- private static final String ATTR_SUBJECT = "AbstractServlet.subject";
- private static final String ATTR_LOG_ACTOR = "AbstractServlet.logActor";
-
private Broker _broker;
- private RootMessageLogger _rootLogger;
- private HttpManagement _httpManagement;
+ private HttpManagementConfiguration _managementConfiguration;
protected AbstractServlet()
{
@@ -83,9 +58,8 @@ public abstract class AbstractServlet extends HttpServlet
{
ServletConfig servletConfig = getServletConfig();
ServletContext servletContext = servletConfig.getServletContext();
- _broker = (Broker)servletContext.getAttribute(ATTR_BROKER);
- _rootLogger = _broker.getRootMessageLogger();
- _httpManagement = (HttpManagement)servletContext.getAttribute(ATTR_MANAGEMENT);
+ _broker = HttpManagementUtil.getBroker(servletContext);
+ _managementConfiguration = HttpManagementUtil.getManagementConfiguration(servletContext);
super.init();
}
@@ -211,18 +185,18 @@ public abstract class AbstractServlet extends HttpServlet
Subject subject;
try
{
- subject = getAndCacheAuthorizedSubject(request);
+ subject = getAuthorisedSubject(request);
}
- catch (AccessControlException e)
+ catch (SecurityException e)
{
- sendError(resp, HttpServletResponse.SC_FORBIDDEN);
+ sendError(resp, HttpServletResponse.SC_UNAUTHORIZED);
return;
}
SecurityManager.setThreadSubject(subject);
try
{
- HttpManagementActor logActor = getLogActorAndCacheInSession(request);
+ HttpManagementActor logActor = HttpManagementUtil.getOrCreateAndCacheLogActor(request, _broker);
CurrentActor.set(logActor);
try
{
@@ -256,187 +230,24 @@ public abstract class AbstractServlet extends HttpServlet
}
}
- /**
- * Gets the logged-in {@link Subject} by trying the following:
- *
- * <ul>
- * <li>Get it from the session</li>
- * <li>Get it from the request</li>
- * <li>Log in using the username and password in the Authorization HTTP header</li>
- * <li>Create a Subject representing the anonymous user.</li>
- * </ul>
- *
- * If an authenticated subject is found it is cached in the http session.
- */
- private Subject getAndCacheAuthorizedSubject(HttpServletRequest request)
+ protected Subject getAuthorisedSubject(HttpServletRequest request)
{
- HttpSession session = request.getSession();
- Subject subject = getAuthorisedSubjectFromSession(session);
-
- if(subject != null)
- {
- return subject;
- }
-
- SubjectCreator subjectCreator = getSubjectCreator(request);
- subject = authenticate(request, subjectCreator);
- if (subject != null)
+ Subject subject = HttpManagementUtil.getAuthorisedSubject(request.getSession());
+ if (subject == null)
{
- authoriseManagement(request, subject);
- setAuthorisedSubjectInSession(subject, request, session);
+ throw new SecurityException("Access to management rest interfaces is denied for un-authorised user");
}
- else
- {
- subject = subjectCreator.createSubjectWithGroups(AnonymousAuthenticationManager.ANONYMOUS_USERNAME);
- }
-
return subject;
}
- protected void authoriseManagement(HttpServletRequest request, Subject subject)
- {
- // TODO: We should eliminate SecurityManager.setThreadSubject in favour of Subject.doAs
- SecurityManager.setThreadSubject(subject); // Required for accessManagement check
- LogActor actor = createHttpManagementActor(request);
- CurrentActor.set(actor);
- try
- {
- try
- {
- Subject.doAs(subject, new PrivilegedExceptionAction<Void>() // Required for proper logging of Subject
- {
- @Override
- public Void run() throws Exception
- {
- boolean allowed = getSecurityManager().accessManagement();
- if (!allowed)
- {
- throw new AccessControlException("User is not authorised for management");
- }
- return null;
- }
- });
- }
- catch (PrivilegedActionException e)
- {
- throw new RuntimeException("Unable to perform access check", e);
- }
- }
- finally
- {
- try
- {
- CurrentActor.remove();
- }
- finally
- {
- SecurityManager.setThreadSubject(null);
- }
- }
- }
-
- private Subject authenticate(HttpServletRequest request, SubjectCreator subjectCreator)
- {
- Subject subject = null;
-
- String remoteUser = request.getRemoteUser();
- if(remoteUser != null)
- {
- subject = authenticateUserAndGetSubject(subjectCreator, remoteUser, null);
- }
- else
- {
- String header = request.getHeader("Authorization");
-
- if (header != null)
- {
- String[] tokens = header.split("\\s");
- if(tokens.length >= 2 && "BASIC".equalsIgnoreCase(tokens[0]))
- {
- if(!isBasicAuthSupported(request))
- {
- //TODO: write a return response indicating failure?
- throw new IllegalArgumentException("BASIC Authorization is not enabled.");
- }
-
- subject = performBasicAuth(subject, subjectCreator, tokens[1]);
- }
- }
- }
-
- return subject;
- }
-
- private Subject performBasicAuth(Subject subject,SubjectCreator subjectCreator, String base64UsernameAndPassword)
- {
- String[] credentials = (new String(Base64.decodeBase64(base64UsernameAndPassword.getBytes()))).split(":",2);
- if(credentials.length == 2)
- {
- subject = authenticateUserAndGetSubject(subjectCreator, credentials[0], credentials[1]);
- }
- else
- {
- //TODO: write a return response indicating failure?
- throw new AccessControlException("Invalid number of credentials supplied: "
- + credentials.length);
- }
- return subject;
- }
-
- private Subject authenticateUserAndGetSubject(SubjectCreator subjectCreator, String username, String password)
- {
- SubjectAuthenticationResult authResult = subjectCreator.authenticate(username, password);
- if( authResult.getStatus() != AuthenticationStatus.SUCCESS)
- {
- //TODO: write a return response indicating failure?
- throw new AccessControlException("Incorrect username or password");
- }
- Subject subject = authResult.getSubject();
- return subject;
- }
-
- private boolean isBasicAuthSupported(HttpServletRequest req)
- {
- return req.isSecure() ? _httpManagement.isHttpsBasicAuthenticationEnabled()
- : _httpManagement.isHttpBasicAuthenticationEnabled();
- }
-
- private HttpManagementActor getLogActorAndCacheInSession(HttpServletRequest req)
- {
- HttpSession session = req.getSession();
-
- HttpManagementActor actor = (HttpManagementActor) session.getAttribute(ATTR_LOG_ACTOR);
- if(actor == null)
- {
- actor = createHttpManagementActor(req);
- session.setAttribute(ATTR_LOG_ACTOR, actor);
- }
-
- return actor;
- }
-
- protected Subject getAuthorisedSubjectFromSession(HttpSession session)
- {
- return (Subject)session.getAttribute(ATTR_SUBJECT);
- }
-
- protected void setAuthorisedSubjectInSession(Subject subject, HttpServletRequest request, final HttpSession session)
- {
- session.setAttribute(ATTR_SUBJECT, subject);
-
- LogActor logActor = createHttpManagementActor(request);
- // Cause the user logon to be logged.
- session.setAttribute(ATTR_LOGIN_LOGOUT_REPORTER, new LoginLogoutReporter(logActor, subject));
- }
-
protected Broker getBroker()
{
return _broker;
}
- protected SocketAddress getSocketAddress(HttpServletRequest request)
+ protected HttpManagementConfiguration getManagementConfiguration()
{
- return InetSocketAddress.createUnresolved(request.getServerName(), request.getServerPort());
+ return _managementConfiguration;
}
protected void sendError(final HttpServletResponse resp, int errorCode)
@@ -450,24 +261,4 @@ public abstract class AbstractServlet extends HttpServlet
throw new RuntimeException("Failed to send error response code " + errorCode, e);
}
}
-
- private HttpManagementActor createHttpManagementActor(HttpServletRequest request)
- {
- return new HttpManagementActor(_rootLogger, request.getRemoteAddr(), request.getRemotePort());
- }
-
- protected HttpManagement getManagement()
- {
- return _httpManagement;
- }
-
- protected SecurityManager getSecurityManager()
- {
- return _broker.getSecurityManager();
- }
-
- protected SubjectCreator getSubjectCreator(HttpServletRequest request)
- {
- return _broker.getSubjectCreator(getSocketAddress(request));
- }
}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java
index 3c6fb1c44d..a7066c73d8 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java
@@ -31,9 +31,10 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.qpid.server.management.plugin.servlet.rest.action.ListAccessControlProviderAttributes;
import org.apache.qpid.server.management.plugin.servlet.rest.action.ListAuthenticationProviderAttributes;
+import org.apache.qpid.server.management.plugin.servlet.rest.action.ListGroupProviderAttributes;
import org.apache.qpid.server.management.plugin.servlet.rest.action.ListMessageStoreTypes;
-import org.apache.qpid.server.model.Broker;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
@@ -53,6 +54,10 @@ public class HelperServlet extends AbstractServlet
_actions.put(listProviderAttributes.getName(), listProviderAttributes);
Action listMessageStoreTypes = new ListMessageStoreTypes();
_actions.put(listMessageStoreTypes.getName(), listMessageStoreTypes);
+ Action groupProviderAttributes = new ListGroupProviderAttributes();
+ _actions.put(groupProviderAttributes.getName(), groupProviderAttributes);
+ Action aclProviderAttributes = new ListAccessControlProviderAttributes();
+ _actions.put(aclProviderAttributes.getName(), aclProviderAttributes);
}
@Override
@@ -96,7 +101,7 @@ public class HelperServlet extends AbstractServlet
}
}
- Object output = action.perform(parameters, (Broker) getServletContext().getAttribute(ATTR_BROKER));
+ Object output = action.perform(parameters, getBroker());
if (output == null)
{
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogoutServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogoutServlet.java
index 4188e7d60d..34b115ed13 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogoutServlet.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogoutServlet.java
@@ -29,13 +29,13 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
-import org.apache.qpid.server.management.plugin.HttpManagement;
+import org.apache.qpid.server.management.plugin.HttpManagementUtil;
@SuppressWarnings("serial")
public class LogoutServlet extends HttpServlet
{
public static final String RETURN_URL_INIT_PARAM = "qpid.webui_logout_redirect";
- private String _returnUrl = HttpManagement.ENTRY_POINT_PATH;
+ private String _returnUrl = HttpManagementUtil.ENTRY_POINT_PATH;
@Override
public void init(ServletConfig config) throws ServletException
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
index 069132af1e..b67c83dc7a 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
@@ -25,7 +25,10 @@ import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.apache.log4j.Logger;
-import org.apache.qpid.server.management.plugin.HttpManagement;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.management.plugin.HttpManagementConfiguration;
+import org.apache.qpid.server.management.plugin.HttpManagementUtil;
+import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.security.SubjectCreator;
import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
@@ -38,7 +41,7 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
-import java.security.AccessControlException;
+import java.net.SocketAddress;
import java.security.Principal;
import java.security.SecureRandom;
import java.util.LinkedHashMap;
@@ -80,7 +83,7 @@ public class SaslServlet extends AbstractServlet
String[] mechanisms = subjectCreator.getMechanisms().split(" ");
Map<String, Object> outputObject = new LinkedHashMap<String, Object>();
- final Subject subject = getAuthorisedSubjectFromSession(session);
+ final Subject subject = getAuthorisedSubject(request);
if(subject != null)
{
Principal principal = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject);
@@ -195,8 +198,8 @@ public class SaslServlet extends AbstractServlet
private void checkSaslAuthEnabled(HttpServletRequest request)
{
- boolean saslAuthEnabled;
- HttpManagement management = getManagement();
+ boolean saslAuthEnabled = false;
+ HttpManagementConfiguration management = getManagementConfiguration();
if (request.isSecure())
{
saslAuthEnabled = management.isHttpsSaslAuthenticationEnabled();
@@ -205,7 +208,6 @@ public class SaslServlet extends AbstractServlet
{
saslAuthEnabled = management.isHttpSaslAuthenticationEnabled();
}
-
if (!saslAuthEnabled)
{
throw new RuntimeException("Sasl authentication disabled.");
@@ -227,7 +229,7 @@ public class SaslServlet extends AbstractServlet
session.removeAttribute(ATTR_ID);
session.removeAttribute(ATTR_SASL_SERVER);
session.removeAttribute(ATTR_EXPIRY);
- response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
@@ -236,17 +238,15 @@ public class SaslServlet extends AbstractServlet
{
Subject subject = subjectCreator.createSubjectWithGroups(saslServer.getAuthorizationID());
- try
- {
- authoriseManagement(request, subject);
- }
- catch (AccessControlException ace)
+ Broker broker = getBroker();
+ LogActor actor = HttpManagementUtil.getOrCreateAndCacheLogActor(request, broker);
+ if (!HttpManagementUtil.hasAccessToManagement(broker.getSecurityManager(), subject, actor))
{
sendError(response, HttpServletResponse.SC_FORBIDDEN);
return;
}
- setAuthorisedSubjectInSession(subject, request, session);
+ HttpManagementUtil.saveAuthorisedSubject(request.getSession(), subject, actor);
session.removeAttribute(ATTR_ID);
session.removeAttribute(ATTR_SASL_SERVER);
session.removeAttribute(ATTR_EXPIRY);
@@ -274,4 +274,16 @@ public class SaslServlet extends AbstractServlet
mapper.writeValue(writer, outputObject);
}
}
+
+ private SubjectCreator getSubjectCreator(HttpServletRequest request)
+ {
+ SocketAddress localAddress = HttpManagementUtil.getSocketAddress(request);
+ return HttpManagementUtil.getManagementConfiguration(getServletContext()).getSubjectCreator(localAddress);
+ }
+
+ @Override
+ protected Subject getAuthorisedSubject(HttpServletRequest request)
+ {
+ return HttpManagementUtil.getAuthorisedSubject(request.getSession());
+ }
}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListAccessControlProviderAttributes.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListAccessControlProviderAttributes.java
new file mode 100644
index 0000000000..6887217016
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListAccessControlProviderAttributes.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.management.plugin.servlet.rest.action;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.qpid.server.management.plugin.servlet.rest.Action;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.plugin.AccessControlFactory;
+import org.apache.qpid.server.plugin.QpidServiceLoader;
+
+public class ListAccessControlProviderAttributes implements Action
+{
+ private static final String ATTRIBUTES = "attributes";
+ private static final String DESCRIPTIONS = "descriptions";
+ private Map<String, AccessControlFactory> _factories;
+
+ public ListAccessControlProviderAttributes()
+ {
+ _factories = new TreeMap<String, AccessControlFactory>();
+ Iterable<AccessControlFactory> factories = new QpidServiceLoader<AccessControlFactory>()
+ .instancesOf(AccessControlFactory.class);
+ for (AccessControlFactory factory : factories)
+ {
+ _factories.put(factory.getType(), factory);
+ }
+ }
+
+ @Override
+ public String getName()
+ {
+ return ListAccessControlProviderAttributes.class.getSimpleName();
+ }
+
+ @Override
+ public Object perform(Map<String, Object> request, Broker broker)
+ {
+ Map<String, Object> attributes = new TreeMap<String, Object>();
+ for (String providerType : _factories.keySet())
+ {
+ AccessControlFactory factory = _factories.get(providerType);
+
+ Map<String, Object> data = new HashMap<String, Object>();
+ data.put(ATTRIBUTES, factory.getAttributeNames());
+ Map<String, String> resources = factory.getAttributeDescriptions();
+ if (resources != null)
+ {
+ data.put(DESCRIPTIONS, resources);
+ }
+
+ attributes.put(factory.getType(), data);
+ }
+ return attributes;
+ }
+
+}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListGroupProviderAttributes.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListGroupProviderAttributes.java
new file mode 100644
index 0000000000..d1414faa71
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListGroupProviderAttributes.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.management.plugin.servlet.rest.action;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.qpid.server.management.plugin.servlet.rest.Action;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.plugin.GroupManagerFactory;
+import org.apache.qpid.server.plugin.QpidServiceLoader;
+
+public class ListGroupProviderAttributes implements Action
+{
+ private static final String ATTRIBUTES = "attributes";
+ private static final String DESCRIPTIONS = "descriptions";
+ private Map<String, GroupManagerFactory> _factories;
+
+ public ListGroupProviderAttributes()
+ {
+ _factories = new TreeMap<String, GroupManagerFactory>();
+ Iterable<GroupManagerFactory> factories = new QpidServiceLoader<GroupManagerFactory>()
+ .instancesOf(GroupManagerFactory.class);
+ for (GroupManagerFactory factory : factories)
+ {
+ _factories.put(factory.getType(), factory);
+ }
+ }
+
+ @Override
+ public String getName()
+ {
+ return ListGroupProviderAttributes.class.getSimpleName();
+ }
+
+ @Override
+ public Object perform(Map<String, Object> request, Broker broker)
+ {
+ Map<String, Object> attributes = new TreeMap<String, Object>();
+ for (String providerType : _factories.keySet())
+ {
+ GroupManagerFactory factory = _factories.get(providerType);
+
+ Map<String, Object> data = new HashMap<String, Object>();
+ data.put(ATTRIBUTES, factory.getAttributeNames());
+ Map<String, String> resources = factory.getAttributeDescriptions();
+ if (resources != null)
+ {
+ data.put(DESCRIPTIONS, resources);
+ }
+
+ attributes.put(factory.getType(), data);
+ }
+ return attributes;
+ }
+
+}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListMessageStoreTypes.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListMessageStoreTypes.java
index 4166736c01..091068f238 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListMessageStoreTypes.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListMessageStoreTypes.java
@@ -17,7 +17,7 @@ public class ListMessageStoreTypes implements Action
@Override
public Object perform(Map<String, Object> request, Broker broker)
{
- return broker.getAttribute(Broker.SUPPORTED_STORE_TYPES);
+ return broker.getAttribute(Broker.SUPPORTED_VIRTUALHOST_STORE_TYPES);
}
}
diff --git a/qpid/java/systests/etc/config-systests.xml b/qpid/java/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/showAclFile.html
index 958aafc9da..182e651a51 100644
--- a/qpid/java/systests/etc/config-systests.xml
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/showAclFile.html
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
-
- Licensed to the Apache Software Foundation (ASF) under one
@@ -19,10 +18,7 @@
- under the License.
-
-->
-<configuration>
- <system/>
- <override>
- <xml fileName="${QPID_HOME}/${test.config}" optional="true"/>
- <xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/>
- </override>
-</configuration>
+<div class="AclFileProvider">
+ <span style="">Path:</span><span class="path" style="position:absolute; left:6em"></span>
+ <br/>
+</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addAuthenticationProvider.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addAuthenticationProvider.html
index 90dd1f1090..f4846ac556 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/addAuthenticationProvider.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addAuthenticationProvider.html
@@ -15,15 +15,16 @@
~ limitations under the License.
-->
<div class="dijitHidden">
- <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Authentication Provider'" id="addAuthenticationProvider">
+ <div data-dojo-type="dijit.Dialog" data-dojo-props="title:'Authentication Provider'" id="addAuthenticationProvider">
<form id="formAddAuthenticationProvider" method="post" dojoType="dijit.form.Form">
+ <div style="height:100px; width:420px; overflow: auto">
<table class="tableContainer-table tableContainer-table-horiz" width="100%" cellspacing="1">
<tr>
- <td class="tableContainer-labelCell" style="width: 300px;">Type*:</td>
+ <td class="tableContainer-labelCell" style="width: 200px;">Type*:</td>
<td class="tableContainer-valueCell"><div id="addAuthenticationProvider.selectAuthenticationProviderDiv"></div></td>
</tr>
<tr>
- <td class="tableContainer-labelCell" style="width: 300px;">Name*:</td>
+ <td class="tableContainer-labelCell" style="width: 200px;">Name*:</td>
<td class="tableContainer-valueCell"><input type="text" required="true" name="name"
id="formAddAuthenticationProvider.name" placeholder="Name" regexp="^[\x20-\x2e\x30-\x7F]{1,255}$"
dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" /></div></td>
@@ -31,8 +32,11 @@
</table>
<input type="hidden" id="formAddAuthenticationProvider.id" name="id"/>
<div id="addAuthenticationProvider.fieldSets"></div>
+ </div>
+ <div class="dijitDialogPaneActionBar">
<!-- submit buttons -->
<input type="submit" value="Save Authentication Provider" label="Save Authentication Provider" dojoType="dijit.form.Button" />
+ </div>
</form>
</div>
</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addBinding.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addBinding.html
index 8dbd219c8d..9aebca90d7 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/addBinding.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addBinding.html
@@ -32,11 +32,10 @@
dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" /></td>
</tr>
</table>
- <br/>
-
+ <div class="dijitDialogPaneActionBar">
<!-- submit buttons -->
<input type="submit" value="Create Binding" label="Create Binding" dojoType="dijit.form.Button" />
-
+ </div>
</form>
</div>
</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addExchange.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addExchange.html
index 4a59cd2cbc..8c9968e37a 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/addExchange.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addExchange.html
@@ -44,11 +44,10 @@
</td>
</tr>
</table>
- <br/>
-
+ <div class="dijitDialogPaneActionBar">
<!-- submit buttons -->
<input type="submit" value="Create Exchange" label="Create Exchange" dojoType="dijit.form.Button" />
-
+ </div>
</form>
</div>
</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html
index c37b879bd5..a6f3384020 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html
@@ -19,43 +19,33 @@
-
-->
<div class="dijitHidden">
- <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Port'" id="addPort">
+ <div data-dojo-type="dijit.Dialog" data-dojo-props="title:'Port'" id="addPort">
<form id="formAddPort" method="post" dojoType="dijit.form.Form">
- <div class="dijitDialogPaneContentArea">
+ <div style="height:320px; width:420px; overflow: auto">
<div id="formAddPort:fields">
<input type="text" required="true" name="name" id="formAddPort.name" placeholder="Name"
data-dojo-props="label: 'Name*:'" dojoType="dijit.form.ValidationTextBox"
missingMessage="A name must be supplied" regexp="^[\x20-\x2e\x30-\x7F]{1,255}$"/>
- <input data-dojo-type="dijit.form.NumberSpinner" id="formAddPort.port" required="true" data-dojo-props="label: 'Port Number*:'"
+ <input data-dojo-type="dijit.form.NumberSpinner" id="formAddPort.port" required="true" data-dojo-props="label: 'Port Number*:', placeHolder: 'Enter port number'"
name="port" smallDelta="1" constraints="{min:1,max:65535,places:0, pattern: '#####'}"
missingMessage="A port number must be supplied" />
- <select id="formAddPort.transports" data-dojo-type="dijit.form.FilteringSelect"
- data-dojo-props="name: 'transports',label: 'Transport:',searchAttr: 'name',required:false,placeHolder: 'TCP', value: '' "
- style="margin: 0;">
- <option value="TCP">TCP</option>
- <option value="SSL">SSL</option>
- </select>
- <select id="formAddPort.authenticationProvider" data-dojo-type="dijit.form.FilteringSelect" style="margin: 0;"
- data-dojo-props="name:'authenticationProvider',label:'Authentication Provider:', searchAttr: 'name', required: false, placeHolder: 'Default', value: '' ">
- </select>
<select id="formAddPort.type" data-dojo-type="dijit.form.FilteringSelect"
- data-dojo-props="name: 'type', value: '',placeHolder: 'Select Port Type', label: 'Port Type:'">
+ data-dojo-props="name: 'type', value: '',placeHolder: 'Select Port Type', label: 'Port Type*:'">
<option value="AMQP" selected="selected">AMQP</option>
<option value="JMX">JMX</option>
<option value="HTTP">HTTP</option>
</select>
</div>
- <div id="formAddPort:fieldsClientAuth">
- <input id="formAddPort.needClientAuth" type="checkbox" name="needClientAuth"
- dojoType="dijit.form.CheckBox" data-dojo-props="label: 'Need SSL Client Certificate:'"/>
- <input id="formAddPort.wantClientAuth" type="checkbox" name="wantClientAuth"
- dojoType="dijit.form.CheckBox" data-dojo-props="label: 'Want SSL Client Certificate:'"/>
+ <div id="formAddPort:fieldsAuthenticationProvider">
+ <select id="formAddPort.authenticationProvider" data-dojo-type="dijit.form.FilteringSelect"
+ data-dojo-props="name:'authenticationProvider',label:'Authentication Provider*:', searchAttr: 'name', required: true, placeHolder: 'Select Provider'">
+ </select>
</div>
<div id="formAddPort:fieldsAMQP">
<input id="formAddPort.bindingAddress" type="text" name="bindingAddress" placeholder="*"
dojoType="dijit.form.TextBox" data-dojo-props="label: 'Binding address:'"/>
<input id="formAddPort.protocolsDefault" type="checkbox" checked="checked"
- dojoType="dijit.form.CheckBox" data-dojo-props="label: 'Support broker default AMQP versions:'"/>
+ dojoType="dijit.form.CheckBox" data-dojo-props="label: 'Support default protocols:'"/>
<select id="formAddPort.protocolsAMQP" name="protocols" data-dojo-type="dijit.form.MultiSelect" multiple="true"
data-dojo-props="name: 'protocols', value: '', placeHolder: 'Select AMQP versions', label: 'AMQP versions:'"
missingMessage="AMQP protocol(s) must be supplied">
@@ -80,6 +70,37 @@
<option value="HTTPS">HTTPS</option>
</select>
</div>
+ <div id="formAddPort:transport" >
+ <select id="formAddPort.transports" data-dojo-type="dijit.form.FilteringSelect"
+ data-dojo-props="name: 'transports',label: 'Transport:',searchAttr: 'name',required:false,placeHolder: 'TCP', value: '' "
+ style="margin: 0;">
+ <option value="TCP">TCP</option>
+ <option value="SSL">SSL</option>
+ </select>
+ </div>
+ <div id="formAddPort:fieldsTransportSSL">
+ <select id="formAddPort.keyStore" data-dojo-type="dijit.form.FilteringSelect"
+ data-dojo-props="name:'keyStore',label:'Key Store*:', searchAttr: 'name', placeHolder: 'Select keystore', value: '', required: true ">
+ </select>
+ </div>
+ <div id="formAddPort:fieldsClientAuth">
+ <div id="formAddPort:fieldsClientAuthCheckboxes">
+ <input id="formAddPort.needClientAuth" type="checkbox" name="needClientAuth"
+ dojoType="dijit.form.CheckBox" data-dojo-props="label: 'Need SSL Client Certificate:'" />
+ <input id="formAddPort.wantClientAuth" type="checkbox" name="wantClientAuth"
+ dojoType="dijit.form.CheckBox" data-dojo-props="label: 'Want SSL Client Certificate:'" />
+ </div>
+ <div><strong>Trust Stores:</strong></div>
+ <table id="formAddPort.trustStores" data-dojo-type="dojox.grid.EnhancedGrid"
+ data-dojo-props="label:'Trust Stores:',plugins:{indirectSelection: true},rowSelector:'0px' " style="height: 100px; width:400px">
+ <thead>
+ <tr>
+ <th field="name">Name</th>
+ <th field="peersOnly">Peers Only</th>
+ </tr>
+ </thead>
+ </table>
+ </div>
<input type="hidden" id="formAddPort.id" name="id"/>
</div>
<div class="dijitDialogPaneActionBar">
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
index 950809d5fc..90a0af7ea9 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
@@ -19,8 +19,9 @@
-
-->
<div class="dijitHidden">
- <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Add Queue'" id="addQueue">
+ <div data-dojo-type="dijit.Dialog" data-dojo-props="title:'Add Queue'" id="addQueue">
<form id="formAddQueue" method="post" dojoType="dijit.form.Form">
+ <div style="height:250px; width:600px; overflow: auto">
<table cellpadding="0" cellspacing="2">
<tr>
<td valign="top"><strong>Queue Name*: </strong></td>
@@ -173,10 +174,11 @@
</tr>
</table>
</div>
- <br/>
+ </div>
+ <div class="dijitDialogPaneActionBar">
<!-- submit buttons -->
<input type="submit" value="Create Queue" label="Create Queue" dojoType="dijit.form.Button" />
-
+ </div>
</form>
</div>
</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHost.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHost.html
index 9b492ef26d..43281f600d 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHost.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHost.html
@@ -62,10 +62,11 @@
</div>
</div>
- <br/>
+ <div class="dijitDialogPaneActionBar">
<!-- submit buttons -->
<input type="submit" value="Save" label="Save" dojoType="dijit.form.Button" />
<input type="hidden" id="formAddVirtualHost.id" name="id"/>
+ </div>
</form>
</div>
</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css b/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css
index f5ca3e68dd..4c8b79ab82 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css
@@ -43,7 +43,6 @@ button {
-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;
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html
index 734e8b5419..5055cbdc47 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html
@@ -19,6 +19,8 @@
-
-->
<div class="FileGroupManager">
+ <span style="">Path:</span><span class="path" style="position:absolute; left:6em"></span>
+ <br/>
<div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Groups'">
<div class="groups"></div>
<button data-dojo-type="dijit.form.Button" class="addGroupButton">Add Group</button>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html
index 2fb9137ff8..2117ef361d 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html
@@ -24,6 +24,7 @@
<link rel="stylesheet" href="dojo/dojox/grid/resources/claroGrid.css">
<link rel="stylesheet" href="dojo/dojox/grid/enhanced/resources/claro/EnhancedGrid.css">
<link rel="stylesheet" href="dojo/dojox/grid/enhanced/resources/EnhancedGrid_rtl.css">
+ <link rel="stylesheet" href="dojo/dojox/form/resources/CheckedMultiSelect.css">
<link rel="stylesheet" href="css/common.css" media="screen">
<script>
function getContextPath()
@@ -65,7 +66,7 @@
"qpid/management/treeView",
"qpid/management/controller",
"qpid/common/footer",
- "qpid/authorization/sasl"]);
+ "qpid/authorization/checkUser"]);
</script>
</head>
@@ -74,9 +75,9 @@
<div id="pageLayout" data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design: 'headline', gutters: false">
<div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'top'">
<div id="header" class="header" style="float: left; width: 300px"></div>
- <div id="login" style="float: right"></div>
+ <div id="login" style="float: right; display:none"><strong>User: </strong> <span id="authenticatedUser"></span><a href="logout">[logout]</a></div>
</div>
- <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'leading', splitter: true">
+ <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'leading', splitter: true" style="width:20%">
<div qpid-type="treeView" qpid-props="query: 'rest/structure'" ></div>
</div>
<div id="managedViews" data-dojo-type="dijit.layout.TabContainer" data-dojo-props="region:'center', tabPosition: 'top'">
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/checkUser.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/checkUser.js
new file mode 100644
index 0000000000..3fc60854f6
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/checkUser.js
@@ -0,0 +1,36 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+require(["dojo/dom",
+ "qpid/authorization/sasl",
+ "dojo/domReady!"], function(dom, sasl){
+
+var updateUI = function updateUI(data)
+{
+ if(data.user)
+ {
+ dom.byId("authenticatedUser").innerHTML = data.user;
+ dom.byId("login").style.display = "block";
+ }
+};
+
+sasl.getUser(updateUI);
+}); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js
index b4f0728685..33e736322f 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js
@@ -18,10 +18,7 @@
* 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;
+define(["dojo/_base/xhr", "dojox/encoding/base64", "dojox/encoding/digests/_base", "dojox/encoding/digests/MD5"], function () {
var encodeUTF8 = function encodeUTF8(str) {
var byteArray = [];
@@ -49,8 +46,23 @@ var decodeUTF8 = function decodeUTF8(byteArray)
return decodeURIComponent(str);
};
+var errorHandler = function errorHandler(error)
+{
+ if(error.status == 401)
+ {
+ alert("Authentication Failed");
+ }
+ else if(error.status == 403)
+ {
+ alert("Authorization Failed");
+ }
+ else
+ {
+ alert(error);
+ }
+}
-var saslPlain = function saslPlain(user, password)
+var saslPlain = function saslPlain(user, password, callbackFunction)
{
var responseArray = [ 0 ].concat(encodeUTF8( user )).concat( [ 0 ] ).concat( encodeUTF8( password ) );
var plainResponse = dojox.encoding.base64.encode(responseArray);
@@ -65,25 +77,10 @@ var saslPlain = function saslPlain(user, password)
},
handleAs: "json",
failOk: true
- }).then(function()
- {
- updateAuthentication();
- },
- function(error)
- {
- if(error.status == 403)
- {
- alert("Authentication Failed");
- }
- else
- {
- alert(error);
- }
- updateAuthentication();
- });
+ }).then(callbackFunction, errorHandler);
};
-var saslCramMD5 = function saslCramMD5(user, password)
+var saslCramMD5 = function saslCramMD5(user, password, saslMechanism, callbackFunction)
{
// Using dojo.xhrGet, as very little information is being sent
@@ -91,7 +88,7 @@ var saslCramMD5 = function saslCramMD5(user, password)
// The URL of the request
url: "rest/sasl",
content: {
- mechanism: "CRAM-MD5"
+ mechanism: saslMechanism
},
handleAs: "json",
failOk: true
@@ -121,22 +118,7 @@ var saslCramMD5 = function saslCramMD5(user, password)
},
handleAs: "json",
failOk: true
- }).then(function()
- {
- updateAuthentication();
- },
- function(error)
- {
- if(error.status == 403)
- {
- alert("Authentication Failed");
- }
- else
- {
- alert(error);
- }
- updateAuthentication();
- });
+ }).then(callbackFunction, errorHandler);
},
function(error)
@@ -163,86 +145,45 @@ var containsMechanism = function containsMechanism(mechanisms, mech)
return false;
};
-var doAuthenticate = function doAuthenticate()
+var SaslClient = {};
+
+SaslClient.authenticate = function(username, password, callbackFunction)
{
dojo.xhrGet({
- // The URL of the request
url: "rest/sasl",
- handleAs: "json"
+ handleAs: "json",
+ failOk: true
}).then(function(data)
{
- var mechMap = data.mechanisms;
-
- if (containsMechanism(mechMap, "CRAM-MD5"))
- {
- saslCramMD5(dojo.byId("username").value, dojo.byId("pass").value);
- updateAuthentication();
- }
- else if (containsMechanism(mechMap, "PLAIN"))
- {
- saslPlain(dojo.byId("username").value, dojo.byId("pass").value);
- updateAuthentication();
- }
- else
- {
- alert("No supported SASL mechanism offered: " + mechMap);
- }
- }
- );
-
-
+ var mechMap = data.mechanisms;
+ if (containsMechanism(mechMap, "CRAM-MD5"))
+ {
+ saslCramMD5(username, password, "CRAM-MD5", callbackFunction);
+ }
+ else if (containsMechanism(mechMap, "CRAM-MD5-HEX"))
+ {
+ var hashedPassword = dojox.encoding.digests.MD5(password, dojox.encoding.digests.outputTypes.Hex);
+ saslCramMD5(username, hashedPassword, "CRAM-MD5-HEX", callbackFunction);
+ }
+ else if (containsMechanism(mechMap, "PLAIN"))
+ {
+ saslPlain(username, password, callbackFunction);
+ }
+ else
+ {
+ alert("No supported SASL mechanism offered: " + mechMap);
+ }
+ }, errorHandler);
};
-
-var updateAuthentication = function updateAuthentication()
+SaslClient.getUser = function(callbackFunction)
{
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, {display: 'none'});
- dojo.style(usernameSpan, {display: 'block'});
- }
- else
- {
- dojo.style(button.domNode, {display: 'block'});
- dojo.style(usernameSpan, {display: 'none'});
- }
- }
- );
+ handleAs: "json",
+ failOk: true
+ }).then(callbackFunction, errorHandler);
};
-require(["dijit/form/DropDownButton", "dijit/TooltipDialog", "dijit/form/TextBox", "dojo/_base/xhr", "dojo/dom", "dojo/dom-construct", "dojo/domReady!"],
- function(DropDownButton, TooltipDialog, TextBox, xhr, dom, domConstruct){
- var dialog = new TooltipDialog({
- content:
- '<strong><label for="username" style="display:inline-block;width:100px;">Username:</label></strong>' +
- '<div data-dojo-type="dijit.form.TextBox" id="username"></div><br/>' +
- '<strong><label for="pass" style="display:inline-block;width:100px;">Password:</label></strong>' +
- '<div data-dojo-type="dijit.form.TextBox" type="password" id="pass"></div><br/>' +
- '<button data-dojo-type="dijit.form.Button" data-dojo-props="onClick:doAuthenticate" type="submit">Login</button>'
- });
-
- button = new DropDownButton({
- label: "Login",
- dropDown: dialog
- });
-
- usernameSpan = domConstruct.create("span", { innerHTML: '<strong>User: </strong> <span id="authenticatedUser"></span><a href="logout">[logout]</a>',
- style: { display: "none" }});
-
-
- var loginDiv = dom.byId("login");
- loginDiv.appendChild(usernameSpan);
- loginDiv.appendChild(button.domNode);
-
-
-
-
- updateAuthentication();
-}); \ No newline at end of file
+return SaslClient;
+});
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
index 5ff208d43f..77ae1ccf47 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
@@ -33,7 +33,7 @@ define(["dojo/_base/xhr",
"dijit/form/RadioButton",
"dijit/form/CheckBox",
"dojox/layout/TableContainer",
- "dojox/layout/ScrollPane",
+ "dijit/layout/ContentPane",
"dojox/validate/us",
"dojox/validate/web",
"dojo/domReady!"
@@ -141,7 +141,7 @@ define(["dojo/_base/xhr",
return (type === "PlainPasswordFile" || type === "Base64MD5PasswordFile");
};
- util.showSetAttributesDialog = function(attributeWidgetFactories, data, putURL, dialogTitle)
+ util.showSetAttributesDialog = function(attributeWidgetFactories, data, putURL, dialogTitle, appendNameToUrl)
{
var layout = new dojox.layout.TableContainer({
cols: 1,
@@ -154,7 +154,7 @@ define(["dojo/_base/xhr",
var form = new dijit.form.Form();
var dialogContent = dom.create("div");
- var dialogContentArea = dom.create("div", { "class": "dijitDialogPaneContentArea"});
+ var dialogContentArea = dom.create("div", {"style": {width: 600}});
var dialogActionBar = dom.create("div", { "class": "dijitDialogPaneActionBar"} );
dialogContent.appendChild(dialogContentArea);
dialogContent.appendChild(dialogActionBar);
@@ -171,11 +171,17 @@ define(["dojo/_base/xhr",
var widget = attributeWidgetFactory.createWidget(data);
var name = attributeWidgetFactory.name ? attributeWidgetFactory.name : widget.name;
widgets[name] = widget;
- widget.initialValue = widget.value;
var dotPos = name.indexOf(".");
if (dotPos == -1)
{
- layout.addChild(widget);
+ if (widget instanceof dijit.layout.ContentPane)
+ {
+ dialogContentArea.appendChild(widget.domNode);
+ }
+ else
+ {
+ layout.addChild(widget);
+ }
}
else
{
@@ -197,7 +203,7 @@ define(["dojo/_base/xhr",
groups[groupName] = groupFieldContainer;
var groupTitle = attributeWidgetFactory.groupName ? attributeWidgetFactory.groupName :
groupName.charAt(0).toUpperCase() + groupName.slice(1);
- var panel = new dijit.TitlePane({title: groupTitle, toggleable: false, content: groupFieldContainer.domNode});
+ var panel = new dijit.TitlePane({title: groupTitle, content: groupFieldContainer.domNode});
dialogContentArea.appendChild(dom.create("br"));
dialogContentArea.appendChild(panel.domNode);
}
@@ -224,8 +230,7 @@ define(["dojo/_base/xhr",
}
var setAttributesDialog = new dijit.Dialog({
title: dialogTitle,
- content: form,
- style: "width: 600px; max-height: 80%"
+ content: form
});
form.on("submit", function(e)
{
@@ -235,23 +240,29 @@ define(["dojo/_base/xhr",
if(form.validate())
{
var values = {};
- for(var i in widgets)
+ var formWidgets = form.getDescendants();
+ for(var i in formWidgets)
{
- var widget = widgets[i];
+ var widget = formWidgets[i];
var value = widget.value;
var propName = widget.name;
- if ((widget instanceof dijit.form.CheckBox || widget instanceof dijit.form.RadioButton))
- {
- values[ propName ] = widget.checked;
- }
- else if (value != widget.initialValue)
- {
- values[ propName ] = value ? value: null;
+ if (propName && !widget.disabled){
+ if ((widget instanceof dijit.form.CheckBox || widget instanceof dijit.form.RadioButton)) {
+ if (widget.checked != widget.initialValue) {
+ values[ propName ] = widget.checked;
+ }
+ } else if (value != widget.initialValue) {
+ values[ propName ] = value ? value: null;
+ }
}
}
var that = this;
- xhr.put({url: putURL, sync: true, handleAs: "json",
+ var url = putURL;
+ if (appendNameToUrl){
+ url = url + "/" + encodeURIComponent(values["name"]);
+ }
+ xhr.put({url: url , sync: true, handleAs: "json",
headers: { "Content-Type": "application/json"},
putData: json.toJson(values),
load: function(x) {that.success = true; },
@@ -280,15 +291,24 @@ define(["dojo/_base/xhr",
});
form.connectChildren(true);
setAttributesDialog.startup();
- setAttributesDialog.on("show", function(){
- var data = geometry.position(dialogContentArea);
- var maxHeight = win.getBox().h * 0.6;
- if (data.h > maxHeight)
- {
- dialogContentArea.style.height = maxHeight + "px";
- dialogContentArea.style.overflow= "auto";
- }
- })
+ var formWidgets = form.getDescendants();
+ var aproximateHeight = 0;
+ for(var i in formWidgets){
+ var widget = formWidgets[i];
+ var propName = widget.name;
+ if (propName) {
+ if ((widget instanceof dijit.form.CheckBox || widget instanceof dijit.form.RadioButton)) {
+ widget.initialValue = widget.checked;
+ } else {
+ widget.initialValue = widget.value;
+ }
+ aproximateHeight += 30;
+ }
+ }
+ var viewport = win.getBox();
+ var maxHeight = Math.max(Math.floor(viewport.h * 0.6), 100);
+ dialogContentArea.style.overflow= "auto";
+ dialogContentArea.style.height = Math.min(aproximateHeight, maxHeight ) + "px";
setAttributesDialog.show();
};
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AccessControlProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AccessControlProvider.js
new file mode 100644
index 0000000000..fd8a3ecb0e
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AccessControlProvider.js
@@ -0,0 +1,131 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+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",
+ "dijit/registry",
+ "dojo/_base/event",
+ "dojox/grid/enhanced/plugins/Pagination",
+ "dojox/grid/enhanced/plugins/IndirectSelection",
+ "dojo/domReady!"],
+ function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, registry, event) {
+
+ function AccessControlProvider(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "accesscontrolprovider", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+ AccessControlProvider.prototype.getTitle = function() {
+ return "AccessControlProvider: " + this.name ;
+ };
+
+ AccessControlProvider.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showAccessControlProvider.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.accessControlProviderUpdater = new AccessControlProviderUpdater(contentPane.containerNode, that.modelObj, that.controller);
+
+ var deleteButton = query(".deleteAccessControlProviderButton", contentPane.containerNode)[0];
+ var deleteWidget = registry.byNode(deleteButton);
+ connect.connect(deleteWidget, "onClick",
+ function(evt){
+ event.stop(evt);
+ that.deleteAccessControlProvider();
+ });
+ }});
+ };
+
+ AccessControlProvider.prototype.close = function() {
+ if (this.accessControlProviderUpdater.details)
+ {
+ this.accessControlProviderUpdater.details.close();
+ }
+ };
+
+ AccessControlProvider.prototype.deleteAccessControlProvider = function() {
+ if(confirm("Are you sure you want to delete access control provider '" + this.name + "'?")) {
+ var query = "rest/accesscontrolprovider/" +encodeURIComponent(this.name);
+ this.success = true
+ var that = this;
+ xhr.del({url: query, sync: true, handleAs: "json"}).then(
+ function(data) {
+ that.close();
+ that.contentPane.onClose()
+ that.controller.tabContainer.removeChild(that.contentPane);
+ that.contentPane.destroyRecursive();
+ },
+ function(error) {that.success = false; that.failureReason = error;});
+ if(!this.success ) {
+ alert("Error:" + this.failureReason);
+ }
+ }
+ };
+
+ function AccessControlProviderUpdater(node, groupProviderObj, controller)
+ {
+ this.controller = controller;
+ this.name = query(".name", node)[0];
+ this.type = query(".type", node)[0];
+ this.query = "rest/accesscontrolprovider/"+encodeURIComponent(groupProviderObj.name);
+
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data)
+ {
+ that.accessControlProviderData = data[0];
+
+ util.flattenStatistics( that.accessControlProviderData );
+
+ that.updateHeader();
+
+ var ui = that.accessControlProviderData.type;
+ require(["qpid/management/accesscontrolprovider/"+ ui],
+ function(SpecificProvider) {
+ that.details = new SpecificProvider(query(".providerDetails", node)[0], groupProviderObj, controller);
+ });
+ });
+ }
+
+ AccessControlProviderUpdater.prototype.updateHeader = function()
+ {
+ this.name.innerHTML = this.accessControlProviderData[ "name" ];
+ this.type.innerHTML = this.accessControlProviderData[ "type" ];
+ };
+
+ return AccessControlProvider;
+ });
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js
index 04ac80784a..a27e43d1b1 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js
@@ -31,6 +31,9 @@ define(["dojo/_base/xhr",
"qpid/management/addAuthenticationProvider",
"qpid/management/addVirtualHost",
"qpid/management/addPort",
+ "qpid/management/addKeystore",
+ "qpid/management/addGroupProvider",
+ "qpid/management/addAccessControlProvider",
"dojox/grid/enhanced/plugins/Pagination",
"dojox/grid/enhanced/plugins/IndirectSelection",
"dijit/layout/AccordionContainer",
@@ -41,7 +44,7 @@ define(["dojo/_base/xhr",
"dijit/form/CheckBox",
"dojo/store/Memory",
"dojo/domReady!"],
- function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, registry, addAuthenticationProvider, addVirtualHost, addPort) {
+ function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, registry, addAuthenticationProvider, addVirtualHost, addPort, addKeystore, addGroupProvider, addAccessControlProvider) {
function Broker(name, parent, controller) {
this.name = name;
@@ -57,29 +60,10 @@ define(["dojo/_base/xhr",
return new dijit.form.ValidationTextBox({
required: true,
value: brokerData.name,
- disabled: true,
label: "Name*:",
name: "name"})
}
}, {
- name: "defaultAuthenticationProvider",
- createWidget: function(brokerData) {
- var providers = brokerData.authenticationproviders;
- var data = [];
- if (providers) {
- for (var i=0; i< providers.length; i++) {
- data.push({id: providers[i].name, name: providers[i].name});
- }
- }
- var providersStore = new dojo.store.Memory({ data: data });
- return new dijit.form.FilteringSelect({
- required: true,
- store: providersStore,
- value: brokerData.defaultAuthenticationProvider,
- label: "Default Authentication Provider*:",
- name: "defaultAuthenticationProvider"})
- }
- }, {
name: "defaultVirtualHost",
createWidget: function(brokerData) {
var hosts = brokerData.virtualhosts;
@@ -97,98 +81,6 @@ define(["dojo/_base/xhr",
name: "defaultVirtualHost"})
}
}, {
- name: "aclFile",
- createWidget: function(brokerData) {
- return new dijit.form.ValidationTextBox({
- required: false,
- value: brokerData.aclFile,
- label: "ACL file location:",
- name: "aclFile"})
- }
- }, {
- name: "groupFile",
- createWidget: function(brokerData)
- {
- return new dijit.form.ValidationTextBox({
- required: false,
- value: brokerData.groupFile,
- label: "Group file location:",
- name: "groupFile"});
- }
- }, {
- name: "keyStorePath",
- createWidget: function(brokerData) {
- return new dijit.form.ValidationTextBox({
- required: false,
- value: brokerData.keyStorePath,
- label: "Path to keystore:",
- name: "keyStorePath"});
- }
- }, {
- name: "keyStorePassword",
- requiredFor: "keyStorePath",
- createWidget: function(brokerData) {
- return new dijit.form.ValidationTextBox({
- required: false,
- label: "Keystore password:",
- invalidMessage: "Missed keystore password",
- name: "keyStorePassword",
- placeholder: brokerData["keyStorePassword"] ? brokerData["keyStorePassword"] : ""
- });
- }
- }, {
- name: "keyStoreCertAlias",
- createWidget: function(brokerData) {
- return new dijit.form.ValidationTextBox({
- required: false,
- value: brokerData.keyStoreCertAlias,
- label: "Keystore certificate alias:",
- name: "keyStoreCertAlias"});
- }
- }, {
- name: "trustStorePath",
- createWidget: function(brokerData)
- {
- return new dijit.form.ValidationTextBox({
- required: false,
- value: brokerData.trustStorePath,
- label: "Path to truststore:",
- name: "trustStorePath"});
- }
- }, {
- name: "trustStorePassword",
- requiredFor: "trustStorePath",
- createWidget: function(brokerData) {
- return new dijit.form.ValidationTextBox({
- required: false,
- label: "Truststore password:",
- invalidMessage: "Missed trustore password",
- name: "trustStorePassword",
- placeholder: brokerData["trustStorePassword"] ? brokerData["trustStorePassword"] : ""
- });
- }
- }, {
- name: "peerStorePath",
- createWidget: function(brokerData) {
- return new dijit.form.ValidationTextBox({
- required: false,
- value: brokerData.peerStorePath,
- label: "Path to peerstore:",
- name: "peerStorePath"});
- }
- }, {
- name: "peerStorePassword",
- requiredFor: "peerStorePath",
- createWidget: function(brokerData) {
- return new dijit.form.ValidationTextBox({
- required: false,
- label: "Peerstore password:",
- invalidMessage: "Missed peerstore password",
- name: "peerStorePassword",
- placeholder: brokerData["peerStorePassword"] ? brokerData["peerStorePassword"] : ""
- });
- }
- }, {
name: "statisticsReportingPeriod",
createWidget: function(brokerData) {
return new dijit.form.ValidationTextBox({
@@ -305,7 +197,7 @@ define(["dojo/_base/xhr",
checked: brokerData["queue.deadLetterQueueEnabled"],
value: "true",
label: "Dead letter queue enabled:",
- name: "queue.deadLetterQueueEnabled",
+ name: "queue.deadLetterQueueEnabled"
});
}
}, {
@@ -319,7 +211,7 @@ define(["dojo/_base/xhr",
value: brokerData["queue.flowControlSizeBytes"],
placeholder: "Size in bytes",
label: "Flow control threshold (bytes):",
- name: "queue.flowControlSizeBytes",
+ name: "queue.flowControlSizeBytes"
});
}
}, {
@@ -333,7 +225,7 @@ define(["dojo/_base/xhr",
value: brokerData["queue.flowResumeSizeBytes"],
placeholder: "Size in bytes",
label: "Flow resume threshold (bytes):",
- name: "queue.flowResumeSizeBytes",
+ name: "queue.flowResumeSizeBytes"
});
}
}, {
@@ -488,7 +380,10 @@ define(["dojo/_base/xhr",
);
var addPortButton = query(".addPort", contentPane.containerNode)[0];
- connect.connect(registry.byNode(addPortButton), "onClick", function(evt){ addPort.show(null, that.brokerUpdater.brokerData.authenticationproviders); });
+ connect.connect(registry.byNode(addPortButton), "onClick", function(evt){
+ addPort.show(null, that.brokerUpdater.brokerData.authenticationproviders,
+ that.brokerUpdater.brokerData.keystores, that.brokerUpdater.brokerData.truststores);
+ });
var deletePort = query(".deletePort", contentPane.containerNode)[0];
connect.connect(registry.byNode(deletePort), "onClick",
@@ -512,6 +407,79 @@ define(["dojo/_base/xhr",
}
);
+ var addKeystoreButton = query(".addKeystore", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(addKeystoreButton), "onClick",
+ function(evt){ addKeystore.showKeystoreDialog() });
+
+ var deleteKeystore = query(".deleteKeystore", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(deleteKeystore), "onClick",
+ function(evt){
+ util.deleteGridSelections(
+ that.brokerUpdater,
+ that.brokerUpdater.keyStoresGrid.grid,
+ "rest/keystore",
+ "Are you sure you want to delete key store");
+ }
+ );
+
+ var addTruststoreButton = query(".addTruststore", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(addTruststoreButton), "onClick",
+ function(evt){ addKeystore.showTruststoreDialog() });
+
+ var deleteTruststore = query(".deleteTruststore", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(deleteTruststore), "onClick",
+ function(evt){
+ util.deleteGridSelections(
+ that.brokerUpdater,
+ that.brokerUpdater.trustStoresGrid.grid,
+ "rest/truststore",
+ "Are you sure you want to delete trust store");
+ }
+ );
+
+ var addGroupProviderButton = query(".addGroupProvider", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(addGroupProviderButton), "onClick",
+ function(evt){addGroupProvider.show();});
+
+ var deleteGroupProvider = query(".deleteGroupProvider", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(deleteGroupProvider), "onClick",
+ function(evt){
+ var warning = "";
+ var data = that.brokerUpdater.groupProvidersGrid.grid.selection.getSelected();
+ if(data.length && data.length > 0)
+ {
+ for(var i = 0; i<data.length; i++)
+ {
+ if (data[i].type.indexOf("File") != -1)
+ {
+ warning = "NOTE: provider deletion will also remove the group file on disk.\n\n"
+ break;
+ }
+ }
+ }
+
+ util.deleteGridSelections(
+ that.brokerUpdater,
+ that.brokerUpdater.groupProvidersGrid.grid,
+ "rest/groupprovider",
+ warning + "Are you sure you want to delete group provider");
+ }
+ );
+
+ var addAccessControlButton = query(".addAccessControlProvider", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(addAccessControlButton), "onClick",
+ function(evt){addAccessControlProvider.show();});
+
+ var deleteAccessControlProviderButton = query(".deleteAccessControlProvider", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(deleteAccessControlProviderButton), "onClick",
+ function(evt){
+ util.deleteGridSelections(
+ that.brokerUpdater,
+ that.brokerUpdater.accessControlProvidersGrid.grid,
+ "rest/accesscontrolprovider",
+ "Are you sure you want to delete access control provider");
+ }
+ );
}});
};
@@ -524,6 +492,7 @@ define(["dojo/_base/xhr",
this.controller = controller;
this.query = "rest/broker";
this.attributes = attributes;
+ this.accessControlProvidersWarn = query(".broker-access-control-providers-warning", node)[0]
var that = this;
xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
@@ -570,7 +539,7 @@ define(["dojo/_base/xhr",
new UpdatableStore(that.brokerData.ports, query(".broker-ports")[0],
[ { name: "Name", field: "name", width: "150px"},
{ name: "State", field: "state", width: "60px"},
- { name: "Authentication", field: "authenticationProvider", width: "100px"},
+ { name: "Auth Provider", field: "authenticationProvider", width: "100px"},
{ name: "Address", field: "bindingAddress", width: "70px"},
{ name: "Port", field: "port", width: "50px"},
{ name: "Transports", field: "transports", width: "100px"},
@@ -581,7 +550,7 @@ define(["dojo/_base/xhr",
var idx = evt.rowIndex,
theItem = this.getItem(idx);
var name = obj.dataStore.getValue(theItem,"name");
- addPort.show(name, that.brokerData.authenticationproviders);
+ that.controller.show("port", name, brokerObj);
});
}, gridProperties, EnhancedGrid);
@@ -615,6 +584,71 @@ define(["dojo/_base/xhr",
});
}, gridProperties, EnhancedGrid);
+ that.keyStoresGrid =
+ new UpdatableStore(that.brokerData.keystores, query(".broker-key-stores")[0],
+ [ { name: "Name", field: "name", width: "20%"},
+ { name: "Path", field: "path", width: "40%"},
+ { name: "Type", field: "type", width: "5%"},
+ { name: "Key Manager Algorithm", field: "keyManagerFactoryAlgorithm", width: "20%"},
+ { name: "Alias", field: "certificateAlias", width: "15%"}
+ ], 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("keystore", name, brokerObj);
+ });
+ }, gridProperties, EnhancedGrid);
+
+ that.trustStoresGrid =
+ new UpdatableStore(that.brokerData.truststores, query(".broker-trust-stores")[0],
+ [ { name: "Name", field: "name", width: "20%"},
+ { name: "Path", field: "path", width: "40%"},
+ { name: "Type", field: "type", width: "5%"},
+ { name: "Trust Manager Algorithm", field: "trustManagerFactoryAlgorithm", width: "25%"},
+ { name: "Peers only", field: "peersOnly", width: "10%",
+ formatter: function(val){
+ return "<input type='radio' disabled='disabled' "+(val ? "checked='checked'": "")+" />";
+ }
+ }
+ ], 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("truststore", name, brokerObj);
+ });
+ }, gridProperties, EnhancedGrid);
+ that.groupProvidersGrid =
+ new UpdatableStore(that.brokerData.groupproviders, query(".broker-group-providers")[0],
+ [ { name: "Name", field: "name", width: "50%"},
+ { name: "Type", field: "type", width: "50%"}
+ ], 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("groupprovider", name, brokerObj);
+ });
+ }, gridProperties, EnhancedGrid);
+ var aclData = that.brokerData.accesscontrolproviders ? that.brokerData.accesscontrolproviders :[];
+ that.accessControlProvidersGrid =
+ new UpdatableStore(aclData, query(".broker-access-control-providers")[0],
+ [ { name: "Name", field: "name", width: "60%"},
+ { name: "Type", field: "type", width: "40%"}
+ ], 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("accesscontrolprovider", name, brokerObj);
+ });
+ }, gridProperties, EnhancedGrid);
+ that.displayACLWarnMessage(aclData);
});
xhr.get({url: "rest/logrecords", sync: properties.useSyncGet, handleAs: "json"})
@@ -659,6 +693,7 @@ define(["dojo/_base/xhr",
{
this.showReadOnlyAttributes();
var brokerData = this.brokerData;
+ window.document.title = "Qpid: " + brokerData.name + " Management";
for(var i in this.attributes)
{
var propertyName = this.attributes[i].name;
@@ -682,6 +717,43 @@ define(["dojo/_base/xhr",
}
};
+ BrokerUpdater.prototype.displayACLWarnMessage = function(aclProviderData)
+ {
+ var message = "";
+ if (aclProviderData.length > 1)
+ {
+ var aclProviders = {};
+ var theSameTypeFound = false;
+ for(var d=0; d<aclProviderData.length; d++)
+ {
+ var acl = aclProviderData[d];
+ var aclType = acl.type;
+ if (aclProviders[aclType])
+ {
+ aclProviders[aclType].push(acl.name);
+ theSameTypeFound = true;
+ }
+ else
+ {
+ aclProviders[aclType] = [acl.name];
+ }
+ }
+
+ if (theSameTypeFound)
+ {
+ message = "Only one instance of a given type will be used. Please remove an instance of type(s):";
+ for(var aclType in aclProviders)
+ {
+ if(aclProviders[aclType].length>1)
+ {
+ message += " " + aclType;
+ }
+ }
+ }
+ }
+ this.accessControlProvidersWarn.innerHTML = message;
+ }
+
BrokerUpdater.prototype.update = function()
{
@@ -699,6 +771,25 @@ define(["dojo/_base/xhr",
that.portsGrid.update(that.brokerData.ports);
that.authenticationProvidersGrid.update(that.brokerData.authenticationproviders);
+
+ if (that.keyStoresGrid)
+ {
+ that.keyStoresGrid.update(that.brokerData.keystores);
+ }
+ if (that.trustStoresGrid)
+ {
+ that.trustStoresGrid.update(that.brokerData.truststores);
+ }
+ if (that.groupProvidersGrid)
+ {
+ that.groupProvidersGrid.update(that.brokerData.groupproviders);
+ }
+ if (that.accessControlProvidersGrid)
+ {
+ var data = that.brokerData.accesscontrolproviders ? that.brokerData.accesscontrolproviders :[];
+ that.accessControlProvidersGrid.update(data);
+ that.displayACLWarnMessage(data);
+ }
});
@@ -718,7 +809,7 @@ define(["dojo/_base/xhr",
dojo.byId("brokerAttribute.operatingSystem").innerHTML = brokerData.operatingSystem;
dojo.byId("brokerAttribute.platform").innerHTML = brokerData.platform;
dojo.byId("brokerAttribute.productVersion").innerHTML = brokerData.productVersion;
- dojo.byId("brokerAttribute.modelVersion").innerHTML = brokerData.managementVersion;
+ dojo.byId("brokerAttribute.modelVersion").innerHTML = brokerData.modelVersion;
dojo.byId("brokerAttribute.storeType").innerHTML = brokerData.storeType;
dojo.byId("brokerAttribute.storeVersion").innerHTML = brokerData.storeVersion;
dojo.byId("brokerAttribute.storePath").innerHTML = brokerData.storePath;
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js
index 4e05f4b0ea..98e01773ef 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js
@@ -27,10 +27,12 @@ define(["dojo/_base/xhr",
"qpid/common/util",
"qpid/common/UpdatableStore",
"dojox/grid/EnhancedGrid",
+ "dijit/registry",
+ "dojo/_base/event",
"dojox/grid/enhanced/plugins/Pagination",
"dojox/grid/enhanced/plugins/IndirectSelection",
"dojo/domReady!"],
- function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid) {
+ function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, registry, event) {
function GroupProvider(name, parent, controller) {
this.name = name;
@@ -43,7 +45,7 @@ define(["dojo/_base/xhr",
}
GroupProvider.prototype.getTitle = function() {
- return "GroupProvider";
+ return "GroupProvider: " + this.name ;
};
GroupProvider.prototype.open = function(contentPane) {
@@ -61,6 +63,13 @@ define(["dojo/_base/xhr",
that.groupProviderAdapter.update();
+ var deleteButton = query(".deleteGroupProviderButton", contentPane.containerNode)[0];
+ var deleteWidget = registry.byNode(deleteButton);
+ connect.connect(deleteWidget, "onClick",
+ function(evt){
+ event.stop(evt);
+ that.deleteGroupProvider();
+ });
}});
};
@@ -68,12 +77,37 @@ define(["dojo/_base/xhr",
updater.remove( this.groupProviderAdapter );
};
+ GroupProvider.prototype.deleteGroupProvider = function() {
+ var warnMessage = "";
+ if (this.groupProviderAdapter.groupProviderData && this.groupProviderAdapter.groupProviderData.type.indexOf("File") != -1)
+ {
+ warnMessage = "NOTE: provider deletion will also remove the group file on disk.\n\n";
+ }
+ if(confirm(warnMessage + "Are you sure you want to delete group provider '" + this.name + "'?")) {
+ var query = "rest/groupprovider/" +encodeURIComponent(this.name);
+ this.success = true
+ var that = this;
+ xhr.del({url: query, sync: true, handleAs: "json"}).then(
+ function(data) {
+ that.close();
+ that.contentPane.onClose()
+ that.controller.tabContainer.removeChild(that.contentPane);
+ that.contentPane.destroyRecursive();
+ },
+ function(error) {that.success = false; that.failureReason = error;});
+ if(!this.success ) {
+ alert("Error:" + this.failureReason);
+ }
+ }
+ };
+
function GroupProviderUpdater(node, groupProviderObj, controller)
{
this.controller = controller;
this.name = query(".name", node)[0];
+ this.type = query(".type", node)[0];
this.query = "rest/groupprovider/"+encodeURIComponent(groupProviderObj.name);
-
+ this.typeUI ={"GroupFile": "FileGroupManager"};
var that = this;
xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
@@ -85,9 +119,10 @@ define(["dojo/_base/xhr",
that.updateHeader();
- require(["qpid/management/groupprovider/"+that.groupProviderData.type],
+ var ui = that.typeUI[that.groupProviderData.type];
+ require(["qpid/management/groupprovider/"+ ui],
function(SpecificProvider) {
- that.details = new SpecificProvider(node, groupProviderObj, controller);
+ that.details = new SpecificProvider(query(".providerDetails", node)[0], groupProviderObj, controller);
that.details.update();
});
@@ -98,6 +133,7 @@ define(["dojo/_base/xhr",
GroupProviderUpdater.prototype.updateHeader = function()
{
this.name.innerHTML = this.groupProviderData[ "name" ];
+ this.type.innerHTML = this.groupProviderData[ "type" ];
};
GroupProviderUpdater.prototype.update = function()
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/KeyStore.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/KeyStore.js
new file mode 100644
index 0000000000..9702c6b9f6
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/KeyStore.js
@@ -0,0 +1,160 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+define(["dojo/dom",
+ "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/management/addKeystore",
+ "dojo/domReady!"],
+ function (dom, xhr, parser, query, connect, registry, properties, updater, util, formatter, addKeystore) {
+
+ function KeyStore(name, parent, controller, objectType) {
+ this.keyStoreName = name;
+ this.controller = controller;
+ this.modelObj = { type: "keystore", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ this.url = "rest/keystore/" + encodeURIComponent(name);
+ this.dialog = addKeystore.showKeystoreDialog;
+ }
+
+ KeyStore.prototype.getTitle = function() {
+ return "KeyStore: " + this.keyStoreName;
+ };
+
+ KeyStore.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showKeyStore.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.keyStoreUpdater = new KeyStoreUpdater(contentPane.containerNode, that.modelObj, that.controller, that.url);
+
+ updater.add( that.keyStoreUpdater );
+
+ that.keyStoreUpdater.update();
+
+ var deleteKeyStoreButton = query(".deleteKeyStoreButton", contentPane.containerNode)[0];
+ var node = registry.byNode(deleteKeyStoreButton);
+ connect.connect(node, "onClick",
+ function(evt){
+ that.deleteKeyStore();
+ });
+
+ var editKeyStoreButton = query(".editKeyStoreButton", contentPane.containerNode)[0];
+ var node = registry.byNode(editKeyStoreButton);
+ connect.connect(node, "onClick",
+ function(evt){
+ that.dialog(that.keyStoreUpdater.keyStoreData)
+ });
+ }});
+ };
+
+ KeyStore.prototype.close = function() {
+ updater.remove( this.keyStoreUpdater );
+ };
+
+ function KeyStoreUpdater(containerNode, keyStoreObj, controller, url)
+ {
+ var that = this;
+
+ function findNode(name) {
+ return query("." + name + "Value", containerNode)[0];
+ }
+
+ function storeNodes(names)
+ {
+ for(var i = 0; i < names.length; i++) {
+ that[names[i]] = findNode(names[i]);
+ }
+ }
+
+ storeNodes(["name",
+ "path",
+ "type",
+ "keyManagerFactoryAlgorithm",
+ "certificateAlias",
+ "peersOnly"
+ ]);
+
+ this.query = url;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ that.keyStoreData = data[0];
+ that.updateHeader();
+ });
+
+ }
+
+ KeyStoreUpdater.prototype.updateHeader = function()
+ {
+ this.name.innerHTML = this.keyStoreData[ "name" ];
+ this.path.innerHTML = this.keyStoreData[ "path" ];
+ this.type.innerHTML = this.keyStoreData[ "type" ];
+ this.keyManagerFactoryAlgorithm.innerHTML = this.keyStoreData[ "keyManagerFactoryAlgorithm" ];
+ this.certificateAlias.innerHTML = this.keyStoreData[ "certificateAlias" ] ? this.keyStoreData[ "certificateAlias" ] : "";
+ };
+
+ KeyStoreUpdater.prototype.update = function()
+ {
+
+ var thisObj = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ thisObj.keyStoreData = data[0];
+ thisObj.updateHeader();
+ });
+ };
+
+ KeyStore.prototype.deleteKeyStore = function() {
+ if(confirm("Are you sure you want to delete key store '" +this.keyStoreName+"'?")) {
+ var query = this.url;
+ this.success = true
+ var that = this;
+ xhr.del({url: query, sync: true, handleAs: "json"}).then(
+ function(data) {
+ that.contentPane.onClose()
+ that.controller.tabContainer.removeChild(that.contentPane);
+ that.contentPane.destroyRecursive();
+ that.close();
+ },
+ function(error) {that.success = false; that.failureReason = error;});
+ if(!this.success ) {
+ alert("Error:" + this.failureReason);
+ }
+ }
+ }
+
+ return KeyStore;
+ });
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Port.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Port.js
new file mode 100644
index 0000000000..d1ba4043c2
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Port.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/dom",
+ "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/management/addPort",
+ "dojo/domReady!"],
+ function (dom, xhr, parser, query, connect, registry, properties, updater, util, formatter, addPort) {
+
+ function Port(name, parent, controller) {
+ this.name = name;
+ this.controller = controller;
+ this.modelObj = { type: "port", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ }
+
+ Port.prototype.getTitle = function() {
+ return "Port: " + this.name;
+ };
+
+ Port.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showPort.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.portUpdater = new PortUpdater(contentPane.containerNode, that.modelObj, that.controller, "rest/port/" + encodeURIComponent(that.name));
+
+ updater.add( that.portUpdater );
+
+ that.portUpdater.update();
+
+ var deletePortButton = query(".deletePortButton", contentPane.containerNode)[0];
+ var node = registry.byNode(deletePortButton);
+ connect.connect(node, "onClick",
+ function(evt){
+ that.deletePort();
+ });
+
+ var editPortButton = query(".editPortButton", contentPane.containerNode)[0];
+ var node = registry.byNode(editPortButton);
+ connect.connect(node, "onClick",
+ function(evt){
+ that.showEditDialog();
+ });
+ }});
+ };
+
+ Port.prototype.close = function() {
+ updater.remove( this.portUpdater );
+ };
+
+
+ Port.prototype.deletePort = function() {
+ if(confirm("Are you sure you want to delete port '" +this.name+"'?")) {
+ var query = "rest/port/" + encodeURIComponent(this.name);
+ this.success = true
+ var that = this;
+ xhr.del({url: query, sync: true, handleAs: "json"}).then(
+ function(data) {
+ that.contentPane.onClose()
+ that.controller.tabContainer.removeChild(that.contentPane);
+ that.contentPane.destroyRecursive();
+ that.close();
+ },
+ function(error) {that.success = false; that.failureReason = error;});
+ if(!this.success ) {
+ alert("Error:" + this.failureReason);
+ }
+ }
+ }
+
+ Port.prototype.showEditDialog = function() {
+ var that = this;
+ xhr.get({url: "rest/broker", sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data)
+ {
+ var brokerData= data[0];
+ addPort.show(that.name, brokerData.authenticationproviders, brokerData.keystores, brokerData.truststores);
+ }
+ );
+ }
+
+ function PortUpdater(containerNode, portObj, controller, url)
+ {
+ 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(["nameValue",
+ "portValue",
+ "authenticationProviderValue",
+ "protocolsValue",
+ "transportsValue",
+ "bindingAddressValue",
+ "keyStoreValue",
+ "needClientAuthValue",
+ "wantClientAuthValue",
+ "trustStoresValue",
+ "bindingAddress",
+ "keyStore",
+ "needClientAuth",
+ "wantClientAuth",
+ "trustStores"
+ ]);
+
+ this.query = url;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ that.keyStoreData = data[0];
+ that.updateHeader();
+ });
+
+ }
+
+ PortUpdater.prototype.updateHeader = function()
+ {
+ function printArray(fieldName, object)
+ {
+ var array = object[fieldName];
+ var data = "<div>";
+ if (array) {
+ for(var i = 0; i < array.length; i++) {
+ data+= "<div>" + array[i] + "</div>";
+ }
+ }
+ return data + "</div>";
+ }
+
+ this.nameValue.innerHTML = this.keyStoreData[ "name" ];
+ this.portValue.innerHTML = this.keyStoreData[ "port" ];
+ this.authenticationProviderValue.innerHTML = this.keyStoreData[ "authenticationProvider" ] ? this.keyStoreData[ "authenticationProvider" ] : "";
+ this.protocolsValue.innerHTML = printArray( "protocols", this.keyStoreData);
+ this.transportsValue.innerHTML = printArray( "transports", this.keyStoreData);
+ this.bindingAddressValue.innerHTML = this.keyStoreData[ "bindingAddress" ] ? this.keyStoreData[ "bindingAddress" ] : "" ;
+ this.keyStoreValue.innerHTML = this.keyStoreData[ "keyStore" ] ? this.keyStoreData[ "keyStore" ] : "";
+ this.needClientAuthValue.innerHTML = "<input type='checkbox' disabled='disabled' "+(this.keyStoreData[ "needClientAuth" ] ? "checked='checked'": "")+" />" ;
+ this.wantClientAuthValue.innerHTML = "<input type='checkbox' disabled='disabled' "+(this.keyStoreData[ "wantClientAuth" ] ? "checked='checked'": "")+" />" ;
+ this.trustStoresValue.innerHTML = printArray( "trustStores", this.keyStoreData);
+ var amqpProtocol = this.keyStoreData["protocols"][0] && this.keyStoreData["protocols"][0].indexOf("AMQP") == 0;
+ this.bindingAddress.style.display= amqpProtocol? "block" : "none";
+ var sslTransport = this.keyStoreData["transports"][0] && this.keyStoreData["transports"][0] == "SSL";
+ var displayStyle = sslTransport ? "block" : "none";
+ this.trustStoresValue.style.display = displayStyle;
+ this.keyStore.style.display = displayStyle;
+ this.needClientAuth.style.display = displayStyle;
+ this.wantClientAuth.style.display = displayStyle;
+ this.trustStores.style.display = displayStyle;
+ };
+
+ PortUpdater.prototype.update = function()
+ {
+
+ var thisObj = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ thisObj.keyStoreData = data[0];
+ thisObj.updateHeader();
+ });
+ };
+
+ return Port;
+ });
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/TrustStore.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/TrustStore.js
new file mode 100644
index 0000000000..703ef34ec2
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/TrustStore.js
@@ -0,0 +1,160 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+define(["dojo/dom",
+ "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/management/addKeystore",
+ "dojo/domReady!"],
+ function (dom, xhr, parser, query, connect, registry, properties, updater, util, formatter, addKeystore) {
+
+ function TrustStore(name, parent, controller) {
+ this.keyStoreName = name;
+ this.controller = controller;
+ this.modelObj = { type: "truststore", name: name };
+ if(parent) {
+ this.modelObj.parent = {};
+ this.modelObj.parent[ parent.type] = parent;
+ }
+ this.url = "rest/truststore/" + encodeURIComponent(name);
+ this.dialog = addKeystore.showTruststoreDialog;
+ }
+
+ TrustStore.prototype.getTitle = function() {
+ return "TrustStore: " + this.keyStoreName;
+ };
+
+ TrustStore.prototype.open = function(contentPane) {
+ var that = this;
+ this.contentPane = contentPane;
+ xhr.get({url: "showTrustStore.html",
+ sync: true,
+ load: function(data) {
+ contentPane.containerNode.innerHTML = data;
+ parser.parse(contentPane.containerNode);
+
+ that.keyStoreUpdater = new KeyStoreUpdater(contentPane.containerNode, that.modelObj, that.controller, that.url);
+
+ updater.add( that.keyStoreUpdater );
+
+ that.keyStoreUpdater.update();
+
+ var deleteTrustStoreButton = query(".deleteTrustStoreButton", contentPane.containerNode)[0];
+ var node = registry.byNode(deleteTrustStoreButton);
+ connect.connect(node, "onClick",
+ function(evt){
+ that.deleteKeyStore();
+ });
+
+ var editTrustStoreButton = query(".editTrustStoreButton", contentPane.containerNode)[0];
+ var node = registry.byNode(editTrustStoreButton);
+ connect.connect(node, "onClick",
+ function(evt){
+ that.dialog(that.keyStoreUpdater.keyStoreData)
+ });
+ }});
+ };
+
+ TrustStore.prototype.close = function() {
+ updater.remove( this.keyStoreUpdater );
+ };
+
+ function KeyStoreUpdater(containerNode, keyStoreObj, controller, url)
+ {
+ var that = this;
+
+ function findNode(name) {
+ return query("." + name + "Value", containerNode)[0];
+ }
+
+ function storeNodes(names)
+ {
+ for(var i = 0; i < names.length; i++) {
+ that[names[i]] = findNode(names[i]);
+ }
+ }
+
+ storeNodes(["name",
+ "path",
+ "type",
+ "trustManagerFactoryAlgorithm",
+ "certificateAlias",
+ "peersOnly"
+ ]);
+
+ this.query = url;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ that.keyStoreData = data[0];
+ that.updateHeader();
+ });
+
+ }
+
+ KeyStoreUpdater.prototype.updateHeader = function()
+ {
+ this.name.innerHTML = this.keyStoreData[ "name" ];
+ this.path.innerHTML = this.keyStoreData[ "path" ];
+ this.type.innerHTML = this.keyStoreData[ "type" ];
+ this.trustManagerFactoryAlgorithm.innerHTML = this.keyStoreData[ "trustManagerFactoryAlgorithm" ];
+ this.peersOnly.innerHTML = "<input type='checkbox' disabled='disabled' "+(this.keyStoreData[ "peersOnly" ] ? "checked='checked'": "")+" />" ;
+ };
+
+ KeyStoreUpdater.prototype.update = function()
+ {
+
+ var thisObj = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data)
+ {
+ thisObj.keyStoreData = data[0];
+ thisObj.updateHeader();
+ });
+ };
+
+ TrustStore.prototype.deleteKeyStore = function() {
+ if(confirm("Are you sure you want to delete trust store '" +this.keyStoreName+"'?")) {
+ var query = this.url;
+ this.success = true
+ var that = this;
+ xhr.del({url: query, sync: true, handleAs: "json"}).then(
+ function(data) {
+ that.contentPane.onClose()
+ that.controller.tabContainer.removeChild(that.contentPane);
+ that.contentPane.destroyRecursive();
+ that.close();
+ },
+ function(error) {that.success = false; that.failureReason = error;});
+ if(!this.success ) {
+ alert("Error:" + this.failureReason);
+ }
+ }
+ }
+
+ return TrustStore;
+ });
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/AclFile.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/AclFile.js
new file mode 100644
index 0000000000..56f92c2025
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/AclFile.js
@@ -0,0 +1,95 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojo/dom",
+ "dojo/parser",
+ "dojo/query",
+ "dojo/dom-construct",
+ "dojo/_base/connect",
+ "dojo/_base/window",
+ "dojo/_base/event",
+ "dojo/_base/json",
+ "dijit/registry",
+ "qpid/common/util",
+ "qpid/common/properties",
+ "qpid/common/updater",
+ "qpid/common/UpdatableStore",
+ "dojox/grid/EnhancedGrid",
+ "dojox/grid/enhanced/plugins/Pagination",
+ "dojox/grid/enhanced/plugins/IndirectSelection",
+ "dojox/validate/us", "dojox/validate/web",
+ "dijit/Dialog",
+ "dijit/form/TextBox",
+ "dijit/form/ValidationTextBox",
+ "dijit/form/TimeTextBox", "dijit/form/Button",
+ "dijit/form/Form",
+ "dijit/form/DateTextBox",
+ "dojo/domReady!"],
+ function (xhr, dom, parser, query, construct, connect, win, event, json, registry, util, properties, updater, UpdatableStore, EnhancedGrid) {
+ function AclFile(containerNode, aclProviderObj, controller) {
+ var node = construct.create("div", null, containerNode, "last");
+ var that = this;
+ this.name = aclProviderObj.name;
+ xhr.get({url: "accesscontrolprovider/showAclFile.html",
+ sync: true,
+ load: function(data) {
+ node.innerHTML = data;
+ parser.parse(node);
+
+ that.groupDatabaseUpdater= new AclFileUpdater(node, aclProviderObj, controller);
+
+ updater.add( that.groupDatabaseUpdater);
+
+ that.groupDatabaseUpdater.update();
+
+
+ }});
+ }
+
+ AclFile.prototype.close = function() {
+ updater.remove( this.groupDatabaseUpdater );
+ };
+
+ function AclFileUpdater(node, aclProviderObj, controller)
+ {
+ this.controller = controller;
+ this.query = "rest/accesscontrolprovider/"+encodeURIComponent(aclProviderObj.name);
+ this.name = aclProviderObj.name;
+ this.path = query(".path", node)[0];
+ }
+
+ AclFileUpdater.prototype.update = function()
+ {
+ var that = this;
+
+ xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
+ .then(function(data) {
+ if (data[0])
+ {
+ that.aclProviderData = data[0];
+ that.path.innerHTML = that.aclProviderData.path;
+ }
+ });
+
+ };
+
+ return AclFile;
+ });
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js
new file mode 100644
index 0000000000..d20897c1d8
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js
@@ -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.
+ *
+ */
+define(["dojo/_base/lang",
+ "dojo/_base/xhr",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dijit/registry",
+ "dojo/parser",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ 'dojo/_base/json',
+ "qpid/common/util",
+ "dojo/store/Memory",
+ "dojox/validate/us",
+ "dojox/validate/web",
+ "dijit/Dialog",
+ "dijit/form/CheckBox",
+ "dijit/form/Textarea",
+ "dijit/form/ComboBox",
+ "dijit/form/TextBox",
+ "dijit/form/ValidationTextBox",
+ "dijit/form/Button",
+ "dijit/form/Form",
+ "dijit/layout/ContentPane",
+ "dojox/layout/TableContainer",
+ "dojo/domReady!"],
+ function (lang, xhr, dom, construct, registry, parser, array, event, json, util) {
+
+ var addAccessControlProvider = {};
+
+ addAccessControlProvider.show = function(accessControlProvider) {
+ var fields = [{
+ name: "name",
+ createWidget: function(accessControlProvider) {
+ return new dijit.form.ValidationTextBox({
+ required: true,
+ value: accessControlProvider.name,
+ disabled: accessControlProvider.name ? true : false,
+ label: "Name*:",
+ regexp: "^[\x20-\x2e\x30-\x7F]{1,255}$",
+ name: "name"});
+ }
+ }, {
+ name: "type",
+ createWidget: function(accessControlProvider) {
+
+ var typeContainer = construct.create("div");
+
+ var typeListContainer = new dojox.layout.TableContainer({
+ cols: 1,
+ "labelWidth": "300",
+ customClass: "formLabel",
+ showLabels: true,
+ orientation: "horiz"
+ });
+
+ typeContainer.appendChild(typeListContainer.domNode);
+
+ var providers = [];
+ var fieldSetContainers = {};
+ xhr.get({
+ url: "rest/helper?action=ListAccessControlProviderAttributes",
+ handleAs: "json",
+ sync: true
+ }).then(
+ function(data) {
+ var providerIndex = 0;
+
+ for (var providerType in data) {
+ if (data.hasOwnProperty(providerType)) {
+ providers[providerIndex++] = {id: providerType, name: providerType};
+
+ var attributes = data[providerType].attributes;
+ var descriptions = data[providerType].descriptions;
+
+ var layout = new dojox.layout.TableContainer( {
+ cols: 1,
+ "labelWidth": "300",
+ customClass: "formLabel",
+ showLabels: true,
+ orientation: "horiz"
+ });
+
+ for(var i=0; i < attributes.length; i++) {
+ if ("type" == attributes[i])
+ {
+ continue;
+ }
+ var labelValue = attributes[i];
+ if (descriptions && descriptions[attributes[i]])
+ {
+ labelValue = descriptions[attributes[i]];
+ }
+ var text = new dijit.form.TextBox({
+ label: labelValue + ":",
+ name: attributes[i]
+ });
+ layout.addChild(text);
+ }
+
+ typeContainer.appendChild(layout.domNode);
+ fieldSetContainers[providerType] = layout;
+ }
+ }
+ });
+
+ var providersStore = new dojo.store.Memory({ data: providers });
+
+ var typeList = new dijit.form.FilteringSelect({
+ required: true,
+ value: accessControlProvider.type,
+ store: providersStore,
+ label: "Type*:",
+ name: "type"});
+
+ typeListContainer.addChild(typeList);
+
+ var onChangeHandler = function onChangeHandler(newValue){
+ for (var i in fieldSetContainers) {
+ var container = fieldSetContainers[i];
+ var descendants = container.getChildren();
+ for(var i in descendants){
+ var descendant = descendants[i];
+ var propName = descendant.name;
+ if (propName) {
+ descendant.set("disabled", true);
+ }
+ }
+ container.domNode.style.display = "none";
+ }
+ var container = fieldSetContainers[newValue];
+ if (container)
+ {
+ container.domNode.style.display = "block";
+ var descendants = container.getChildren();
+ for(var i in descendants){
+ var descendant = descendants[i];
+ var propName = descendant.name;
+ if (propName) {
+ descendant.set("disabled", false);
+ }
+ }
+ }
+ };
+ typeList.on("change", onChangeHandler);
+ onChangeHandler(typeList.value);
+ return new dijit.layout.ContentPane({content: typeContainer, style:{padding: 0}});
+ }
+ }];
+
+ util.showSetAttributesDialog(
+ fields,
+ accessControlProvider ? accessControlProvider : {},
+ "rest/accesscontrolprovider" + (name ? "/" + encodeURIComponent(name.name) : ""),
+ accessControlProvider ? "Edit access control provider - " + accessControlProvider.name : "Add access control provider",
+ accessControlProvider ? false : true);
+ };
+ return addAccessControlProvider;
+ }); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAuthenticationProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAuthenticationProvider.js
index decc7fa0b3..d2891c7d3b 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAuthenticationProvider.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAuthenticationProvider.js
@@ -207,7 +207,7 @@ define(["dojo/_base/xhr",
var layout = new dojox.layout.TableContainer( {
id: providerType + "FieldSet",
cols: 1,
- "labelWidth": "300",
+ "labelWidth": "200",
showLabels: true,
orientation: "horiz"
});
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addGroupProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addGroupProvider.js
new file mode 100644
index 0000000000..c8cd33fd6a
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addGroupProvider.js
@@ -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.
+ *
+ */
+define(["dojo/_base/lang",
+ "dojo/_base/xhr",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dijit/registry",
+ "dojo/parser",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ 'dojo/_base/json',
+ "qpid/common/util",
+ "dojo/store/Memory",
+ "dojox/validate/us",
+ "dojox/validate/web",
+ "dijit/Dialog",
+ "dijit/form/CheckBox",
+ "dijit/form/Textarea",
+ "dijit/form/ComboBox",
+ "dijit/form/TextBox",
+ "dijit/form/ValidationTextBox",
+ "dijit/form/Button",
+ "dijit/form/Form",
+ "dijit/layout/ContentPane",
+ "dojox/layout/TableContainer",
+ "dojo/domReady!"],
+ function (lang, xhr, dom, construct, registry, parser, array, event, json, util) {
+
+ var addGroupProvider = {};
+
+ addGroupProvider.show = function(groupProvider) {
+ var fields = [{
+ name: "name",
+ createWidget: function(groupProvider) {
+ return new dijit.form.ValidationTextBox({
+ required: true,
+ value: groupProvider.name,
+ disabled: groupProvider.name ? true : false,
+ label: "Name*:",
+ regexp: "^[\x20-\x2e\x30-\x7F]{1,255}$",
+ name: "name"});
+ }
+ }, {
+ name: "type",
+ createWidget: function(groupProvider) {
+
+ var typeContainer = construct.create("div");
+
+ var typeListContainer = new dojox.layout.TableContainer({
+ cols: 1,
+ "labelWidth": "300",
+ customClass: "formLabel",
+ showLabels: true,
+ orientation: "horiz"
+ });
+
+ typeContainer.appendChild(typeListContainer.domNode);
+
+ var providers = [];
+ var fieldSetContainers = {};
+ xhr.get({
+ url: "rest/helper?action=ListGroupProviderAttributes",
+ handleAs: "json",
+ sync: true
+ }).then(
+ function(data) {
+ var providerIndex = 0;
+
+ for (var providerType in data) {
+ if (data.hasOwnProperty(providerType)) {
+ providers[providerIndex++] = {id: providerType, name: providerType};
+
+ var attributes = data[providerType].attributes;
+ var descriptions = data[providerType].descriptions;
+
+ var layout = new dojox.layout.TableContainer( {
+ cols: 1,
+ "labelWidth": "300",
+ customClass: "formLabel",
+ showLabels: true,
+ orientation: "horiz"
+ });
+
+ for(var i=0; i < attributes.length; i++) {
+ if ("type" == attributes[i])
+ {
+ continue;
+ }
+ var labelValue = attributes[i];
+ if (descriptions && descriptions[attributes[i]])
+ {
+ labelValue = descriptions[attributes[i]];
+ }
+ var text = new dijit.form.TextBox({
+ label: labelValue + ":",
+ name: attributes[i]
+ });
+ layout.addChild(text);
+ }
+
+ typeContainer.appendChild(layout.domNode);
+ fieldSetContainers[providerType] = layout;
+ }
+ }
+ });
+
+ var providersStore = new dojo.store.Memory({ data: providers });
+
+ var typeList = new dijit.form.FilteringSelect({
+ required: true,
+ value: groupProvider.type,
+ store: providersStore,
+ label: "Type*:",
+ name: "type"});
+
+ typeListContainer.addChild(typeList);
+
+ var onChangeHandler = function onChangeHandler(newValue){
+ for (var i in fieldSetContainers) {
+ var container = fieldSetContainers[i];
+ var descendants = container.getChildren();
+ for(var i in descendants){
+ var descendant = descendants[i];
+ var propName = descendant.name;
+ if (propName) {
+ descendant.set("disabled", true);
+ }
+ }
+ container.domNode.style.display = "none";
+ }
+ var container = fieldSetContainers[newValue];
+ if (container)
+ {
+ container.domNode.style.display = "block";
+ var descendants = container.getChildren();
+ for(var i in descendants){
+ var descendant = descendants[i];
+ var propName = descendant.name;
+ if (propName) {
+ descendant.set("disabled", false);
+ }
+ }
+ }
+ };
+ typeList.on("change", onChangeHandler);
+ onChangeHandler(typeList.value);
+ return new dijit.layout.ContentPane({content: typeContainer, style:{padding: 0}});
+ }
+ }];
+
+ util.showSetAttributesDialog(
+ fields,
+ groupProvider ? groupProvider : {},
+ "rest/groupprovider" + (name ? "/" + encodeURIComponent(name.name) : ""),
+ groupProvider ? "Edit group provider - " + groupProvider.name : "Add group provider",
+ groupProvider ? false : true);
+ };
+ return addGroupProvider;
+ }); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addKeystore.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addKeystore.js
new file mode 100644
index 0000000000..4fdcffb7f1
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addKeystore.js
@@ -0,0 +1,164 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+define(["dojo/_base/lang",
+ "dojo/_base/xhr",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dijit/registry",
+ "dojo/parser",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ 'dojo/_base/json',
+ "qpid/common/util",
+ "dojo/store/Memory",
+ "dojox/validate/us",
+ "dojox/validate/web",
+ "dijit/Dialog",
+ "dijit/form/CheckBox",
+ "dijit/form/Textarea",
+ "dijit/form/ComboBox",
+ "dijit/form/TextBox",
+ "dijit/form/ValidationTextBox",
+ "dijit/form/Button",
+ "dijit/form/Form",
+ "dijit/TitlePane",
+ "dojox/layout/TableContainer",
+ "dojo/domReady!"],
+ function (lang, xhr, dom, construct, registry, parser, array, event, json, util) {
+
+ var addKeystore = { };
+
+ addKeystore.createWidgetFactories = function(isKeystore)
+ {
+ var fields = [{
+ name: "name",
+ createWidget: function(keystore) {
+ return new dijit.form.ValidationTextBox({
+ required: true,
+ value: keystore.name,
+ disabled: keystore.name ? true : false,
+ label: "Name:",
+ regexp: "^[\x20-\x2e\x30-\x7F]{1,255}$",
+ name: "name"});
+ }
+ }, {
+ name: "path",
+ createWidget: function(keystore) {
+ return new dijit.form.ValidationTextBox({
+ required: true,
+ value: keystore.path,
+ label: "Path to keystore:",
+ name: "path"});
+ }
+ }, {
+ name: "password",
+ requiredFor: "path",
+ createWidget: function(keystore) {
+ return new dijit.form.ValidationTextBox({
+ required: false,
+ label: "Keystore password:",
+ invalidMessage: "Missed keystore password",
+ name: "password",
+ placeHolder: keystore["password"] ? keystore["password"] : ""
+ });
+ }
+ }];
+ if (!isKeystore)
+ {
+ fields.push({
+ name: "peersOnly",
+ createWidget: function(keystore) {
+ return new dijit.form.CheckBox({
+ required: false,
+ checked: keystore && keystore.peersOnly,
+ label: "Peers only:",
+ name: "peersOnly"});
+ }
+ });
+ }
+ fields.push({
+ name: "Options",
+ createWidget: function(keystore) {
+ var optionalFieldContainer = new dojox.layout.TableContainer({
+ cols: 1,
+ "labelWidth": "290",
+ showLabels: true,
+ orientation: "horiz",
+ customClass: "formLabel"
+ });
+ if (isKeystore)
+ {
+ optionalFieldContainer.addChild(new dijit.form.ValidationTextBox({
+ required: false,
+ value: keystore.certificateAlias,
+ label: "Keystore certificate alias:",
+ name: "certificateAlias"}));
+ optionalFieldContainer.addChild( new dijit.form.ValidationTextBox({
+ required: false,
+ value: keystore.keyManagerFactoryAlgorithm,
+ label: "Key manager factory algorithm:",
+ placeHolder: "Use default",
+ name: "keyManagerFactoryAlgorithm"}));
+ }
+ else
+ {
+ optionalFieldContainer.addChild( new dijit.form.ValidationTextBox({
+ required: false,
+ value: keystore.trustManagerFactoryAlgorithm,
+ label: "Trust manager factory algorithm:",
+ placeHolder: "Use default",
+ name: "trustManagerFactoryAlgorithm"}));
+ }
+ optionalFieldContainer.addChild(new dijit.form.ValidationTextBox({
+ required: false,
+ value: keystore.type,
+ label: "Key store type:",
+ placeHolder: "Use default",
+ name: "type"}));
+ var panel = new dijit.TitlePane({title: "Optional Attributes", content: optionalFieldContainer.domNode, open: false});
+ return panel;
+ }
+ });
+ return fields;
+ }
+
+ addKeystore.showKeystoreDialog = function(keystore) {
+ var keystoreAttributeWidgetFactories = addKeystore.createWidgetFactories(true);
+
+ util.showSetAttributesDialog(
+ keystoreAttributeWidgetFactories,
+ keystore ? keystore : {},
+ "rest/keystore" + (keystore ? "/" + encodeURIComponent(keystore.name) : ""),
+ keystore ? "Edit keystore - " + keystore.name : "Add keystore",
+ keystore ? false : true);
+ };
+
+ addKeystore.showTruststoreDialog = function(truststore) {
+ var truststoreAttributeWidgetFactories = addKeystore.createWidgetFactories(false);
+ util.showSetAttributesDialog(
+ truststoreAttributeWidgetFactories,
+ truststore ? truststore : {},
+ "rest/truststore" + (truststore ? "/" + encodeURIComponent(truststore.name) : ""),
+ truststore ? "Edit truststore - " + truststore.name : "Add truststore",
+ truststore ? false : true);
+ };
+ return addKeystore;
+ }); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js
index 0c1a188cbf..cf50b39c87 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js
@@ -28,6 +28,7 @@ define(["dojo/_base/xhr",
"dojo/_base/event",
'dojo/_base/json',
"dojo/store/Memory",
+ "dojo/data/ObjectStore",
"dijit/form/FilteringSelect",
"dojo/dom-style",
"dojo/_base/lang",
@@ -50,9 +51,10 @@ define(["dojo/_base/xhr",
"dijit/form/Select",
"dijit/form/NumberSpinner",
/* basic dojox classes */
- "dojox/form/BusyButton",
+ "dojox/grid/EnhancedGrid",
+ "dojox/grid/enhanced/plugins/IndirectSelection",
"dojo/domReady!"],
- function (xhr, dom, construct, win, registry, parser, array, event, json, Memory, FilteringSelect, domStyle, lang) {
+ function (xhr, dom, construct, win, registry, parser, array, event, json, Memory, ObjectStore, FilteringSelect, domStyle, lang) {
var addPort = {};
@@ -110,36 +112,79 @@ define(["dojo/_base/xhr",
var type = dijit.byId("formAddPort.type").value;
if (type == "AMQP")
{
+ var transportWidget = registry.byId("formAddPort.transports");
var needClientAuth = dijit.byId("formAddPort.needClientAuth");
var wantClientAuth = dijit.byId("formAddPort.wantClientAuth");
- newPort.needClientAuth = needClientAuth.disabled ? false : needClientAuth.checked;
- newPort.wantClientAuth = wantClientAuth.disabled ? false : wantClientAuth.checked
+ var trustStoreWidget = dijit.byId("formAddPort.trustStores");
+
+ var initialTransport = transportWidget.initialValue;
+ var currentTransport = transportWidget.value;
+ if (currentTransport == "SSL")
+ {
+ newPort.needClientAuth = needClientAuth.checked;
+ newPort.wantClientAuth = wantClientAuth.checked
+
+ var items = trustStoreWidget.selection.getSelected();
+ var trustStores = [];
+ if(items.length > 0){
+ for(var i in items)
+ {
+ var item = items[i];
+ trustStores.push(trustStoreWidget.store.getValue(item, "name"));
+ }
+ newPort.trustStores = trustStores;
+ }
+ else if (trustStoreWidget.initialValue && trustStoreWidget.initialValue.length > 0)
+ {
+ newPort.trustStores = null;
+ }
+ }
+ else if (initialTransport && currentTransport != initialTransport)
+ {
+ newPort.needClientAuth = false;
+ newPort.wantClientAuth = false;
+ newPort.trustStores = null;
+ }
}
+
return newPort;
};
- var toggleCertificateWidgets = function toggleCertificateWidgets(protocolType, transportType)
+ var toggleSslWidgets = function toggleSslWidgets(protocolType, transportType)
{
- var clientAuthPanel = registry.byId("formAddPort:fieldsClientAuth");
- var display = clientAuthPanel.domNode.style.display;
+ var clientAuthPanel = dojo.byId("formAddPort:fieldsClientAuth");
+ var display = clientAuthPanel.style.display;
if (transportType == "SSL" && protocolType == "AMQP")
{
- clientAuthPanel.domNode.style.display = "block";
+ clientAuthPanel.style.display = "block";
registry.byId("formAddPort.needClientAuth").set("disabled", false);
registry.byId("formAddPort.wantClientAuth").set("disabled", false);
}
else
{
- clientAuthPanel.domNode.style.display = "none";
+ clientAuthPanel.style.display = "none";
registry.byId("formAddPort.needClientAuth").set("disabled", true);
registry.byId("formAddPort.wantClientAuth").set("disabled", true);
}
- if (clientAuthPanel.domNode.style.display != display)
+
+ var transportSSLPanel = registry.byId("formAddPort:fieldsTransportSSL");
+ var transportSSLPanelDisplay = transportSSLPanel.domNode.style.display;
+ if (transportType == "SSL")
{
- clientAuthPanel.resize();
+ transportSSLPanel.domNode.style.display = "block";
+ registry.byId("formAddPort.keyStore").set("disabled", false);
+ }
+ else
+ {
+ transportSSLPanel.domNode.style.display = "none";
+ registry.byId("formAddPort.keyStore").set("disabled", true);
}
- };
+ if (transportSSLPanel.domNode.style.display != transportSSLPanelDisplay && transportSSLPanel.domNode.style.display=="block")
+ {
+ registry.byId("formAddPort.trustStores").resize();
+ }
+ };
xhr.get({url: "addPort.html",
sync: true,
@@ -155,7 +200,7 @@ define(["dojo/_base/xhr",
registry.byId("formAddPort.transports").on("change", function(newValue){
var protocolType = registry.byId("formAddPort.type").value;
- toggleCertificateWidgets(protocolType, newValue);
+ toggleSslWidgets(protocolType, newValue);
});
registry.byId("formAddPort.type").on("change", function(newValue) {
@@ -166,8 +211,9 @@ define(["dojo/_base/xhr",
registry.byId("formAddPort:fields" + option.value).domNode.style.display = "none";
});
- registry.byId("formAddPort.needClientAuth").set("enabled", ("AMQP" == newValue));
- registry.byId("formAddPort.wantClientAuth").set("enabled", ("AMQP" == newValue));
+ var isAMQP = ("AMQP" == newValue);
+ registry.byId("formAddPort.needClientAuth").set("enabled", isAMQP);
+ registry.byId("formAddPort.wantClientAuth").set("enabled", isAMQP);
registry.byId("formAddPort:fields" + newValue).domNode.style.display = "block";
var defaultsAMQPProtocols = registry.byId("formAddPort.protocolsDefault");
@@ -175,19 +221,95 @@ define(["dojo/_base/xhr",
var protocolsWidget = registry.byId("formAddPort.protocols" + newValue);
if (protocolsWidget)
{
- protocolsWidget.set("disabled", ("AMQP" == newValue && defaultsAMQPProtocols.checked));
+ protocolsWidget.set("disabled", (isAMQP && defaultsAMQPProtocols.checked));
+ }
+
+ var transportWidget = registry.byId("formAddPort.transports");
+ var disableTransportWidget = false;
+ var toggleSsl = true;
+ var isRMI = (newValue == "JMX" && registry.byId("formAddPort.protocolsJMX").value == "RMI");
+ if (isRMI)
+ {
+ if (transportWidget.value != "TCP")
+ {
+ transportWidget.set("value", "TCP");
+
+ // changing of transport widget value will cause the call to toggleSslWidgets
+ toggleSsl = false;
+ }
+ disableTransportWidget = true;
+ }
+ else if (newValue == "HTTP" && registry.byId("formAddPort.protocolsHTTP").value == "HTTPS")
+ {
+ if (transportWidget.value != "SSL")
+ {
+ transportWidget.set("value", "SSL");
+
+ // changing of transport widget value will cause the call to toggleSslWidgets
+ toggleSsl = false;
+ }
+ disableTransportWidget = true;
+ }
+ if (toggleSsl)
+ {
+ toggleSslWidgets(newValue, transportWidget.value);
}
- var transport = registry.byId("formAddPort.transports").value;
- toggleCertificateWidgets(newValue, transport);
+ transportWidget.set("disabled", disableTransportWidget);
+ registry.byId("formAddPort.authenticationProvider").set("disabled", isRMI);
+ registry.byId("formAddPort:fieldsAuthenticationProvider").domNode.style.display = isRMI? "none" : "block";
});
+
theForm = registry.byId("formAddPort");
+ var containers = ["formAddPort:fields", "formAddPort:fieldsTransportSSL", "formAddPort:fieldsAMQP",
+ "formAddPort:fieldsJMX", "formAddPort:fieldsHTTP", "formAddPort:transport",
+ "formAddPort:fieldsClientAuthCheckboxes", "formAddPort:fieldsAuthenticationProvider"];
+ var labelWidthValue = "200";
+ for(var i = 0; i < containers.length; i++)
+ {
+ var containerId = containers[i];
+ var fields = new dojox.layout.TableContainer( {
+ cols: 1,
+ labelWidth: labelWidthValue,
+ showLabels: true,
+ orientation: "horiz",
+ customClass: "formLabel"
+ }, dom.byId(containerId));
+ fields.startup();
+ }
+
+ registry.byId("formAddPort.protocolsJMX").on("change", function(newValue){
+ var isRMI = newValue == "RMI";
+ var transportWidget = registry.byId("formAddPort.transports");
+ if (isRMI && transportWidget.value != "TCP")
+ {
+ transportWidget.set("value", "TCP");
+ }
+ transportWidget.set("disabled", isRMI);
+ registry.byId("formAddPort:fieldsAuthenticationProvider").domNode.style.display = isRMI? "none" : "block";
+ registry.byId("formAddPort.authenticationProvider").set("disabled", isRMI);
+ });
+
+ registry.byId("formAddPort.protocolsHTTP").on("change", function(newValue){
+ var isHTTPS = newValue == "HTTPS";
+ var transportWidget = registry.byId("formAddPort.transports");
+ if (isHTTPS && transportWidget.value != "SSL") {
+ transportWidget.set("value", "SSL");
+ }
+ transportWidget.set("disabled", isHTTPS);
+ });
+
theForm.on("submit", function(e) {
event.stop(e);
if(theForm.validate()){
var newPort = convertToPort(theForm.getValues());
+ if ((newPort.needClientAuth || newPort.wantClientAuth) && (!newPort.hasOwnProperty("trustStores") || newPort.trustStores.length==0))
+ {
+ alert("A trustore must be selected when requesting client certificates.");
+ return false;
+ }
var that = this;
xhr.put({url: "rest/port/"+encodeURIComponent(newPort.name), sync: true, handleAs: "json",
@@ -216,52 +338,8 @@ define(["dojo/_base/xhr",
});
}});
- addPort.show = function(portName, providers) {
+ addPort.show = function(portName, providers, keystores, truststores) {
- if (!addPort.fields)
- {
- var labelWidthValue = "300";
- addPort.fields = new dojox.layout.TableContainer( {
- cols: 1,
- labelWidth: labelWidthValue,
- showLabels: true,
- orientation: "horiz",
- customClass: "formLabel"
- }, dom.byId("formAddPort:fields"));
- addPort.fields.startup();
- addPort.fieldsClientAuth = new dojox.layout.TableContainer( {
- cols: 1,
- labelWidth: labelWidthValue,
- showLabels: true,
- orientation: "horiz",
- customClass: "formLabel"
- }, dom.byId("formAddPort:fieldsClientAuth"));
- addPort.fieldsClientAuth.startup();
- addPort.fieldsAMQP = new dojox.layout.TableContainer( {
- cols: 1,
- labelWidth: labelWidthValue,
- showLabels: true,
- orientation: "horiz",
- customClass: "formLabel"
- }, dom.byId("formAddPort:fieldsAMQP"));
- addPort.fieldsAMQP.startup();
- addPort.fieldsJMX = new dojox.layout.TableContainer( {
- cols: 1,
- labelWidth: labelWidthValue,
- showLabels: true,
- orientation: "horiz",
- customClass: "formLabel"
- }, dom.byId("formAddPort:fieldsJMX"));
- addPort.fieldsJMX.startup();
- addPort.fieldsHTTP = new dojox.layout.TableContainer( {
- cols: 1,
- labelWidth: labelWidthValue,
- showLabels: true,
- orientation: "horiz",
- customClass: "formLabel"
- }, dom.byId("formAddPort:fieldsHTTP"));
- addPort.fieldsHTTP.startup();
- }
registry.byId("formAddPort").reset();
dojo.byId("formAddPort.id").value = "";
@@ -278,6 +356,36 @@ define(["dojo/_base/xhr",
providerWidget.startup();
}
+ var keystoreWidget = registry.byId("formAddPort.keyStore");
+ if (keystores)
+ {
+ var data = [];
+ for (var i=0; i< keystores.length; i++)
+ {
+ data.push( {id: keystores[i].name, name: keystores[i].name} );
+ }
+ var keystoresStore = new Memory({ data: data });
+ keystoreWidget.set("store", keystoresStore);
+ keystoreWidget.startup();
+ }
+
+ var truststoreWidget = registry.byId("formAddPort.trustStores");
+ if (truststores)
+ {
+ var layout = [[{name: "Name", field: "name", width: "80%"},
+ {name: "Peers only", field: "peersOnly", width: "20%",
+ formatter: function(val){
+ return "<input type='radio' disabled='disabled' "+(val?"checked='checked'": "")+" />"
+ }
+ }]];
+
+ var mem = new Memory({ data: truststores, idProperty: "id"});
+ truststoreWidget.set("store", new ObjectStore({objectStore: mem}));
+ truststoreWidget.set("structure", layout);
+ truststoreWidget.rowSelectCell.toggleAllSelection(false);
+ truststoreWidget.startup();
+ }
+
if (portName)
{
xhr.get({
@@ -291,11 +399,32 @@ define(["dojo/_base/xhr",
nameField.set("disabled", true);
dom.byId("formAddPort.id").value=port.id;
providerWidget.set("value", port.authenticationProvider ? port.authenticationProvider : "");
+ keystoreWidget.set("value", port.keyStore ? port.keyStore : "");
+ if (port.trustStores)
+ {
+ var items = truststoreWidget.store.objectStore.data;
+ for (var j=0; j< items.length; j++)
+ {
+ var selected = false;
+ for (var i=0; i< port.trustStores.length; i++)
+ {
+ var trustStore = port.trustStores[i];
+ if (items[j].name == trustStore)
+ {
+ selected = true;
+ break;
+ }
+ }
+ truststoreWidget.selection.setSelected(j,selected);
+ }
+ }
+
var transportWidget = registry.byId("formAddPort.transports");
transportWidget.set("value", port.transports ? port.transports[0] : "");
registry.byId("formAddPort.port").set("value", port.port);
var protocols = port.protocols;
var typeWidget = registry.byId("formAddPort.type");
+
var store = typeWidget.store;
store.data.forEach(function(option){
registry.byId("formAddPort.protocols" + option.value).set("disabled", true);
@@ -310,7 +439,7 @@ define(["dojo/_base/xhr",
var defaultProtocolsWidget = registry.byId("formAddPort.protocolsDefault");
var addressWidget = registry.byId("formAddPort.bindingAddress");
addressWidget.set("value", port.bindingAddress);
- amqpProtocolsWidget.set("disabled", false);
+
if (protocols)
{
amqpProtocolsWidget.set("value", protocols)
@@ -343,16 +472,24 @@ define(["dojo/_base/xhr",
registry.byId("formAddPort:fields" + typeWidget.value).domNode.style.display = "block";
typeWidget.set("disabled", true);
- toggleCertificateWidgets(typeWidget.value, transportWidget.value);
+ keystoreWidget.initialValue = port.keyStore;
+ truststoreWidget.initialValue = port.trustStores;
+ transportWidget.initialValue = transportWidget.value;
+ providerWidget.initialValue = providerWidget.value;
+
registry.byId("addPort").show();
});
}
else
{
var typeWidget = registry.byId("formAddPort.type");
- typeWidget.set("disabled", false);
+ if (typeWidget.get("disabled"))
+ {
+ typeWidget.set("disabled", false);
+ }
typeWidget.set("value", "AMQP");
- registry.byId("formAddPort.name").set("disabled", false);
+ var name = registry.byId("formAddPort.name");
+ name.set("disabled", false);
registry.byId("addPort").show();
}
};
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js
index 5d3a666760..cd18a0c4b6 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js
@@ -29,15 +29,20 @@ define(["dojo/dom",
"qpid/management/AuthenticationProvider",
"qpid/management/GroupProvider",
"qpid/management/group/Group",
+ "qpid/management/KeyStore",
+ "qpid/management/TrustStore",
+ "qpid/management/AccessControlProvider",
+ "qpid/management/Port",
"dojo/ready",
"dojo/domReady!"],
- function (dom, registry, ContentPane, Broker, VirtualHost, Exchange, Queue, Connection, AuthProvider, GroupProvider, Group, ready) {
+ function (dom, registry, ContentPane, Broker, VirtualHost, Exchange, Queue, Connection, AuthProvider, GroupProvider, Group, KeyStore, TrustStore, AccessControlProvider, Port, ready) {
var controller = {};
var constructors = { broker: Broker, virtualhost: VirtualHost, exchange: Exchange,
queue: Queue, connection: Connection,
authenticationprovider: AuthProvider, groupprovider: GroupProvider,
- group: Group };
+ group: Group, keystore: KeyStore, truststore: TrustStore,
+ accesscontrolprovider: AccessControlProvider, port: Port};
var tabDiv = dom.byId("managedViews");
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js
index 44fc9702e2..02276b8713 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js
@@ -82,11 +82,12 @@ define(["dojo/_base/xhr",
xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
.then(function(data) {
+ that.path = query(".path", node)[0];
that.groupProviderData = data[0];
util.flattenStatistics( that.groupProviderData );
- var groupDiv = query(".groups")[0];
+ var groupDiv = query(".groups", node)[0];
var gridProperties = {
height: 400,
@@ -109,7 +110,15 @@ define(["dojo/_base/xhr",
that.groupsGrid =
new UpdatableStore(that.groupProviderData.groups, groupDiv,
[ { name: "Group Name", field: "name", width: "100%" }
- ], null, gridProperties, EnhancedGrid);
+ ], 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("group", name, groupProviderObj);
+ });
+ }, gridProperties, EnhancedGrid);
var addGroupButton = query(".addGroupButton", node)[0];
@@ -167,6 +176,7 @@ define(["dojo/_base/xhr",
xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"})
.then(function(data) {
that.groupProviderData = data[0];
+ that.path.innerHTML = that.groupProviderData.path;
util.flattenStatistics( that.groupProviderData );
that.groupsGrid.update(that.groupProviderData.groups);
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js
index 59356cfce1..7bb52b938f 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js
@@ -277,8 +277,13 @@ define(["dojo/_base/xhr",
controller.show("groupprovider", details.groupprovider, {broker: {type:"broker", name:""}});
} else if (details.type == 'group') {
controller.show("group", details.group, { type: "groupprovider", name: details.groupprovider, parent: {broker: {type:"broker", name:""}}});
+ } else if (details.type == 'keystore') {
+ controller.show("keystore", details.keystore, {broker: {type:"broker", name:""}});
+ } else if (details.type == 'truststore') {
+ controller.show("truststore", details.truststore, {broker: {type:"broker", name:""}});
+ } else if (details.type == 'accesscontrolprovider') {
+ controller.show("accesscontrolprovider", details.accesscontrolprovider, {broker: {type:"broker", name:""}});
}
-
};
TreeViewModel.prototype.update = function () {
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/login.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/login.html
new file mode 100644
index 0000000000..aaa2855bd2
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/login.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Qpid Management Login</title>
+ <link rel="stylesheet" href="dojo/dojo/resources/dojo.css">
+ <link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css">
+ <link rel="stylesheet" href="css/common.css" media="screen">
+ <script>
+ function getContextPath()
+ {
+ var contextPath = "/";
+ var documentURL = document.URL;
+ var managementPageStart = documentURL.lastIndexOf("/");
+ var firstSlashPos = documentURL.indexOf("/", documentURL.indexOf("//") + 2);
+ if (managementPageStart > firstSlashPos)
+ {
+ contextPath = documentURL.substring(firstSlashPos, managementPageStart);
+ }
+ return contextPath;
+ }
+
+ var dojoConfig = {
+ tlmSiblingOfDojo:false,
+ parseOnLoad:true,
+ async:true,
+ baseUrl: getContextPath(),
+ packages:[
+ { name:"dojo", location:"dojo/dojo" },
+ { name:"dijit", location:"dojo/dijit" },
+ { name:"dojox", location:"dojo/dojox" },
+ { name:"qpid", location:"js/qpid" }
+ ]
+ };
+
+ </script>
+ <script src="dojo/dojo/dojo.js">
+ </script>
+
+ <script>
+ require(["dojo/_base/xhr",
+ "dojo/parser",
+ "dijit/form/Form",
+ "dijit/form/Button",
+ "dijit/form/TextBox",
+ "dijit/form/ValidationTextBox",
+ "dijit/layout/BorderContainer",
+ "dijit/layout/ContentPane",
+ "dijit/TitlePane",
+ "dojox/layout/TableContainer",
+ "dojox/validate/us",
+ "dojox/validate/web",
+ "qpid/common/footer"]);
+ </script>
+
+</head>
+<body class="claro">
+
+<div id="pageLayout" data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design: 'headline', gutters: false">
+ <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'top'">
+ <div id="header" class="header" style="float: left; width: 300px"></div>
+ <div id="login" style="float: right"></div>
+ </div>
+ <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'center'">
+ <div style="width:350px; margin-left: auto; margin-right: auto;">
+ <div data-dojo-type="dijit.form.Form" method="POST" id="loginForm">
+ <script type="dojo/on" data-dojo-event="submit" data-dojo-args="e">
+ e.preventDefault()
+ if(this.validate()){
+ require(["qpid/authorization/sasl"], function(sasl){
+ var redirectIfAuthenticated = function redirectIfAuthenticated(){
+ sasl.getUser(function(data){
+ if(data.user){
+ window.location = "index.html";
+ }
+ });
+ };
+
+ sasl.authenticate(dijit.byId("username").value, dijit.byId("password").value, redirectIfAuthenticated);
+ });
+ }
+ return false;
+ </script>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title:'Login', toggleable: false" >
+ <div class="dijitDialogPaneContentArea">
+ <div data-dojo-type="dojox.layout.TableContainer" data-dojo-props="cols:1,labelWidth:'100',showLabels:true,orientation:'horiz',customClass:'formLabel'">
+ <div data-dojo-type="dijit.form.ValidationTextBox" id="username" name="username" data-dojo-props="label:'User name:',required:true, intermediateChanges:true"></div>
+ <div data-dojo-type="dijit.form.ValidationTextBox" type="password" id="password" name="password" data-dojo-props="label:'Password:',required:true, intermediateChanges:true"></div>
+ </div>
+ </div>
+ <div class="dijitDialogPaneActionBar">
+ <button data-dojo-type="dijit.form.Button" type="submit" id="loginButton">Login</button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'bottom'">
+ <div qpid-type="footer"></div>
+ </div>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showAccessControlProvider.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showAccessControlProvider.html
new file mode 100644
index 0000000000..399425a7de
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showAccessControlProvider.html
@@ -0,0 +1,31 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<div class="accessControlProvider">
+ <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span>
+ <br/>
+ <span style="">Type:</span><span class="type" style="position:absolute; left:6em"></span>
+ <br/>
+ <div class="providerDetails"></div>
+ <div class="dijitDialogPaneActionBar">
+ <input class="deleteAccessControlProviderButton" type="button" value="Delete Access Control provider" label="Delete Access Control Provider" dojoType="dijit.form.Button" />
+ </div>
+</div>
+<br/> \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html
index 887ca4e736..d9991452af 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html
@@ -53,36 +53,10 @@
<div class="formLabel-labelCell" style="float:left; width: 250px;">Broker store location:</div>
<div id="brokerAttribute.storePath" style="float:left;"></div>
</div>
- <div id="brokerAttribute.defaultAuthenticationProvider.container" style="display: none; clear:both">
- <div class="formLabel-labelCell" style="float:left; width: 250px;">Default authentication provider:</div>
- <div id="brokerAttribute.defaultAuthenticationProvider" style="float:left;"></div>
- </div>
<div id="brokerAttribute.defaultVirtualHost.container" style="display: none; clear:both; clear:both;">
<div class="formLabel-labelCell" style="float:left; width: 250px;">Default virtual host:</div>
<div id="brokerAttribute.defaultVirtualHost" style="float:left;"></div>
</div>
- <div id="brokerAttribute.aclFile.container" style="display: none; clear:both">
- <div class="formLabel-labelCell" style="float:left; width: 250px;">ACL file location:</div>
- <div id="brokerAttribute.aclFile" style="float:left;"></div>
- </div>
- <div id="brokerAttribute.groupFile.container" style="display: none; clear:both">
- <div class="formLabel-labelCell" style="float:left; width: 250px;">Group file location:</div>
- <div id="brokerAttribute.groupFile" style="float:left;"></div>
- </div>
- <div id="brokerAttribute.keyStorePath.container" style="display: none; clear:both">
- <div class="formLabel-labelCell" style="float:left; width: 250px;">Path to keystore:</div>
- <div id="brokerAttribute.keyStorePath" style="float:left;"></div><br/>
- <div class="formLabel-labelCell" style="float:left; width: 250px;">Keystore certificate alias:</div>
- <div id="brokerAttribute.keyStoreCertAlias" style="float:left;"></div>
- </div>
- <div id="brokerAttribute.trustStorePath.container" style="display: none; clear:both">
- <div class="formLabel-labelCell" style="float:left; width: 250px;">Path to truststore:</div>
- <div id="brokerAttribute.trustStorePath" style="float:left;"></div>
- </div>
- <div id="brokerAttribute.peerStorePath.container" style="display: none; clear:both">
- <div class="formLabel-labelCell" style="float:left; width: 250px;">Path to peerstore:</div>
- <div id="brokerAttribute.peerStorePath" style="float:left;"></div>
- </div>
<div id="brokerAttribute.statisticsReportingPeriod.container" style="display: none; clear:both">
<div class="formLabel-labelCell" style="float:left; width: 250px;">Statistics reporting period:</div>
<div id="brokerAttribute.statisticsReportingPeriod" style="float:left;"></div>
@@ -191,6 +165,31 @@
<button data-dojo-type="dijit.form.Button" class="deleteAuthenticationProvider">Delete Provider</button>
</div>
<br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Key stores'">
+ <div class="broker-key-stores"></div>
+ <button data-dojo-type="dijit.form.Button" class="addKeystore">Add Key Store</button>
+ <button data-dojo-type="dijit.form.Button" class="deleteKeystore">Delete Key Store</button>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Trust stores'">
+ <div class="broker-trust-stores"></div>
+ <button data-dojo-type="dijit.form.Button" class="addTruststore">Add Trust Store</button>
+ <button data-dojo-type="dijit.form.Button" class="deleteTruststore">Delete Trust Store</button>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Group Providers'">
+ <div class="broker-group-providers"></div>
+ <button data-dojo-type="dijit.form.Button" class="addGroupProvider">Add Group Provider</button>
+ <button data-dojo-type="dijit.form.Button" class="deleteGroupProvider">Delete Group Provider</button>
+ </div>
+ <br/>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Access Control Providers'">
+ <div class="broker-access-control-providers-warning" style="color: red"></div>
+ <div class="broker-access-control-providers"></div>
+ <button data-dojo-type="dijit.form.Button" class="addAccessControlProvider">Add Access Control Provider</button>
+ <button data-dojo-type="dijit.form.Button" class="deleteAccessControlProvider">Delete Access Control Provider</button>
+ </div>
+ <br/>
<div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Log File', open: false">
<div class="broker-logfile"></div>
</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html
index 914857db5c..332c7f5eaa 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html
@@ -22,4 +22,10 @@
<span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span>
<br/>
<span style="">Type:</span><span class="type" style="position:absolute; left:6em"></span>
-</div> \ No newline at end of file
+ <br/>
+ <div class="providerDetails"></div>
+ <div class="dijitDialogPaneActionBar">
+ <input class="deleteGroupProviderButton" type="button" value="Delete Group provider" label="Delete Group Provider" dojoType="dijit.form.Button" />
+ </div>
+</div>
+<br/> \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showKeyStore.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showKeyStore.html
new file mode 100644
index 0000000000..5caee836d3
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showKeyStore.html
@@ -0,0 +1,47 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<div class="keystore">
+ <div class="keyStoreContainer">
+
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Name:</div>
+ <div class="nameValue" style="float:left;"></div><br/>
+
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Type:</div>
+ <div class="typeValue" style="float:left;"></div><br/>
+
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Key Manager Factory Algorithm:</div>
+ <div class="keyManagerFactoryAlgorithmValue" style="float:left;"></div><br/>
+
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Path:</div>
+ <div class="pathValue" style="float:left;"></div><br/>
+
+ <div class="certificateAlias">
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Certificate alias:</div>
+ <div class="certificateAliasValue" style="float:left;"></div><br>
+ </div>
+
+ </div>
+ <br/>
+ <div class="dijitDialogPaneActionBar">
+ <button data-dojo-type="dijit.form.Button" class="editKeyStoreButton" type="button">Edit</button>
+ <button data-dojo-type="dijit.form.Button" class="deleteKeyStoreButton" type="button">Delete</button>
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showPort.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showPort.html
new file mode 100644
index 0000000000..f297f2d751
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showPort.html
@@ -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.
+ -
+ -->
+<div class="port">
+ <div class="portContainer">
+
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Name:</div>
+ <div class="nameValue" style="float:left;"></div><br/>
+
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Port Number:</div>
+ <div class="portValue" style="float:left;"></div><br/>
+
+ <div class="authenticationProvider" style="clear:both">
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Authentication Provider:</div>
+ <div class="authenticationProviderValue" style="float:left;"></div><br/>
+ </div>
+
+ <div class="protocols" style="clear:both">
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Protocols:</div>
+ <div class="protocolsValue" style="float:left;"></div><br/>
+ </div>
+
+ <div class="transports" style="clear:both">
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Transports:</div>
+ <div class="transportsValue" style="float:left;"></div><br/>
+ </div>
+
+ <div class="bindingAddress" style="clear:both">
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Binding address:</div>
+ <div class="bindingAddressValue" style="float:left;"></div><br>
+ </div>
+
+ <div class="keyStore" style="clear:both">
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Key Store:</div>
+ <div class="keyStoreValue" style="float:left;"></div><br>
+ </div>
+
+ <div class="needClientAuth" style="clear:both">
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Need SSL Client Certificate:</div>
+ <div class="needClientAuthValue" style="float:left;"></div><br>
+ </div>
+
+ <div class="wantClientAuth" style="clear:both">
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Want SSL Client Certificate:</div>
+ <div class="wantClientAuthValue" style="float:left;"></div><br>
+ </div>
+
+ <div class="trustStores" style="clear:both">
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Trust Stores:</div>
+ <div class="trustStoresValue" style="float:left;"></div><br>
+ </div>
+
+ </div>
+ <br/>
+
+ <div class="dijitDialogPaneActionBar">
+ <button data-dojo-type="dijit.form.Button" class="editPortButton" type="button">Edit</button>
+ <button data-dojo-type="dijit.form.Button" class="deletePortButton" type="button">Delete</button>
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showTrustStore.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showTrustStore.html
new file mode 100644
index 0000000000..6f9146fdfe
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showTrustStore.html
@@ -0,0 +1,47 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<div class="truststore">
+ <div class="trustStoreContainer">
+
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Name:</div>
+ <div class="nameValue" style="float:left;"></div><br/>
+
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Type:</div>
+ <div class="typeValue" style="float:left;"></div><br/>
+
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Trust Manager Factory Algorithm:</div>
+ <div class="trustManagerFactoryAlgorithmValue" style="float:left;"></div><br/>
+
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Path:</div>
+ <div class="pathValue" style="float:left;"></div><br/>
+
+ <div class="peersOnly">
+ <div class="formLabel-labelCell" style="float:left; width: 250px;">Peer store:</div>
+ <div class="peersOnlyValue" style="float:left;"></div>
+ </div>
+
+ </div>
+ <br/>
+ <div class="dijitDialogPaneActionBar">
+ <button data-dojo-type="dijit.form.Button" class="editTrustStoreButton" type="button">Edit</button>
+ <button data-dojo-type="dijit.form.Button" class="deleteTrustStoreButton" type="button">Delete</button>
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java
new file mode 100644
index 0000000000..55606af117
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java
@@ -0,0 +1,105 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.security.SubjectCreator;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class HttpManagementTest extends QpidTestCase
+{
+ private UUID _id;
+ private Broker _broker;
+ private HttpManagement _management;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _id = UUID.randomUUID();
+ _broker = mock(Broker.class);
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(HttpManagement.HTTP_BASIC_AUTHENTICATION_ENABLED, false);
+ attributes.put(HttpManagement.HTTPS_BASIC_AUTHENTICATION_ENABLED, true);
+ attributes.put(HttpManagement.HTTP_SASL_AUTHENTICATION_ENABLED, false);
+ attributes.put(HttpManagement.HTTPS_SASL_AUTHENTICATION_ENABLED, true);
+ attributes.put(HttpManagement.NAME, getTestName());
+ attributes.put(HttpManagement.TIME_OUT, 10000l);
+ _management = new HttpManagement(_id, _broker, attributes);
+ }
+
+ public void testGetBroker()
+ {
+ assertEquals("Unexpected broker", _broker, _management.getBroker());
+ }
+
+ public void testGetSessionTimeout()
+ {
+ assertEquals("Unexpected session timeout", 10000l, _management.getSessionTimeout());
+ }
+
+ public void testGetName()
+ {
+ assertEquals("Unexpected name", getTestName(), _management.getName());
+ }
+
+ public void testIsHttpsSaslAuthenticationEnabled()
+ {
+ assertEquals("Unexpected value for the https sasl enabled attribute", true,
+ _management.isHttpsSaslAuthenticationEnabled());
+ }
+
+ public void testIsHttpSaslAuthenticationEnabled()
+ {
+ assertEquals("Unexpected value for the http sasl enabled attribute", false, _management.isHttpSaslAuthenticationEnabled());
+ }
+
+ public void testIsHttpsBasicAuthenticationEnabled()
+ {
+ assertEquals("Unexpected value for the https basic authentication enabled attribute", true,
+ _management.isHttpsBasicAuthenticationEnabled());
+ }
+
+ public void testIsHttpBasicAuthenticationEnabled()
+ {
+ assertEquals("Unexpected value for the http basic authentication enabled attribute", false,
+ _management.isHttpBasicAuthenticationEnabled());
+ }
+
+ public void testGetSubjectCreator()
+ {
+ SocketAddress localAddress = InetSocketAddress.createUnresolved("localhost", 8080);
+ SubjectCreator subjectCreator = mock(SubjectCreator.class);
+ when(_broker.getSubjectCreator(localAddress)).thenReturn(subjectCreator);
+ SubjectCreator httpManagementSubjectCreator = _management.getSubjectCreator(localAddress);
+ assertEquals("Unexpected subject creator", subjectCreator, httpManagementSubjectCreator);
+ }
+
+}
diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java
index 93f7df8c85..d094134e11 100644
--- a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java
+++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java
@@ -22,14 +22,15 @@ package org.apache.qpid.server.jmx;
import org.apache.log4j.Logger;
import org.apache.qpid.server.configuration.BrokerProperties;
-import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.KeyStore;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Transport;
-import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator;
+import org.apache.qpid.server.security.auth.jmx.JMXPasswordAuthenticator;
+import org.apache.qpid.ssl.SSLContextFactory;
import javax.management.JMException;
import javax.management.MBeanServer;
@@ -39,10 +40,8 @@ import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.MBeanServerForwarder;
import javax.management.remote.rmi.RMIConnectorServer;
+import javax.net.ssl.SSLContext;
import javax.rmi.ssl.SslRMIClientSocketFactory;
-import javax.rmi.ssl.SslRMIServerSocketFactory;
-import java.io.File;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
@@ -57,6 +56,7 @@ import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.UnicastRemoteObject;
+import java.security.GeneralSecurityException;
import java.util.HashMap;
/**
@@ -122,16 +122,32 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
if (connectorSslEnabled)
{
- String keyStorePath = System.getProperty("javax.net.ssl.keyStore");
- String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword");
+ KeyStore keyStore = _connectorPort.getKeyStore();
- validateKeyStoreProperties(keyStorePath, keyStorePassword);
+ String keyStorePath = (String) keyStore.getAttribute(KeyStore.PATH);
+ String keyStorePassword = keyStore.getPassword();
+ String keyStoreType = (String) keyStore.getAttribute(KeyStore.TYPE);
+ String keyManagerFactoryAlgorithm = (String) keyStore.getAttribute(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM);
+
+ SSLContext sslContext;
+ try
+ {
+ sslContext = SSLContextFactory.buildServerContext(keyStorePath, keyStorePassword, keyStoreType, keyManagerFactoryAlgorithm);
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new RuntimeException("Unable to create SSLContext for key store", e);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Unable to create SSLContext for key store", e);
+ }
CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(keyStorePath));
//create the SSL RMI socket factories
csf = new SslRMIClientSocketFactory();
- ssf = new SslRMIServerSocketFactory();
+ ssf = new QpidSslRMIServerSocketFactory(sslContext);
}
else
{
@@ -144,7 +160,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
int jmxPortConnectorServer = _connectorPort.getPort();
//add a JMXAuthenticator implementation the env map to authenticate the RMI based JMX connector server
- RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator(_broker, new InetSocketAddress(jmxPortConnectorServer));
+ JMXPasswordAuthenticator rmipa = new JMXPasswordAuthenticator(_broker, new InetSocketAddress(jmxPortConnectorServer));
HashMap<String,Object> connectorEnv = new HashMap<String,Object>();
connectorEnv.put(JMXConnectorServer.AUTHENTICATOR, rmipa);
@@ -262,31 +278,6 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
return rmiRegistry;
}
- private void validateKeyStoreProperties(String keyStorePath, String keyStorePassword) throws FileNotFoundException
- {
- if (keyStorePath == null)
- {
- throw new IllegalConfigurationException("JVM system property 'javax.net.ssl.keyStore' is not set, "
- + "unable to start requested SSL protected JMX connector");
- }
- if (keyStorePassword == null)
- {
- throw new IllegalConfigurationException( "JVM system property 'javax.net.ssl.keyStorePassword' is not set, "
- + "unable to start requested SSL protected JMX connector");
- }
-
- File ksf = new File(keyStorePath);
- if (!ksf.exists())
- {
- throw new FileNotFoundException("Cannot find SSL keystore file for JMX management: " + ksf);
- }
- if (!ksf.canRead())
- {
- throw new FileNotFoundException("Cannot read SSL keystore file for JMX management: "
- + ksf + ". Check permissions.");
- }
- }
-
@Override
public void registerObject(ManagedObject managedObject) throws JMException
{
diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/QpidSslRMIServerSocketFactory.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/QpidSslRMIServerSocketFactory.java
new file mode 100644
index 0000000000..ab114f0888
--- /dev/null
+++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/QpidSslRMIServerSocketFactory.java
@@ -0,0 +1,105 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.jmx;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.rmi.ssl.SslRMIServerSocketFactory;
+
+public class QpidSslRMIServerSocketFactory extends SslRMIServerSocketFactory
+{
+ private final SSLContext _sslContext;
+
+ /**
+ * SslRMIServerSocketFactory which creates the ServerSocket using the
+ * supplied SSLContext rather than the system default context normally
+ * used by the superclass, allowing us to use a configuration-specified
+ * key store.
+ *
+ * @param sslContext previously created sslContext using the desired key store.
+ * @throws NullPointerException if the provided {@link SSLContext} is null.
+ */
+ public QpidSslRMIServerSocketFactory(SSLContext sslContext) throws NullPointerException
+ {
+ super();
+
+ if(sslContext == null)
+ {
+ throw new NullPointerException("The provided SSLContext must not be null");
+ }
+
+ _sslContext = sslContext;
+
+ //TODO: settings + implementation for SSL client auth, updating equals and hashCode appropriately.
+ }
+
+ @Override
+ public ServerSocket createServerSocket(int port) throws IOException
+ {
+ final SSLSocketFactory factory = _sslContext.getSocketFactory();
+
+ return new ServerSocket(port)
+ {
+ public Socket accept() throws IOException
+ {
+ Socket socket = super.accept();
+
+ SSLSocket sslSocket =
+ (SSLSocket) factory.createSocket(socket,
+ socket.getInetAddress().getHostName(),
+ socket.getPort(),
+ true);
+ sslSocket.setUseClientMode(false);
+
+ return sslSocket;
+ }
+ };
+ }
+
+ /**
+ * One QpidSslRMIServerSocketFactory is equal to
+ * another if their (non-null) SSLContext are equal.
+ */
+ @Override
+ public boolean equals(Object object)
+ {
+ if (!(object instanceof QpidSslRMIServerSocketFactory))
+ {
+ return false;
+ }
+
+ QpidSslRMIServerSocketFactory that = (QpidSslRMIServerSocketFactory) object;
+
+ return _sslContext.equals(that._sslContext);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return _sslContext.hashCode();
+ }
+
+}
diff --git a/qpid/java/broker/etc/md5passwd b/qpid/java/broker/etc/md5passwd
index 59354a21f5..f7185c0e92 100644
--- a/qpid/java/broker/etc/md5passwd
+++ b/qpid/java/broker/etc/md5passwd
@@ -20,3 +20,4 @@ guest:CE4DQ6BIb/BVMN9scFyLtA==
client:CE4DQ6BIb/BVMN9scFyLtA==
server:CE4DQ6BIb/BVMN9scFyLtA==
admin:ISMvKXpXpadDiUoOSoAfww==
+webadmin:rda7WOE5vhAzJNBNgtj1RQ==
diff --git a/qpid/java/broker/etc/virtualhosts.xml b/qpid/java/broker/etc/virtualhosts.xml
deleted file mode 100644
index 0f7cc7866f..0000000000
--- a/qpid/java/broker/etc/virtualhosts.xml
+++ /dev/null
@@ -1,165 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
- -
- - Licensed to the Apache Software Foundation (ASF) under one
- - or more contributor license agreements. See the NOTICE file
- - distributed with this work for additional information
- - regarding copyright ownership. The ASF licenses this file
- - to you under the Apache License, Version 2.0 (the
- - "License"); you may not use this file except in compliance
- - with the License. You may obtain a copy of the License at
- -
- - http://www.apache.org/licenses/LICENSE-2.0
- -
- - Unless required by applicable law or agreed to in writing,
- - software distributed under the License is distributed on an
- - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- - KIND, either express or implied. See the License for the
- - specific language governing permissions and limitations
- - under the License.
- -
- -->
-<virtualhosts>
- <default>test</default>
- <virtualhost>
- <name>localhost</name>
- <localhost>
- <store>
- <class>org.apache.qpid.server.store.MemoryMessageStore</class>
- <!--<class>org.apache.qpid.server.store.derby.DerbyMessageStore</class>
- <environment-path>${QPID_WORK}/derbystore</environment-path>-->
- </store>
-
- <housekeeping>
- <threadCount>2</threadCount>
- <checkPeriod>20000</checkPeriod>
- </housekeeping>
-
- <exchanges>
- <exchange>
- <type>direct</type>
- <name>test.direct</name>
- <durable>true</durable>
- </exchange>
- <exchange>
- <type>topic</type>
- <name>test.topic</name>
- </exchange>
- </exchanges>
- <queues>
- <exchange>amq.direct</exchange>
- <maximumQueueDepth>4235264</maximumQueueDepth>
- <!-- 4Mb -->
- <maximumMessageSize>2117632</maximumMessageSize>
- <!-- 2Mb -->
- <maximumMessageAge>600000</maximumMessageAge>
- <!-- 10 mins -->
- <maximumMessageCount>50</maximumMessageCount>
- <!-- 50 messages -->
-
- <queue>
- <name>queue</name>
- </queue>
- <queue>
- <name>ping</name>
- </queue>
- <queue>
- <name>test-queue</name>
- <test-queue>
- <exchange>test.direct</exchange>
- <durable>true</durable>
- </test-queue>
- </queue>
- <queue>
- <name>test-ping</name>
- <test-ping>
- <exchange>test.direct</exchange>
- </test-ping>
- </queue>
-
- </queues>
- </localhost>
- </virtualhost>
-
-
- <virtualhost>
- <name>development</name>
- <development>
- <store>
- <class>org.apache.qpid.server.store.MemoryMessageStore</class>
- <!--<class>org.apache.qpid.server.store.derby.DerbyMessageStore</class>
- <environment-path>${QPID_WORK}/derbystore</environment-path>-->
- </store>
-
- <queues>
- <minimumAlertRepeatGap>30000</minimumAlertRepeatGap>
- <maximumMessageCount>50</maximumMessageCount>
- <queue>
- <name>queue</name>
- <queue>
- <exchange>amq.direct</exchange>
- <maximumQueueDepth>4235264</maximumQueueDepth>
- <!-- 4Mb -->
- <maximumMessageSize>2117632</maximumMessageSize>
- <!-- 2Mb -->
- <maximumMessageAge>600000</maximumMessageAge>
- <!-- 10 mins -->
- </queue>
- </queue>
- <queue>
- <name>ping</name>
- <ping>
- <exchange>amq.direct</exchange>
- <maximumQueueDepth>4235264</maximumQueueDepth>
- <!-- 4Mb -->
- <maximumMessageSize>2117632</maximumMessageSize>
- <!-- 2Mb -->
- <maximumMessageAge>600000</maximumMessageAge>
- <!-- 10 mins -->
- </ping>
- </queue>
- </queues>
- </development>
- </virtualhost>
- <virtualhost>
- <name>test</name>
- <test>
- <store>
- <class>org.apache.qpid.server.store.MemoryMessageStore</class>
- <!--<class>org.apache.qpid.server.store.derby.DerbyMessageStore</class>
- <environment-path>${QPID_WORK}/derbystore</environment-path>-->
- </store>
-
- <queues>
- <minimumAlertRepeatGap>30000</minimumAlertRepeatGap>
- <maximumMessageCount>50</maximumMessageCount>
- <queue>
- <name>queue</name>
- <queue>
- <exchange>amq.direct</exchange>
- <maximumQueueDepth>4235264</maximumQueueDepth>
- <!-- 4Mb -->
- <maximumMessageSize>2117632</maximumMessageSize>
- <!-- 2Mb -->
- <maximumMessageAge>600000</maximumMessageAge>
- <!-- 10 mins -->
- </queue>
- </queue>
- <queue>
- <name>ping</name>
- <ping>
- <exchange>amq.direct</exchange>
- <maximumQueueDepth>4235264</maximumQueueDepth>
- <!-- 4Mb -->
- <maximumMessageSize>2117632</maximumMessageSize>
- <!-- 2Mb -->
- <maximumMessageAge>600000</maximumMessageAge>
- <!-- 10 mins -->
- </ping>
- </queue>
- </queues>
- </test>
- </virtualhost>
-</virtualhosts>
-
-
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java
index d1be4213ec..dd0fde5f7a 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java
@@ -124,7 +124,7 @@ public class Broker
}
BrokerConfigurationStoreCreator storeCreator = new BrokerConfigurationStoreCreator();
- ConfigurationEntryStore store = storeCreator.createStore(storeLocation, storeType, options.getInitialConfigurationLocation());
+ ConfigurationEntryStore store = storeCreator.createStore(storeLocation, storeType, options.getInitialConfigurationLocation(), options.isOverwriteConfigurationStore());
if (options.isManagementMode())
{
@@ -134,7 +134,7 @@ public class Broker
_applicationRegistry = new ApplicationRegistry(store);
try
{
- _applicationRegistry.initialise();
+ _applicationRegistry.initialise(options);
}
catch(Exception e)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
index 289cfebc29..5c2a8fd090 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
@@ -24,15 +24,19 @@ import java.io.File;
import org.apache.qpid.server.configuration.BrokerProperties;
import org.apache.qpid.server.configuration.ConfigurationEntryStore;
-import org.apache.qpid.server.configuration.store.JsonConfigurationEntryStore;
+import org.apache.qpid.server.configuration.store.MemoryConfigurationEntryStore;
+import org.apache.qpid.server.util.StringUtil;
public class BrokerOptions
{
+ public static final String DEFAULT_INITIAL_CONFIG_NAME = "initial-config.json";
public static final String DEFAULT_STORE_TYPE = "json";
public static final String DEFAULT_CONFIG_NAME_PREFIX = "config";
public static final String DEFAULT_LOG_CONFIG_FILE = "etc/log4j.xml";
public static final String DEFAULT_INITIAL_CONFIG_LOCATION =
- BrokerOptions.class.getClassLoader().getResource("initial-store.json").toExternalForm();
+ BrokerOptions.class.getClassLoader().getResource(DEFAULT_INITIAL_CONFIG_NAME).toExternalForm();
+ public static final String MANAGEMENT_MODE_USER_NAME = "mm_admin";
+ private static final int MANAGEMENT_MODE_PASSWORD_LENGTH = 10;
private String _logConfigFile;
private Integer _logWatchFrequency = 0;
@@ -43,17 +47,35 @@ public class BrokerOptions
private String _initialConfigurationLocation;
private boolean _managementMode;
+ private boolean _managementModeQuiesceVhosts;
private int _managementModeRmiPort;
private int _managementModeConnectorPort;
private int _managementModeHttpPort;
+ private String _managementModePassword;
private String _workingDir;
private boolean _skipLoggingConfiguration;
+ private boolean _overwriteConfigurationStore;
public String getLogConfigFile()
{
return _logConfigFile;
}
+ public String getManagementModePassword()
+ {
+ if(_managementModePassword == null)
+ {
+ _managementModePassword = new StringUtil().randomAlphaNumericString(MANAGEMENT_MODE_PASSWORD_LENGTH);
+ }
+
+ return _managementModePassword;
+ }
+
+ public void setManagementModePassword(String managementModePassword)
+ {
+ _managementModePassword = managementModePassword;
+ }
+
public void setLogConfigFile(final String logConfigFile)
{
_logConfigFile = logConfigFile;
@@ -83,6 +105,16 @@ public class BrokerOptions
_managementMode = managementMode;
}
+ public boolean isManagementModeQuiesceVirtualHosts()
+ {
+ return _managementModeQuiesceVhosts;
+ }
+
+ public void setManagementModeQuiesceVirtualHosts(boolean managementModeQuiesceVhosts)
+ {
+ _managementModeQuiesceVhosts = managementModeQuiesceVhosts;
+ }
+
public int getManagementModeRmiPort()
{
return _managementModeRmiPort;
@@ -169,6 +201,24 @@ public class BrokerOptions
}
/**
+ * Returns whether the existing broker configuration store should be overwritten with the current
+ * initial configuration file (see {@link BrokerOptions#getInitialConfigurationLocation()}).
+ */
+ public boolean isOverwriteConfigurationStore()
+ {
+ return _overwriteConfigurationStore;
+ }
+
+ /**
+ * Sets whether the existing broker configuration store should be overwritten with the current
+ * initial configuration file (see {@link BrokerOptions#getInitialConfigurationLocation()}).
+ */
+ public void setOverwriteConfigurationStore(boolean overwrite)
+ {
+ _overwriteConfigurationStore = overwrite;
+ }
+
+ /**
* Get the broker work directory location.
*
* Defaults to the location set in the "QPID_WORK" system property if it is set, or the 'work' sub-directory
@@ -205,7 +255,7 @@ public class BrokerOptions
/**
* Get the broker initial JSON configuration location.
*
- * Defaults to an internal configuration file within the broker jar, which is loaded with the {@link JsonConfigurationEntryStore}.
+ * Defaults to an internal configuration file within the broker jar.
*
* @return the previously set configuration location, or the default location if none was set.
*/
@@ -221,7 +271,7 @@ public class BrokerOptions
/**
* Set the absolute path or URL to use for the initial JSON configuration, which is loaded with the
- * {@link JsonConfigurationEntryStore} in order to initialise any new {@link ConfigurationEntryStore} for the broker.
+ * {@link MemoryConfigurationEntryStore} in order to initialise any new {@link ConfigurationEntryStore} for the broker.
*
* Passing null clears any previously set value and returns to the default.
*/
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
index dcae3a0eaf..46612613dd 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server;
+import java.io.File;
+
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
@@ -30,6 +32,7 @@ import org.apache.commons.cli.PosixParser;
import org.apache.log4j.Logger;
import org.apache.qpid.common.QpidProperties;
import org.apache.qpid.framing.ProtocolVersion;
+import org.apache.qpid.server.configuration.store.ConfigurationEntryStoreUtil;
/**
* Main entry point for AMQPD.
@@ -37,7 +40,6 @@ import org.apache.qpid.framing.ProtocolVersion;
*/
public class Main
{
-
private static final Option OPTION_HELP = new Option("h", "help", false, "print this message");
private static final Option OPTION_VERSION = new Option("v", "version", false, "print the version information and exit");
@@ -46,10 +48,17 @@ public class Main
.withDescription("use given configuration store location").withLongOpt("store-path").create("sp");
private static final Option OPTION_CONFIGURATION_STORE_TYPE = OptionBuilder.withArgName("type").hasArg()
- .withDescription("use given store type").withLongOpt("store-type").create("st");
+ .withDescription("use given broker configuration store type").withLongOpt("store-type").create("st");
private static final Option OPTION_INITIAL_CONFIGURATION_PATH = OptionBuilder.withArgName("path").hasArg()
- .withDescription("pass the location of initial JSON config to use when creating a new configuration store").withLongOpt("initial-config-path").create("icp");
+ .withDescription("set the location of initial JSON config to use when creating/overwriting a broker configuration store").withLongOpt("initial-config-path").create("icp");
+
+ private static final Option OPTION_OVERWRITE_CONFIGURATION_STORE = OptionBuilder.withDescription("overwrite the broker configuration store with the current initial configuration")
+ .withLongOpt("overwrite-store").create("os");
+
+ private static final Option OPTION_CREATE_INITIAL_CONFIG = OptionBuilder.withArgName("path").hasOptionalArg().withDescription("create a copy of the initial config file, either to an" +
+ " optionally specified file path, or as " + BrokerOptions.DEFAULT_INITIAL_CONFIG_NAME + " in the current directory")
+ .withLongOpt("create-initial-config").create("cic");
private static final Option OPTION_LOG_CONFIG_FILE =
OptionBuilder.withArgName("file").hasArg()
@@ -62,14 +71,18 @@ public class Main
.withDescription("monitor the log file configuration file for changes. Units are seconds. "
+ "Zero means do not check for changes.").withLongOpt("logwatch").create("w");
- private static final Option OPTION_MANAGEMENT_MODE = OptionBuilder.withDescription("start broker in a management mode")
+ private static final Option OPTION_MANAGEMENT_MODE = OptionBuilder.withDescription("start broker in management mode, disabling the AMQP ports")
.withLongOpt("management-mode").create("mm");
- private static final Option OPTION_RMI_PORT = OptionBuilder.withArgName("port").hasArg()
- .withDescription("override jmx rmi port in management mode").withLongOpt("jmxregistryport").create("rmi");
- private static final Option OPTION_CONNECTOR_PORT = OptionBuilder.withArgName("port").hasArg()
- .withDescription("override jmx connector port in management mode").withLongOpt("jmxconnectorport").create("jmxrmi");
- private static final Option OPTION_HTTP_PORT = OptionBuilder.withArgName("port").hasArg()
- .withDescription("override web management port in management mode").withLongOpt("httpport").create("http");
+ private static final Option OPTION_MM_QUIESCE_VHOST = OptionBuilder.withDescription("make virtualhosts stay in the quiesced state during management mode.")
+ .withLongOpt("management-mode-quiesce-virtualhosts").create("mmqv");
+ private static final Option OPTION_MM_RMI_PORT = OptionBuilder.withArgName("port").hasArg()
+ .withDescription("override jmx rmi registry port in management mode").withLongOpt("management-mode-rmi-registry-port").create("mmrmi");
+ private static final Option OPTION_MM_CONNECTOR_PORT = OptionBuilder.withArgName("port").hasArg()
+ .withDescription("override jmx connector port in management mode").withLongOpt("management-mode-jmx-connector-port").create("mmjmx");
+ private static final Option OPTION_MM_HTTP_PORT = OptionBuilder.withArgName("port").hasArg()
+ .withDescription("override http management port in management mode").withLongOpt("management-mode-http-port").create("mmhttp");
+ private static final Option OPTION_MM_PASSWORD = OptionBuilder.withArgName("password").hasArg()
+ .withDescription("Set the password for the management mode user " + BrokerOptions.MANAGEMENT_MODE_USER_NAME).withLongOpt("management-mode-password").create("mmpass");
private static final Options OPTIONS = new Options();
@@ -79,13 +92,17 @@ public class Main
OPTIONS.addOption(OPTION_VERSION);
OPTIONS.addOption(OPTION_CONFIGURATION_STORE_PATH);
OPTIONS.addOption(OPTION_CONFIGURATION_STORE_TYPE);
+ OPTIONS.addOption(OPTION_OVERWRITE_CONFIGURATION_STORE);
+ OPTIONS.addOption(OPTION_CREATE_INITIAL_CONFIG);
OPTIONS.addOption(OPTION_LOG_CONFIG_FILE);
OPTIONS.addOption(OPTION_LOG_WATCH);
OPTIONS.addOption(OPTION_INITIAL_CONFIGURATION_PATH);
OPTIONS.addOption(OPTION_MANAGEMENT_MODE);
- OPTIONS.addOption(OPTION_RMI_PORT);
- OPTIONS.addOption(OPTION_CONNECTOR_PORT);
- OPTIONS.addOption(OPTION_HTTP_PORT);
+ OPTIONS.addOption(OPTION_MM_QUIESCE_VHOST);
+ OPTIONS.addOption(OPTION_MM_RMI_PORT);
+ OPTIONS.addOption(OPTION_MM_CONNECTOR_PORT);
+ OPTIONS.addOption(OPTION_MM_HTTP_PORT);
+ OPTIONS.addOption(OPTION_MM_PASSWORD);
}
protected CommandLine _commandLine;
@@ -140,11 +157,38 @@ public class Main
protected void execute() throws Exception
{
+ BrokerOptions options = new BrokerOptions();
+ String initialConfigLocation = _commandLine.getOptionValue(OPTION_INITIAL_CONFIGURATION_PATH.getOpt());
+ if (initialConfigLocation != null)
+ {
+ options.setInitialConfigurationLocation(initialConfigLocation);
+ }
+
+ //process the remaining options
if (_commandLine.hasOption(OPTION_HELP.getOpt()))
{
final HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("Qpid", OPTIONS, true);
}
+ else if (_commandLine.hasOption(OPTION_CREATE_INITIAL_CONFIG.getOpt()))
+ {
+ File destinationFile = null;
+
+ String destinationOption = _commandLine.getOptionValue(OPTION_CREATE_INITIAL_CONFIG.getOpt());
+ if (destinationOption != null)
+ {
+ destinationFile = new File(destinationOption);
+ }
+ else
+ {
+ destinationFile = new File(System.getProperty("user.dir"), BrokerOptions.DEFAULT_INITIAL_CONFIG_NAME);
+ }
+
+ ConfigurationEntryStoreUtil util = new ConfigurationEntryStoreUtil();
+ util.copyInitialConfigFile(options.getInitialConfigurationLocation(), destinationFile);
+
+ System.out.println("Initial config written to: " + destinationFile.getAbsolutePath());
+ }
else if (_commandLine.hasOption(OPTION_VERSION.getOpt()))
{
final StringBuilder protocol = new StringBuilder("AMQP version(s) [major.minor]: ");
@@ -166,12 +210,12 @@ public class Main
}
else
{
- BrokerOptions options = new BrokerOptions();
String configurationStore = _commandLine.getOptionValue(OPTION_CONFIGURATION_STORE_PATH.getOpt());
if (configurationStore != null)
{
options.setConfigurationStoreLocation(configurationStore);
}
+
String configurationStoreType = _commandLine.getOptionValue(OPTION_CONFIGURATION_STORE_TYPE.getOpt());
if (configurationStoreType != null)
{
@@ -190,27 +234,24 @@ public class Main
options.setLogConfigFile(logConfig);
}
- String initialConfigLocation = _commandLine.getOptionValue(OPTION_INITIAL_CONFIGURATION_PATH.getOpt());
- if (initialConfigLocation != null)
- {
- options.setInitialConfigurationLocation(initialConfigLocation);
- }
+ boolean overwriteConfigurationStore = _commandLine.hasOption(OPTION_OVERWRITE_CONFIGURATION_STORE.getOpt());
+ options.setOverwriteConfigurationStore(overwriteConfigurationStore);
- boolean managmentMode = _commandLine.hasOption(OPTION_MANAGEMENT_MODE.getOpt());
- if (managmentMode)
+ boolean managementMode = _commandLine.hasOption(OPTION_MANAGEMENT_MODE.getOpt());
+ if (managementMode)
{
options.setManagementMode(true);
- String rmiPort = _commandLine.getOptionValue(OPTION_RMI_PORT.getOpt());
+ String rmiPort = _commandLine.getOptionValue(OPTION_MM_RMI_PORT.getOpt());
if (rmiPort != null)
{
options.setManagementModeRmiPort(Integer.parseInt(rmiPort));
}
- String connectorPort = _commandLine.getOptionValue(OPTION_CONNECTOR_PORT.getOpt());
+ String connectorPort = _commandLine.getOptionValue(OPTION_MM_CONNECTOR_PORT.getOpt());
if (connectorPort != null)
{
options.setManagementModeConnectorPort(Integer.parseInt(connectorPort));
}
- String httpPort = _commandLine.getOptionValue(OPTION_HTTP_PORT.getOpt());
+ String httpPort = _commandLine.getOptionValue(OPTION_MM_HTTP_PORT.getOpt());
if (httpPort != null)
{
options.setManagementModeHttpPort(Integer.parseInt(httpPort));
@@ -218,6 +259,12 @@ public class Main
boolean quiesceVhosts = _commandLine.hasOption(OPTION_MM_QUIESCE_VHOST.getOpt());
options.setManagementModeQuiesceVirtualHosts(quiesceVhosts);
+
+ String password = _commandLine.getOptionValue(OPTION_MM_PASSWORD.getOpt());
+ if (password != null)
+ {
+ options.setManagementModePassword(password);
+ }
}
setExceptionHandler();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreator.java
index 2bb63a803b..8ce74ff334 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreator.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreator.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.configuration;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -58,9 +60,10 @@ public class BrokerConfigurationStoreCreator
* @param storeLocation store location
* @param storeType store type
* @param initialConfigLocation initial store location
+ * @param overwrite whether to overwrite an existing configuration store with the initial configuration
* @throws IllegalConfigurationException if store type is unknown
*/
- public ConfigurationEntryStore createStore(String storeLocation, String storeType, String initialConfigLocation)
+ public ConfigurationEntryStore createStore(String storeLocation, String storeType, String initialConfigLocation, boolean overwrite)
{
ConfigurationEntryStore initialStore = new MemoryConfigurationEntryStore(initialConfigLocation, null);
ConfigurationStoreFactory factory = _factories.get(storeType.toLowerCase());
@@ -68,7 +71,11 @@ public class BrokerConfigurationStoreCreator
{
throw new IllegalConfigurationException("Unknown store type: " + storeType);
}
- return factory.createStore(storeLocation, initialStore);
+ return factory.createStore(storeLocation, initialStore, overwrite);
}
+ public Collection<String> getStoreTypes()
+ {
+ return Collections.unmodifiableCollection(_factories.keySet());
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AccessControlProviderRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AccessControlProviderRecoverer.java
new file mode 100644
index 0000000000..df80b9fe5f
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AccessControlProviderRecoverer.java
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.configuration.startup;
+
+import java.util.Map;
+
+import org.apache.qpid.server.configuration.ConfigurationEntry;
+import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer;
+import org.apache.qpid.server.configuration.RecovererProvider;
+import org.apache.qpid.server.model.AccessControlProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.adapter.AccessControlProviderFactory;
+
+public class AccessControlProviderRecoverer implements ConfiguredObjectRecoverer<AccessControlProvider>
+{
+ private final AccessControlProviderFactory _accessControlProviderFactory;
+
+ public AccessControlProviderRecoverer(AccessControlProviderFactory authenticationProviderFactory)
+ {
+ _accessControlProviderFactory = authenticationProviderFactory;
+ }
+
+ @Override
+ public AccessControlProvider create(RecovererProvider recovererProvider, ConfigurationEntry configurationEntry, ConfiguredObject... parents)
+ {
+ Broker broker = RecovererHelper.verifyOnlyBrokerIsParent(parents);
+ Map<String, Object> attributes = configurationEntry.getAttributes();
+ AccessControlProvider authenticationProvider = _accessControlProviderFactory.recover(
+ configurationEntry.getId(),
+ broker,
+ attributes);
+
+ return authenticationProvider;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java
index 3290c827c9..81aff002d1 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java
@@ -51,5 +51,4 @@ public class AuthenticationProviderRecoverer implements ConfiguredObjectRecovere
return authenticationProvider;
}
-
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java
index 0d7be75a0b..35c96bc993 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java
@@ -1,23 +1,50 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
package org.apache.qpid.server.configuration.startup;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.configuration.ConfigurationEntry;
import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.RecovererProvider;
+import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.logging.LogRecorder;
import org.apache.qpid.server.logging.RootMessageLogger;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfiguredObject;
-import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.KeyStore;
+import org.apache.qpid.server.model.TrustStore;
+import org.apache.qpid.server.model.adapter.AccessControlProviderFactory;
import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory;
import org.apache.qpid.server.model.adapter.BrokerAdapter;
+import org.apache.qpid.server.model.adapter.GroupProviderFactory;
import org.apache.qpid.server.model.adapter.PortFactory;
-import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener;
-import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.stats.StatisticsGatherer;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
@@ -28,20 +55,26 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker>
private final LogRecorder _logRecorder;
private final RootMessageLogger _rootMessageLogger;
private final AuthenticationProviderFactory _authenticationProviderFactory;
+ private final AccessControlProviderFactory _accessControlProviderFactory;
private final PortFactory _portFactory;
private final TaskExecutor _taskExecutor;
+ private final BrokerOptions _brokerOptions;
+ private final GroupProviderFactory _groupProviderFactory;
- public BrokerRecoverer(AuthenticationProviderFactory authenticationProviderFactory, PortFactory portFactory,
- StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder,
- RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor)
+ public BrokerRecoverer(AuthenticationProviderFactory authenticationProviderFactory, GroupProviderFactory groupProviderFactory,
+ AccessControlProviderFactory accessControlProviderFactory, PortFactory portFactory, StatisticsGatherer statisticsGatherer,
+ VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions)
{
+ _groupProviderFactory = groupProviderFactory;
_portFactory = portFactory;
_authenticationProviderFactory = authenticationProviderFactory;
+ _accessControlProviderFactory = accessControlProviderFactory;
_statisticsGatherer = statisticsGatherer;
_virtualHostRegistry = virtualHostRegistry;
_logRecorder = logRecorder;
_rootMessageLogger = rootMessageLogger;
_taskExecutor = taskExecutor;
+ _brokerOptions = brokerOptions;
}
@Override
@@ -49,85 +82,62 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker>
{
StoreConfigurationChangeListener storeChangeListener = new StoreConfigurationChangeListener(entry.getStore());
BrokerAdapter broker = new BrokerAdapter(entry.getId(), entry.getAttributes(), _statisticsGatherer, _virtualHostRegistry,
- _logRecorder, _rootMessageLogger, _authenticationProviderFactory, _portFactory, _taskExecutor, entry.getStore());
+ _logRecorder, _rootMessageLogger, _authenticationProviderFactory, _groupProviderFactory, _accessControlProviderFactory,
+ _portFactory, _taskExecutor, entry.getStore(), _brokerOptions);
broker.addChangeListener(storeChangeListener);
- Map<String, Collection<ConfigurationEntry>> childEntries = entry.getChildren();
- for (String type : childEntries.keySet())
+
+ //Recover the SSL keystores / truststores first, then others that depend on them
+ Map<String, Collection<ConfigurationEntry>> childEntries = new HashMap<String, Collection<ConfigurationEntry>>(entry.getChildren());
+ Map<String, Collection<ConfigurationEntry>> priorityChildEntries = new HashMap<String, Collection<ConfigurationEntry>>(childEntries);
+ List<String> types = new ArrayList<String>(childEntries.keySet());
+
+ for(String type : types)
{
- ConfiguredObjectRecoverer<?> recoverer = recovererProvider.getRecoverer(type);
- if (recoverer == null)
+ if(KeyStore.class.getSimpleName().equals(type) || TrustStore.class.getSimpleName().equals(type)
+ || AuthenticationProvider.class.getSimpleName().equals(type))
{
- throw new IllegalConfigurationException("Cannot recover entry for the type '" + type + "' from broker");
+ childEntries.remove(type);
}
- Collection<ConfigurationEntry> entries = childEntries.get(type);
- for (ConfigurationEntry childEntry : entries)
+ else
{
- ConfiguredObject object = recoverer.create(recovererProvider, childEntry, broker);
- if (object == null)
- {
- throw new IllegalConfigurationException("Cannot create configured object for the entry " + childEntry);
- }
- broker.recoverChild(object);
- object.addChangeListener(storeChangeListener);
+ priorityChildEntries.remove(type);
}
}
- wireUpConfiguredObjects(broker, entry.getAttributes());
- return broker;
- }
-
- private void wireUpConfiguredObjects(BrokerAdapter broker, Map<String, Object> brokerAttributes)
- {
- AuthenticationProvider defaultAuthenticationProvider = null;
- Collection<AuthenticationProvider> authenticationProviders = broker.getAuthenticationProviders();
- int numberOfAuthenticationProviders = authenticationProviders.size();
- if (numberOfAuthenticationProviders == 0)
+ for (String type : priorityChildEntries.keySet())
{
- throw new IllegalConfigurationException("No authentication provider was configured");
+ recoverType(recovererProvider, storeChangeListener, broker, priorityChildEntries, type);
}
- else if (numberOfAuthenticationProviders == 1)
+ for (String type : childEntries.keySet())
{
- defaultAuthenticationProvider = authenticationProviders.iterator().next();
+ recoverType(recovererProvider, storeChangeListener, broker, childEntries, type);
}
- else
- {
- String name = (String) brokerAttributes.get(Broker.DEFAULT_AUTHENTICATION_PROVIDER);
- if (name == null)
- {
- throw new IllegalConfigurationException("Multiple authentication providers defined, but no default was configured.");
- }
- defaultAuthenticationProvider = getAuthenticationProviderByName(broker, name);
- }
- broker.setDefaultAuthenticationProvider(defaultAuthenticationProvider);
-
- Collection<Port> ports = broker.getPorts();
- for (Port port : ports)
- {
- String authenticationProviderName = (String) port.getAttribute(Port.AUTHENTICATION_PROVIDER);
- AuthenticationProvider provider = null;
- if (authenticationProviderName != null)
- {
- provider = getAuthenticationProviderByName(broker, authenticationProviderName);
- }
- else
- {
- provider = defaultAuthenticationProvider;
- }
- port.setAuthenticationProvider(provider);
- }
+ return broker;
}
- private AuthenticationProvider getAuthenticationProviderByName(BrokerAdapter broker, String authenticationProviderName)
+ private void recoverType(RecovererProvider recovererProvider,
+ StoreConfigurationChangeListener storeChangeListener,
+ BrokerAdapter broker,
+ Map<String, Collection<ConfigurationEntry>> childEntries,
+ String type)
{
- AuthenticationProvider provider = broker.findAuthenticationProviderByName(authenticationProviderName);
- if (provider == null)
+ ConfiguredObjectRecoverer<?> recoverer = recovererProvider.getRecoverer(type);
+ if (recoverer == null)
{
- throw new IllegalConfigurationException("Cannot find the authentication provider with name: "
- + authenticationProviderName);
+ throw new IllegalConfigurationException("Cannot recover entry for the type '" + type + "' from broker");
+ }
+ Collection<ConfigurationEntry> entries = childEntries.get(type);
+ for (ConfigurationEntry childEntry : entries)
+ {
+ ConfiguredObject object = recoverer.create(recovererProvider, childEntry, broker);
+ if (object == null)
+ {
+ throw new IllegalConfigurationException("Cannot create configured object for the entry " + childEntry);
+ }
+ broker.recoverChild(object);
+ object.addChangeListener(storeChangeListener);
}
- return provider;
}
-
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java
index 15cb229d8a..2de454c34f 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java
@@ -20,10 +20,12 @@
*/
package org.apache.qpid.server.configuration.startup;
+import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer;
import org.apache.qpid.server.configuration.RecovererProvider;
import org.apache.qpid.server.logging.LogRecorder;
import org.apache.qpid.server.logging.RootMessageLogger;
+import org.apache.qpid.server.model.AccessControlProvider;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.GroupProvider;
@@ -32,9 +34,12 @@ import org.apache.qpid.server.model.Plugin;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.adapter.AccessControlProviderFactory;
import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory;
+import org.apache.qpid.server.model.adapter.GroupProviderFactory;
import org.apache.qpid.server.model.adapter.PortFactory;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.plugin.AccessControlFactory;
import org.apache.qpid.server.plugin.AuthenticationManagerFactory;
import org.apache.qpid.server.plugin.GroupManagerFactory;
import org.apache.qpid.server.plugin.PluginFactory;
@@ -50,23 +55,27 @@ public class DefaultRecovererProvider implements RecovererProvider
private final LogRecorder _logRecorder;
private final RootMessageLogger _rootMessageLogger;
private final AuthenticationProviderFactory _authenticationProviderFactory;
+ private final AccessControlProviderFactory _accessControlProviderFactory;
private final PortFactory _portFactory;
- private final QpidServiceLoader<GroupManagerFactory> _groupManagerServiceLoader;
+ private final GroupProviderFactory _groupProviderFactory;
private final QpidServiceLoader<PluginFactory> _pluginFactoryServiceLoader;
private final TaskExecutor _taskExecutor;
+ private final BrokerOptions _brokerOptions;
public DefaultRecovererProvider(StatisticsGatherer brokerStatisticsGatherer, VirtualHostRegistry virtualHostRegistry,
- LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor)
+ LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions)
{
_authenticationProviderFactory = new AuthenticationProviderFactory(new QpidServiceLoader<AuthenticationManagerFactory>());
+ _accessControlProviderFactory = new AccessControlProviderFactory(new QpidServiceLoader<AccessControlFactory>());
+ _groupProviderFactory = new GroupProviderFactory(new QpidServiceLoader<GroupManagerFactory>());
_portFactory = new PortFactory();
_brokerStatisticsGatherer = brokerStatisticsGatherer;
_virtualHostRegistry = virtualHostRegistry;
_logRecorder = logRecorder;
_rootMessageLogger = rootMessageLogger;
- _groupManagerServiceLoader = new QpidServiceLoader<GroupManagerFactory>();
_pluginFactoryServiceLoader = new QpidServiceLoader<PluginFactory>();
_taskExecutor = taskExecutor;
+ _brokerOptions = brokerOptions;
}
@Override
@@ -74,13 +83,17 @@ public class DefaultRecovererProvider implements RecovererProvider
{
if (Broker.class.getSimpleName().equals(type))
{
- return new BrokerRecoverer(_authenticationProviderFactory, _portFactory, _brokerStatisticsGatherer, _virtualHostRegistry,
- _logRecorder, _rootMessageLogger, _taskExecutor);
+ return new BrokerRecoverer(_authenticationProviderFactory, _groupProviderFactory, _accessControlProviderFactory, _portFactory, _brokerStatisticsGatherer,
+ _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor, _brokerOptions);
}
else if(VirtualHost.class.getSimpleName().equals(type))
{
return new VirtualHostRecoverer(_brokerStatisticsGatherer);
}
+ else if(AccessControlProvider.class.getSimpleName().equals(type))
+ {
+ return new AccessControlProviderRecoverer(_accessControlProviderFactory);
+ }
else if(AuthenticationProvider.class.getSimpleName().equals(type))
{
return new AuthenticationProviderRecoverer(_authenticationProviderFactory);
@@ -91,7 +104,7 @@ public class DefaultRecovererProvider implements RecovererProvider
}
else if(GroupProvider.class.getSimpleName().equals(type))
{
- return new GroupProviderRecoverer(_groupManagerServiceLoader);
+ return new GroupProviderRecoverer(_groupProviderFactory);
}
else if(KeyStore.class.getSimpleName().equals(type))
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java
index 275a0c736c..00f23b3c1c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java
@@ -24,24 +24,20 @@ import java.util.Map;
import org.apache.qpid.server.configuration.ConfigurationEntry;
import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer;
-import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.RecovererProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.GroupProvider;
-import org.apache.qpid.server.model.adapter.GroupProviderAdapter;
-import org.apache.qpid.server.plugin.GroupManagerFactory;
-import org.apache.qpid.server.plugin.QpidServiceLoader;
-import org.apache.qpid.server.security.group.GroupManager;
+import org.apache.qpid.server.model.adapter.GroupProviderFactory;
public class GroupProviderRecoverer implements ConfiguredObjectRecoverer<GroupProvider>
{
- private QpidServiceLoader<GroupManagerFactory> _groupManagerServiceLoader;
+ private GroupProviderFactory _groupProviderFactory;
- public GroupProviderRecoverer(QpidServiceLoader<GroupManagerFactory> groupManagerServiceLoader)
+ public GroupProviderRecoverer(GroupProviderFactory groupProviderFactory)
{
super();
- _groupManagerServiceLoader = groupManagerServiceLoader;
+ _groupProviderFactory = groupProviderFactory;
}
@Override
@@ -49,26 +45,9 @@ public class GroupProviderRecoverer implements ConfiguredObjectRecoverer<GroupPr
{
Broker broker = RecovererHelper.verifyOnlyBrokerIsParent(parents);
Map<String, Object> attributes = configurationEntry.getAttributes();
- GroupManager groupManager = createGroupManager(attributes);
- if (groupManager == null)
- {
- throw new IllegalConfigurationException("Cannot create GroupManager from attributes : " + attributes);
- }
- GroupProviderAdapter groupProviderAdapter = new GroupProviderAdapter(configurationEntry.getId(), groupManager, broker);
- return groupProviderAdapter;
- }
- private GroupManager createGroupManager(Map<String, Object> attributes)
- {
- for(GroupManagerFactory factory : _groupManagerServiceLoader.instancesOf(GroupManagerFactory.class))
- {
- GroupManager groupManager = factory.createInstance(attributes);
- if (groupManager != null)
- {
- return groupManager;
- }
- }
- return null;
- }
+ GroupProvider groupProvider = _groupProviderFactory.recover(configurationEntry.getId(), broker, attributes);
+ return groupProvider;
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreUtil.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreUtil.java
new file mode 100644
index 0000000000..6d895892b3
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreUtil.java
@@ -0,0 +1,91 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.configuration.store;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.util.FileUtils;
+
+public class ConfigurationEntryStoreUtil
+{
+ public void copyInitialConfigFile(String initialConfigLocation, File destinationFile)
+ {
+ URL initialStoreURL = toURL(initialConfigLocation);
+ InputStream in = null;
+ try
+ {
+ in = initialStoreURL.openStream();
+ FileUtils.copy(in, destinationFile);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalConfigurationException("Cannot create file " + destinationFile + " by copying initial config from " + initialConfigLocation , e);
+ }
+ finally
+ {
+ if (in != null)
+ {
+ try
+ {
+ in.close();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalConfigurationException("Cannot close initial config input stream: " + initialConfigLocation , e);
+ }
+ }
+ }
+ }
+
+ public URL toURL(String location)
+ {
+ URL url = null;
+ try
+ {
+ url = new URL(location);
+ }
+ catch (MalformedURLException e)
+ {
+ File locationFile = new File(location);
+ url = fileToURL(locationFile);
+ }
+ return url;
+ }
+
+ protected URL fileToURL(File storeFile)
+ {
+ URL storeURL = null;
+ try
+ {
+ storeURL = storeFile.toURI().toURL();
+ }
+ catch (MalformedURLException e)
+ {
+ throw new IllegalConfigurationException("Cannot create URL for file " + storeFile, e);
+ }
+ return storeURL;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStore.java
index 7a1db3d46d..5f7e68b62a 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStore.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStore.java
@@ -1,9 +1,6 @@
package org.apache.qpid.server.configuration.store;
import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@@ -11,7 +8,6 @@ import java.util.UUID;
import org.apache.qpid.server.configuration.ConfigurationEntry;
import org.apache.qpid.server.configuration.ConfigurationEntryStore;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
-import org.apache.qpid.util.FileUtils;
public class JsonConfigurationEntryStore extends MemoryConfigurationEntryStore
{
@@ -21,13 +17,32 @@ public class JsonConfigurationEntryStore extends MemoryConfigurationEntryStore
public JsonConfigurationEntryStore(String storeLocation, ConfigurationEntryStore initialStore)
{
+ this(storeLocation, initialStore, false);
+ }
+
+ public JsonConfigurationEntryStore(String storeLocation, ConfigurationEntryStore initialStore, boolean overwrite)
+ {
super();
_storeFile = new File(storeLocation);
+
+ if(_storeFile.isDirectory())
+ {
+ throw new IllegalConfigurationException("A directory exists at the location for the broker configuration store file: " + storeLocation);
+ }
+
+ if(overwrite && _storeFile.exists())
+ {
+ if(!_storeFile.delete())
+ {
+ throw new RuntimeException("Unable to overwrite existing configuration store file as requested: " + storeLocation);
+ }
+ }
+
if ((!_storeFile.exists() || _storeFile.length() == 0))
{
initialiseStore(_storeFile, initialStore);
}
- load(fileToURL(_storeFile));
+ load(getConfigurationEntryStoreUtil().fileToURL(_storeFile));
if(isGeneratedObjectIdDuringLoad())
{
saveAsTree(_storeFile);
@@ -72,7 +87,6 @@ public class JsonConfigurationEntryStore extends MemoryConfigurationEntryStore
return "JsonConfigurationEntryStore [_storeFile=" + _storeFile + ", _rootId=" + getRootEntry().getId() + "]";
}
-
private void initialiseStore(File storeFile, ConfigurationEntryStore initialStore)
{
createFileIfNotExist(storeFile);
@@ -84,7 +98,7 @@ public class JsonConfigurationEntryStore extends MemoryConfigurationEntryStore
{
if (initialStore instanceof MemoryConfigurationEntryStore && initialStore.getStoreLocation() != null)
{
- copyInitialStoreFile(initialStore.getStoreLocation(), storeFile);
+ getConfigurationEntryStoreUtil().copyInitialConfigFile(initialStore.getStoreLocation(), storeFile);
}
else
{
@@ -96,33 +110,4 @@ public class JsonConfigurationEntryStore extends MemoryConfigurationEntryStore
}
}
- private void copyInitialStoreFile(String initialStoreLocation, File storeFile)
- {
- URL initialStoreURL = toURL(initialStoreLocation);
- InputStream in = null;
- try
- {
- in = initialStoreURL.openStream();
- FileUtils.copy(in, storeFile);
- }
- catch (IOException e)
- {
- throw new IllegalConfigurationException("Cannot create store file " + storeFile + " by copying initial store from " + initialStoreLocation , e);
- }
- finally
- {
- if (in != null)
- {
- try
- {
- in.close();
- }
- catch (IOException e)
- {
- throw new IllegalConfigurationException("Cannot close initial store input stream: " + initialStoreLocation , e);
- }
- }
- }
- }
-
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java
index 385d2f7327..abf1537ef7 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java
@@ -12,6 +12,7 @@ import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.configuration.ConfigurationEntry;
import org.apache.qpid.server.configuration.ConfigurationEntryStore;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.model.AccessControlProvider;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Protocol;
import org.apache.qpid.server.model.State;
@@ -25,7 +26,9 @@ public class ManagementModeStoreHandler implements ConfigurationEntryStore
private static final String MANAGEMENT_MODE_PORT_PREFIX = "MANAGEMENT-MODE-PORT-";
private static final String PORT_TYPE = Port.class.getSimpleName();
private static final String VIRTUAL_HOST_TYPE = VirtualHost.class.getSimpleName();
+ private static final String ACCESS_CONTROL_PROVIDER_TYPE = AccessControlProvider.class.getSimpleName();
private static final String ATTRIBUTE_STATE = VirtualHost.STATE;
+ private static final Object MANAGEMENT_MODE_AUTH_PROVIDER = "mm-auth";
private final ConfigurationEntryStore _store;
private final Map<UUID, ConfigurationEntry> _cliEntries;
@@ -208,6 +211,10 @@ public class ManagementModeStoreHandler implements ConfigurationEntryStore
attributes.put(Port.PORT, port);
attributes.put(Port.PROTOCOLS, Collections.singleton(protocol));
attributes.put(Port.NAME, MANAGEMENT_MODE_PORT_PREFIX + protocol.name());
+ if (protocol != Protocol.RMI)
+ {
+ attributes.put(Port.AUTHENTICATION_PROVIDER, MANAGEMENT_MODE_AUTH_PROVIDER);
+ }
ConfigurationEntry portEntry = new ConfigurationEntry(UUID.randomUUID(), PORT_TYPE, attributes,
Collections.<UUID> emptySet(), this);
if (LOGGER.isDebugEnabled())
@@ -244,7 +251,11 @@ public class ManagementModeStoreHandler implements ConfigurationEntryStore
String entryType = entry.getType();
Map<String, Object> attributes = entry.getAttributes();
boolean quiesce = false;
- if (VIRTUAL_HOST_TYPE.equals(entryType))
+ if (VIRTUAL_HOST_TYPE.equals(entryType) && options.isManagementModeQuiesceVirtualHosts())
+ {
+ quiesce = true;
+ }
+ else if (ACCESS_CONTROL_PROVIDER_TYPE.equals(entryType))
{
quiesce = true;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/MemoryConfigurationEntryStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/MemoryConfigurationEntryStore.java
index 6931e22d63..6ee26c0726 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/MemoryConfigurationEntryStore.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/MemoryConfigurationEntryStore.java
@@ -26,7 +26,6 @@ import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
@@ -71,6 +70,7 @@ public class MemoryConfigurationEntryStore implements ConfigurationEntryStore
private final ObjectMapper _objectMapper;
private final Map<UUID, ConfigurationEntry> _entries;
private final Map<String, Class<? extends ConfiguredObject>> _relationshipClasses;
+ private final ConfigurationEntryStoreUtil _util = new ConfigurationEntryStoreUtil();
private String _storeLocation;
private UUID _rootId;
@@ -119,7 +119,7 @@ public class MemoryConfigurationEntryStore implements ConfigurationEntryStore
else
{
_storeLocation = initialStoreLocation;
- load(toURL(_storeLocation));
+ load(_util.toURL(_storeLocation));
}
}
@@ -289,21 +289,6 @@ public class MemoryConfigurationEntryStore implements ConfigurationEntryStore
}
}
- protected URL toURL(String location)
- {
- URL url = null;
- try
- {
- url = new URL(location);
- }
- catch (MalformedURLException e)
- {
- File locationFile = new File(location);
- url = fileToURL(locationFile);
- }
- return url;
- }
-
protected void createFileIfNotExist(File file)
{
File parent = file.getParentFile();
@@ -349,20 +334,6 @@ public class MemoryConfigurationEntryStore implements ConfigurationEntryStore
}
}
- protected URL fileToURL(File storeFile)
- {
- URL storeURL = null;
- try
- {
- storeURL = storeFile.toURI().toURL();
- }
- catch (MalformedURLException e)
- {
- throw new IllegalConfigurationException("Cannot create URL for file " + storeFile, e);
- }
- return storeURL;
- }
-
private void loadFromJson(String json)
{
ByteArrayInputStream bais = null;
@@ -586,14 +557,7 @@ public class MemoryConfigurationEntryStore implements ConfigurationEntryStore
UUID id = null;
if (idAsString == null)
{
- if (expectedConfiguredObjectClass == Broker.class)
- {
- id = UUIDGenerator.generateRandomUUID();
- }
- else
- {
- id = UUIDGenerator.generateBrokerChildUUID(type, name);
- }
+ id = UUIDGenerator.generateRandomUUID();
_generatedObjectIdDuringLoad = true;
}
@@ -691,4 +655,9 @@ public class MemoryConfigurationEntryStore implements ConfigurationEntryStore
{
return _generatedObjectIdDuringLoad;
}
+
+ protected ConfigurationEntryStoreUtil getConfigurationEntryStoreUtil()
+ {
+ return _util;
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/JsonConfigurationStoreFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/JsonConfigurationStoreFactory.java
index 1a0b514b4c..7c7d3e2071 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/JsonConfigurationStoreFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/JsonConfigurationStoreFactory.java
@@ -27,9 +27,9 @@ import org.apache.qpid.server.plugin.ConfigurationStoreFactory;
public class JsonConfigurationStoreFactory implements ConfigurationStoreFactory
{
@Override
- public ConfigurationEntryStore createStore(String storeLocation, ConfigurationEntryStore initialStore)
+ public ConfigurationEntryStore createStore(String storeLocation, ConfigurationEntryStore initialStore, boolean overwrite)
{
- return new JsonConfigurationEntryStore(storeLocation, initialStore);
+ return new JsonConfigurationEntryStore(storeLocation, initialStore, overwrite);
}
@Override
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/MemoryConfigurationStoreFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/MemoryConfigurationStoreFactory.java
index fcd6c73170..ed952ff475 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/MemoryConfigurationStoreFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/MemoryConfigurationStoreFactory.java
@@ -27,7 +27,7 @@ import org.apache.qpid.server.plugin.ConfigurationStoreFactory;
public class MemoryConfigurationStoreFactory implements ConfigurationStoreFactory
{
@Override
- public ConfigurationEntryStore createStore(String storeLocation, ConfigurationEntryStore initialStore)
+ public ConfigurationEntryStore createStore(String storeLocation, ConfigurationEntryStore initialStore, boolean overwrite)
{
return new MemoryConfigurationEntryStore(null, initialStore);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index 246e056f0b..7a3367d215 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.exchange;
+import java.util.ArrayList;
+import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.binding.Binding;
@@ -47,6 +49,7 @@ import java.util.concurrent.atomic.AtomicLong;
public abstract class AbstractExchange implements Exchange
{
+ private static final Logger _logger = Logger.getLogger(AbstractExchange.class);
private AMQShortString _name;
private final AtomicBoolean _closed = new AtomicBoolean();
@@ -295,7 +298,29 @@ public abstract class AbstractExchange implements Exchange
{
_receivedMessageCount.incrementAndGet();
_receivedMessageSize.addAndGet(message.getSize());
- final List<? extends BaseQueue> queues = doRoute(message);
+ List<? extends BaseQueue> queues = doRoute(message);
+ List<? extends BaseQueue> allQueues = queues;
+
+ boolean deletedQueues = false;
+
+ for(BaseQueue q : allQueues)
+ {
+ if(q.isDeleted())
+ {
+ if(!deletedQueues)
+ {
+ deletedQueues = true;
+ queues = new ArrayList<BaseQueue>(allQueues);
+ }
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Exchange: " + getName() + " - attempt to enqueue message onto deleted queue " + String.valueOf(q.getNameShortString()));
+ }
+ queues.remove(q);
+ }
+ }
+
+
if(!queues.isEmpty())
{
_routedMessageCount.incrementAndGet();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java
index 47cacdc176..3d0d9a0f31 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java
@@ -14,14 +14,17 @@
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
- * under the License.
+ * under the License.
+ *
*
- *
*/
package org.apache.qpid.server.filter;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.log4j.Logger;
-
import org.apache.qpid.filter.BooleanExpression;
import org.apache.qpid.filter.FilterableMessage;
import org.apache.qpid.filter.SelectorParsingException;
@@ -119,6 +122,34 @@ public class JMSSelectorFilter implements MessageFilter
@Override
public String toString()
{
- return "JMSSelector("+_selector+")";
+ return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
+ .append("selector", _selector)
+ .toString();
}
+
+ @Override
+ public int hashCode()
+ {
+ return new HashCodeBuilder().append(_selector).toHashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (obj == this)
+ {
+ return true;
+ }
+ if (obj.getClass() != getClass())
+ {
+ return false;
+ }
+ JMSSelectorFilter rhs = (JMSSelectorFilter) obj;
+ return new EqualsBuilder().append(_selector, rhs._selector).isEquals();
+ }
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties
index 1aa7815c39..76c1fa1b5b 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties
@@ -45,4 +45,6 @@ STATS_MSGS = BRK-1009 : {0,choice,0#delivered|1#received} : {1,number,#.###} msg
PLATFORM = BRK-1010 : Platform : JVM : {0} version: {1} OS : {2} version: {3} arch: {4}
# 0 Maximum Memory
-MAX_MEMORY = BRK-1011 : Maximum Memory : {0,number} bytes \ No newline at end of file
+MAX_MEMORY = BRK-1011 : Maximum Memory : {0,number} bytes
+
+MANAGEMENT_MODE = BRK-1012 : Management Mode : User Details : {0} / {1} \ No newline at end of file
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java
new file mode 100644
index 0000000000..d96bef0463
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AccessControlProvider.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.model;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.qpid.server.security.AccessControl;
+
+public interface AccessControlProvider extends ConfiguredObject
+{
+ public static final String ID = "id";
+ public static final String DESCRIPTION = "description";
+ public static final String NAME = "name";
+ public static final String STATE = "state";
+ public static final String DURABLE = "durable";
+ public static final String LIFETIME_POLICY = "lifetimePolicy";
+ public static final String TIME_TO_LIVE = "timeToLive";
+ public static final String CREATED = "created";
+ public static final String UPDATED = "updated";
+ public static final String TYPE = "type";
+
+ public static final Collection<String> AVAILABLE_ATTRIBUTES =
+ Collections.unmodifiableList(
+ Arrays.asList(ID,
+ NAME,
+ DESCRIPTION,
+ STATE,
+ DURABLE,
+ LIFETIME_POLICY,
+ TIME_TO_LIVE,
+ CREATED,
+ UPDATED,
+ TYPE));
+
+ //retrieve the underlying AccessControl object
+ AccessControl getAccessControl();
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java
index ad0e68cee6..f666eb29f1 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java
@@ -21,11 +21,9 @@
package org.apache.qpid.server.model;
import java.net.SocketAddress;
-import java.security.AccessControlException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.Map;
import org.apache.qpid.server.logging.LogRecorder;
import org.apache.qpid.server.logging.RootMessageLogger;
@@ -43,7 +41,8 @@ public interface Broker extends ConfiguredObject
String PLATFORM = "platform";
String PROCESS_PID = "processPid";
String PRODUCT_VERSION = "productVersion";
- String SUPPORTED_STORE_TYPES = "supportedStoreTypes";
+ String SUPPORTED_BROKER_STORE_TYPES = "supportedBrokerStoreTypes";
+ String SUPPORTED_VIRTUALHOST_STORE_TYPES = "supportedVirtualHostStoreTypes";
String SUPPORTED_AUTHENTICATION_PROVIDERS = "supportedAuthenticationProviders";
String CREATED = "created";
String DURABLE = "durable";
@@ -53,7 +52,6 @@ public interface Broker extends ConfiguredObject
String STATE = "state";
String TIME_TO_LIVE = "timeToLive";
String UPDATED = "updated";
- String DEFAULT_AUTHENTICATION_PROVIDER = "defaultAuthenticationProvider";
String DEFAULT_VIRTUAL_HOST = "defaultVirtualHost";
String STATISTICS_REPORTING_PERIOD = "statisticsReportingPeriod";
String STATISTICS_REPORTING_RESET_ENABLED = "statisticsReportingResetEnabled";
@@ -81,30 +79,6 @@ public interface Broker extends ConfiguredObject
String VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE = "virtualhost.storeTransactionOpenTimeoutClose";
String VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_WARN = "virtualhost.storeTransactionOpenTimeoutWarn";
- /*
- * A temporary attribute to pass the path to ACL file.
- * TODO: It should be a part of AuthorizationProvider.
- */
- String ACL_FILE = "aclFile";
-
- /*
- * A temporary attributes to set the broker default key/trust stores.
- * TODO: Remove them after adding a full support to configure KeyStore/TrustStore via management layers.
- */
- String KEY_STORE_PATH = "keyStorePath";
- String KEY_STORE_PASSWORD = "keyStorePassword";
- String KEY_STORE_CERT_ALIAS = "keyStoreCertAlias";
- String TRUST_STORE_PATH = "trustStorePath";
- String TRUST_STORE_PASSWORD = "trustStorePassword";
- String PEER_STORE_PATH = "peerStorePath";
- String PEER_STORE_PASSWORD = "peerStorePassword";
-
- /*
- * A temporary attributes to set the broker group file.
- * TODO: Remove them after adding a full support to configure authorization providers via management layers.
- */
- String GROUP_FILE = "groupFile";
-
// Attributes
Collection<String> AVAILABLE_ATTRIBUTES =
Collections.unmodifiableList(
@@ -114,7 +88,8 @@ public interface Broker extends ConfiguredObject
PLATFORM,
PROCESS_PID,
PRODUCT_VERSION,
- SUPPORTED_STORE_TYPES,
+ SUPPORTED_BROKER_STORE_TYPES,
+ SUPPORTED_VIRTUALHOST_STORE_TYPES,
SUPPORTED_AUTHENTICATION_PROVIDERS,
CREATED,
DURABLE,
@@ -124,7 +99,6 @@ public interface Broker extends ConfiguredObject
STATE,
TIME_TO_LIVE,
UPDATED,
- DEFAULT_AUTHENTICATION_PROVIDER,
DEFAULT_VIRTUAL_HOST,
QUEUE_ALERT_THRESHOLD_MESSAGE_AGE,
QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES,
@@ -147,17 +121,7 @@ public interface Broker extends ConfiguredObject
VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE,
VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN,
VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE,
- VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_WARN,
-
- ACL_FILE,
- KEY_STORE_PATH,
- KEY_STORE_PASSWORD,
- KEY_STORE_CERT_ALIAS,
- TRUST_STORE_PATH,
- TRUST_STORE_PASSWORD,
- PEER_STORE_PATH,
- PEER_STORE_PASSWORD,
- GROUP_FILE
+ VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_WARN
));
//children
@@ -167,11 +131,7 @@ public interface Broker extends ConfiguredObject
Collection<AuthenticationProvider> getAuthenticationProviders();
- VirtualHost createVirtualHost(String name, State initialState, boolean durable,
- LifetimePolicy lifetime, long ttl, Map<String, Object> attributes)
- throws AccessControlException, IllegalArgumentException;
-
- AuthenticationProvider getDefaultAuthenticationProvider();
+ Collection<AccessControlProvider> getAccessControlProviders();
Collection<GroupProvider> getGroupProviders();
@@ -192,8 +152,14 @@ public interface Broker extends ConfiguredObject
*/
LogRecorder getLogRecorder();
+ AuthenticationProvider findAuthenticationProviderByName(String authenticationProviderName);
+
VirtualHost findVirtualHostByName(String name);
+ KeyStore findKeyStoreByName(String name);
+
+ TrustStore findTrustStoreByName(String name);
+
/**
* Get the SubjectCreator for the given socket address.
* TODO: move the authentication related functionality into host aliases and AuthenticationProviders
@@ -211,10 +177,6 @@ public interface Broker extends ConfiguredObject
*/
VirtualHostRegistry getVirtualHostRegistry();
- KeyStore getDefaultKeyStore();
-
- TrustStore getDefaultTrustStore();
-
TaskExecutor getTaskExecutor();
boolean isManagementMode();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java
index 959714656b..74a7469ffb 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java
@@ -24,10 +24,23 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-public interface KeyStore extends TrustStore
+public interface KeyStore extends ConfiguredObject
{
+ String ID = "id";
+ String NAME = "name";
+ String DURABLE = "durable";
+ String LIFETIME_POLICY = "lifetimePolicy";
+ String STATE = "state";
+ String TIME_TO_LIVE = "timeToLive";
+ String CREATED = "created";
+ String UPDATED = "updated";
+ String DESCRIPTION = "description";
+ String PATH = "path";
+ String PASSWORD = "password";
+ String TYPE = "type";
String CERTIFICATE_ALIAS = "certificateAlias";
+ String KEY_MANAGER_FACTORY_ALGORITHM = "keyManagerFactoryAlgorithm";
public static final Collection<String> AVAILABLE_ATTRIBUTES =
Collections.unmodifiableList(
@@ -44,8 +57,11 @@ public interface KeyStore extends TrustStore
PATH,
PASSWORD,
TYPE,
- KEY_MANAGER_FACTORY_ALGORITHM,
- CERTIFICATE_ALIAS
+ CERTIFICATE_ALIAS,
+ KEY_MANAGER_FACTORY_ALGORITHM
));
+ public String getPassword();
+
+ public void setPassword(String password);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java
index bf4c40815a..bccb6b48ee 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java
@@ -52,6 +52,7 @@ public class Model
{
addRelationship(Broker.class, VirtualHost.class);
addRelationship(Broker.class, Port.class);
+ addRelationship(Broker.class, AccessControlProvider.class);
addRelationship(Broker.class, AuthenticationProvider.class);
addRelationship(Broker.class, GroupProvider.class);
addRelationship(Broker.class, TrustStore.class);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java
index 33ba34767d..60d62e3f27 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java
@@ -45,6 +45,8 @@ public interface Port extends ConfiguredObject
String NEED_CLIENT_AUTH = "needClientAuth";
String WANT_CLIENT_AUTH = "wantClientAuth";
String AUTHENTICATION_PROVIDER = "authenticationProvider";
+ String KEY_STORE = "keyStore";
+ String TRUST_STORES = "trustStores";
// Attributes
public static final Collection<String> AVAILABLE_ATTRIBUTES =
@@ -67,7 +69,9 @@ public interface Port extends ConfiguredObject
RECEIVE_BUFFER_SIZE,
NEED_CLIENT_AUTH,
WANT_CLIENT_AUTH,
- AUTHENTICATION_PROVIDER
+ AUTHENTICATION_PROVIDER,
+ KEY_STORE,
+ TRUST_STORES
));
@@ -75,6 +79,10 @@ public interface Port extends ConfiguredObject
int getPort();
+ KeyStore getKeyStore();
+
+ Collection<TrustStore> getTrustStores();
+
Collection<Transport> getTransports();
void addTransport(Transport transport) throws IllegalStateException,
@@ -85,7 +93,6 @@ public interface Port extends ConfiguredObject
AccessControlException,
IllegalArgumentException;
-
Collection<Protocol> getProtocols();
void addProtocol(Protocol protocol) throws IllegalStateException,
@@ -96,12 +103,9 @@ public interface Port extends ConfiguredObject
AccessControlException,
IllegalArgumentException;
+ AuthenticationProvider getAuthenticationProvider();
//children
Collection<VirtualHostAlias> getVirtualHostBindings();
Collection<Connection> getConnections();
-
- AuthenticationProvider getAuthenticationProvider();
-
- void setAuthenticationProvider(AuthenticationProvider authenticationProvider);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java
index 53498ab431..c686e7bd50 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java
@@ -38,9 +38,9 @@ public interface TrustStore extends ConfiguredObject
String PATH = "path";
String PASSWORD = "password";
- String PEERS_ONLY = "peersOnly";
String TYPE = "type";
- String KEY_MANAGER_FACTORY_ALGORITHM = "keyManagerFactoryAlgorithm";
+ String PEERS_ONLY = "peersOnly";
+ String TRUST_MANAGER_FACTORY_ALGORITHM = "trustManagerFactoryAlgorithm";
public static final Collection<String> AVAILABLE_ATTRIBUTES =
Collections.unmodifiableList(
@@ -56,9 +56,9 @@ public interface TrustStore extends ConfiguredObject
DESCRIPTION,
PATH,
PASSWORD,
- PEERS_ONLY,
TYPE,
- KEY_MANAGER_FACTORY_ALGORITHM
+ PEERS_ONLY,
+ TRUST_MANAGER_FACTORY_ALGORITHM
));
public String getPassword();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java
index 20929a337a..51fd3a5c78 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java
@@ -63,6 +63,7 @@ abstract class AbstractAdapter implements ConfiguredObject
{
if (attributes.containsKey(name))
{
+ //TODO: dont put nulls
_attributes.put(name, attributes.get(name));
}
}
@@ -254,6 +255,7 @@ abstract class AbstractAdapter implements ConfiguredObject
if((currentValue == null && expected == null)
|| (currentValue != null && currentValue.equals(expected)))
{
+ //TODO: dont put nulls
_attributes.put(name, desired);
return true;
}
@@ -397,4 +399,51 @@ abstract class AbstractAdapter implements ConfiguredObject
{
return _defaultAttributes;
}
+
+ /**
+ * Returns a map of effective attribute values that would result
+ * if applying the supplied changes. Does not apply the changes.
+ */
+ protected Map<String, Object> generateEffectiveAttributes(Map<String,Object> changedValues)
+ {
+ //Build a new set of effective attributes that would be
+ //the result of applying the attribute changes, so we
+ //can validate the configuration that would result
+
+ Map<String, Object> defaultValues = getDefaultAttributes();
+ Map<String, Object> existingActualValues = getActualAttributes();
+
+ //create a new merged map, starting with the defaults
+ Map<String, Object> merged = new HashMap<String, Object>(defaultValues);
+
+ for(String name : getAttributeNames())
+ {
+ if(changedValues.containsKey(name))
+ {
+ Object changedValue = changedValues.get(name);
+ if(changedValue != null)
+ {
+ //use the new non-null value for the merged values
+ merged.put(name, changedValue);
+ }
+ else
+ {
+ //we just use the default (if there was one) since the changed
+ //value is null and effectively clears any existing actual value
+ }
+ }
+ else if(existingActualValues.get(name) != null)
+ {
+ //Use existing non-null actual value for the merge
+ merged.put(name, existingActualValues.get(name));
+ }
+ else
+ {
+ //There was neither a change or an existing non-null actual
+ //value, so just use the default value (if there was one).
+ }
+ }
+
+ return merged;
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java
index 80196c395e..707cf8076d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java
@@ -37,20 +37,21 @@ import org.apache.qpid.server.util.MapValueConverter;
public abstract class AbstractKeyStoreAdapter extends AbstractAdapter
{
+ public static final String DUMMY_PASSWORD_MASK = "********";
+ public static final String DEFAULT_KEYSTORE_TYPE = java.security.KeyStore.getDefaultType();
+
private String _name;
private String _password;
- protected AbstractKeyStoreAdapter(UUID id, Broker broker, Map<String, Object> attributes)
+ protected AbstractKeyStoreAdapter(UUID id, Broker broker, Map<String, Object> defaults,
+ Map<String, Object> attributes)
{
- super(id, broker.getTaskExecutor());
+ super(id, defaults, attributes, broker.getTaskExecutor());
addParent(Broker.class, broker);
+
_name = MapValueConverter.getStringAttribute(TrustStore.NAME, attributes);
_password = MapValueConverter.getStringAttribute(TrustStore.PASSWORD, attributes);
- setMandatoryAttribute(TrustStore.PATH, attributes);
- setOptionalAttribute(TrustStore.PEERS_ONLY, attributes);
- setOptionalAttribute(TrustStore.TYPE, attributes);
- setOptionalAttribute(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM, attributes);
- setOptionalAttribute(TrustStore.DESCRIPTION, attributes);
+ MapValueConverter.assertMandatoryAttribute(KeyStore.PATH, attributes);
}
@Override
@@ -163,15 +164,16 @@ public abstract class AbstractKeyStoreAdapter extends AbstractAdapter
}
else if(KeyStore.PASSWORD.equals(name))
{
- return null; // for security reasons we don't expose the password
+ // For security reasons we don't expose the password
+ if (getPassword() != null)
+ {
+ return DUMMY_PASSWORD_MASK;
+ }
+
+ return null;
}
- return super.getAttribute(name);
- }
- @Override
- protected boolean setState(State currentState, State desiredState)
- {
- return false;
+ return super.getAttribute(name);
}
public String getPassword()
@@ -183,25 +185,4 @@ public abstract class AbstractKeyStoreAdapter extends AbstractAdapter
{
_password = password;
}
-
- private void setMandatoryAttribute(String name, Map<String, Object> attributeValues)
- {
- changeAttribute(name, null, MapValueConverter.getStringAttribute(name, attributeValues));
- }
-
- private void setOptionalAttribute(String name, Map<String, Object> attributeValues)
- {
- Object attrValue = attributeValues.get(name);
- if (attrValue != null)
- {
- if (attrValue instanceof Boolean)
- {
- changeAttribute(name, null, MapValueConverter.getBooleanAttribute(name, attributeValues));
- }
- else
- {
- changeAttribute(name, null, MapValueConverter.getStringAttribute(name, attributeValues));
- }
- }
- }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderAdapter.java
new file mode 100644
index 0000000000..75b80eb56c
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderAdapter.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.server.model.adapter;
+
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.qpid.server.model.AccessControlProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.IllegalStateTransitionException;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.plugin.AccessControlFactory;
+import org.apache.qpid.server.security.AccessControl;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.util.MapValueConverter;
+
+public class AccessControlProviderAdapter extends AbstractAdapter implements AccessControlProvider
+{
+ protected AccessControl _accessControl;
+ protected final Broker _broker;
+
+ protected Collection<String> _supportedAttributes;
+ protected Map<String, AccessControlFactory> _factories;
+ private AtomicReference<State> _state;
+
+ public AccessControlProviderAdapter(UUID id, Broker broker, AccessControl accessControl, Map<String, Object> attributes, Collection<String> attributeNames)
+ {
+ super(id, null, null, broker.getTaskExecutor());
+
+ if (accessControl == null)
+ {
+ throw new IllegalArgumentException("AccessControl must not be null");
+ }
+
+ _accessControl = accessControl;
+ _broker = broker;
+ _supportedAttributes = createSupportedAttributes(attributeNames);
+ addParent(Broker.class, broker);
+
+ State state = MapValueConverter.getEnumAttribute(State.class, STATE, attributes, State.INITIALISING);
+ _state = new AtomicReference<State>(state);
+
+ // set attributes now after all attribute names are known
+ if (attributes != null)
+ {
+ for (String name : _supportedAttributes)
+ {
+ if (attributes.containsKey(name))
+ {
+ changeAttribute(name, null, attributes.get(name));
+ }
+ }
+ }
+ }
+
+ protected Collection<String> createSupportedAttributes(Collection<String> factoryAttributes)
+ {
+ List<String> attributesNames = new ArrayList<String>(AVAILABLE_ATTRIBUTES);
+ if (factoryAttributes != null)
+ {
+ attributesNames.addAll(factoryAttributes);
+ }
+
+ return Collections.unmodifiableCollection(attributesNames);
+ }
+
+ @Override
+ public String getName()
+ {
+ return (String)getAttribute(AccessControlProvider.NAME);
+ }
+
+ @Override
+ public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException
+ {
+ return null;
+ }
+
+ @Override
+ public State getActualState()
+ {
+ return _state.get();
+ }
+
+ @Override
+ public boolean isDurable()
+ {
+ return true;
+ }
+
+ @Override
+ public void setDurable(boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ }
+
+ @Override
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+
+ @Override
+ public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return null;
+ }
+
+ @Override
+ public long getTimeToLive()
+ {
+ return 0;
+ }
+
+ @Override
+ public long setTimeToLive(long expected, long desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ return 0;
+ }
+
+ @Override
+ public Statistics getStatistics()
+ {
+ return NoStatistics.getInstance();
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return _supportedAttributes;
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+ if(CREATED.equals(name))
+ {
+ // TODO
+ }
+ else if(DURABLE.equals(name))
+ {
+ return true;
+ }
+ else if(ID.equals(name))
+ {
+ return getId();
+ }
+ else if(LIFETIME_POLICY.equals(name))
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+ else if(STATE.equals(name))
+ {
+ return getActualState();
+ }
+ else if(TIME_TO_LIVE.equals(name))
+ {
+ // TODO
+ }
+ else if(UPDATED.equals(name))
+ {
+ // TODO
+ }
+ return super.getAttribute(name);
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public boolean setState(State currentState, State desiredState)
+ throws IllegalStateTransitionException, AccessControlException
+ {
+ State state = _state.get();
+
+ if(desiredState == State.DELETED)
+ {
+ return _state.compareAndSet(state, State.DELETED);
+ }
+ else if (desiredState == State.QUIESCED)
+ {
+ return _state.compareAndSet(state, State.QUIESCED);
+ }
+ else if(desiredState == State.ACTIVE)
+ {
+ if ((state == State.INITIALISING || state == State.QUIESCED) && _state.compareAndSet(state, State.ACTIVE))
+ {
+ _accessControl.open();
+ return true;
+ }
+ else
+ {
+ throw new IllegalStateException("Can't activate access control provider in " + state + " state");
+ }
+ }
+ else if(desiredState == State.STOPPED)
+ {
+ if(_state.compareAndSet(state, State.STOPPED))
+ {
+ _accessControl.close();
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+ }
+
+
+ @Override
+ protected void changeAttributes(Map<String, Object> attributes)
+ {
+ throw new UnsupportedOperationException("Changing attributes on AccessControlProvider is not supported");
+ }
+
+ @Override
+ protected void authoriseSetDesiredState(State currentState, State desiredState) throws AccessControlException
+ {
+ if(desiredState == State.DELETED)
+ {
+ if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), AccessControlProvider.class, Operation.DELETE))
+ {
+ throw new AccessControlException("Deletion of AccessControlProvider is denied");
+ }
+ }
+ }
+
+ @Override
+ protected void authoriseSetAttribute(String name, Object expected, Object desired) throws AccessControlException
+ {
+ if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), AccessControlProvider.class, Operation.UPDATE))
+ {
+ throw new AccessControlException("Setting of AccessControlProvider attributes is denied");
+ }
+ }
+
+ @Override
+ protected void authoriseSetAttributes(Map<String, Object> attributes) throws AccessControlException
+ {
+ if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), AccessControlProvider.class, Operation.UPDATE))
+ {
+ throw new AccessControlException("Setting of AccessControlProvider attributes is denied");
+ }
+ }
+
+ public AccessControl getAccessControl()
+ {
+ return _accessControl;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderFactory.java
new file mode 100644
index 0000000000..6cdf2f2c1a
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderFactory.java
@@ -0,0 +1,90 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model.adapter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.model.AccessControlProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.plugin.AccessControlFactory;
+import org.apache.qpid.server.plugin.QpidServiceLoader;
+import org.apache.qpid.server.security.AccessControl;
+
+public class AccessControlProviderFactory
+{
+ private final Iterable<AccessControlFactory> _factories;
+ private Collection<String> _supportedAcessControlProviders;
+
+ public AccessControlProviderFactory(QpidServiceLoader<AccessControlFactory> accessControlFactoryServiceLoader)
+ {
+ _factories = accessControlFactoryServiceLoader.instancesOf(AccessControlFactory.class);
+ List<String> supportedAccessControlProviders = new ArrayList<String>();
+ for (AccessControlFactory factory : _factories)
+ {
+ supportedAccessControlProviders.add(factory.getType());
+ }
+ _supportedAcessControlProviders = Collections.unmodifiableCollection(supportedAccessControlProviders);
+ }
+
+ /**
+ * Creates {@link AccessControlProvider} for given ID, {@link Broker} and attributes.
+ * <p>
+ * The configured {@link AccessControlFactory}'s are used to try to create the {@link AccessControlProvider}.
+ * The first non-null instance is returned. The factories are used in non-deterministic order.
+ */
+ public AccessControlProvider create(UUID id, Broker broker, Map<String, Object> attributes)
+ {
+ AccessControlProvider ac = createAccessControlProvider(id, broker, attributes);
+ ac.getAccessControl().onCreate();
+
+ return ac;
+ }
+
+ public AccessControlProvider recover(UUID id, Broker broker, Map<String, Object> attributes)
+ {
+ return createAccessControlProvider(id, broker, attributes);
+ }
+
+ private AccessControlProvider createAccessControlProvider(UUID id,
+ Broker broker, Map<String, Object> attributes)
+ {
+ for (AccessControlFactory factory : _factories)
+ {
+ AccessControl accessControl = factory.createInstance(attributes);
+ if (accessControl != null)
+ {
+ return new AccessControlProviderAdapter(id, broker,accessControl, attributes, factory.getAttributeNames());
+ }
+ }
+
+ throw new IllegalArgumentException("No access control provider factory found for configuration attributes " + attributes);
+ }
+
+ public Collection<String> getSupportedAuthenticationProviders()
+ {
+ return _supportedAcessControlProviders;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java
index e7057f89d3..71f5397d2b 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java
@@ -133,15 +133,11 @@ public class AmqpPortAdapter extends PortAdapter
private SSLContext createSslContext()
{
- KeyStore keyStore = _broker.getDefaultKeyStore();
- if (keyStore == null)
- {
- throw new IllegalConfigurationException("SSL was requested on AMQP port '"
- + this.getName() + "' but no key store defined");
- }
+ KeyStore keyStore = getKeyStore();
- Collection<TrustStore> trustStores = _broker.getTrustStores();
- if (((Boolean)getAttribute(NEED_CLIENT_AUTH) || (Boolean)getAttribute(WANT_CLIENT_AUTH)) && trustStores.isEmpty())
+ Collection<TrustStore> trustStores = getTrustStores();
+ boolean needClientCert = (Boolean)getAttribute(NEED_CLIENT_AUTH) || (Boolean)getAttribute(WANT_CLIENT_AUTH);
+ if (needClientCert && trustStores.isEmpty())
{
throw new IllegalConfigurationException("Client certificate authentication is enabled on AMQP port '"
+ this.getName() + "' but no trust store defined");
@@ -165,7 +161,7 @@ public class AmqpPortAdapter extends PortAdapter
trustStore.getPassword(),
(String)trustStore.getAttribute(TrustStore.TYPE),
(Boolean) trustStore.getAttribute(TrustStore.PEERS_ONLY),
- (String)trustStore.getAttribute(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM)));
+ (String)trustStore.getAttribute(TrustStore.TRUST_MANAGER_FACTORY_ALGORITHM)));
}
sslContext = SSLContextFactory.buildClientContext(trstWrappers, keystorePath,
keystorePassword, keystoreType,
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java
index f788923b3a..8d601460ad 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java
@@ -219,10 +219,6 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana
String providerName = getName();
// verify that provider is not in use
- if (providerName.equals(_broker.getAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER)))
- {
- throw new IntegrityViolationException("Authentication provider '" + providerName + "' is set as default and cannot be deleted");
- }
Collection<Port> ports = new ArrayList<Port>(_broker.getPorts());
for (Port port : ports)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
index e968d91e79..c715f1989c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
@@ -24,7 +24,6 @@ import java.lang.reflect.Type;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.security.AccessControlException;
-import java.security.KeyStoreException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -32,17 +31,19 @@ import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
-import javax.net.ssl.KeyManagerFactory;
-import java.security.cert.Certificate;
-
import org.apache.log4j.Logger;
import org.apache.qpid.common.QpidProperties;
+import org.apache.qpid.server.BrokerOptions;
+import org.apache.qpid.server.configuration.BrokerConfigurationStoreCreator;
import org.apache.qpid.server.configuration.ConfigurationEntryStore;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.logging.LogRecorder;
import org.apache.qpid.server.logging.RootMessageLogger;
import org.apache.qpid.server.logging.actors.BrokerActor;
import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.messages.BrokerMessages;
+import org.apache.qpid.server.model.AccessControlProvider;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfigurationChangeListener;
@@ -58,22 +59,19 @@ import org.apache.qpid.server.model.Statistics;
import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.model.VirtualHost;
-import org.apache.qpid.server.configuration.store.ManagementModeStoreHandler;
-import org.apache.qpid.server.configuration.updater.TaskExecutor;
-import org.apache.qpid.server.security.access.Operation;
-import org.apache.qpid.server.security.group.FileGroupManager;
-import org.apache.qpid.server.security.group.GroupManager;
+import org.apache.qpid.server.model.adapter.AuthenticationProviderAdapter.SimpleAuthenticationProviderAdapter;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.SubjectCreator;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.server.security.auth.manager.SimpleAuthenticationManager;
import org.apache.qpid.server.stats.StatisticsGatherer;
import org.apache.qpid.server.store.MessageStoreCreator;
import org.apache.qpid.server.util.MapValueConverter;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
-import org.apache.qpid.transport.network.security.ssl.SSLUtil;
public class BrokerAdapter extends AbstractAdapter implements Broker, ConfigurationChangeListener
{
-
private static final Logger LOGGER = Logger.getLogger(BrokerAdapter.class);
@SuppressWarnings("serial")
@@ -95,19 +93,9 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
put(CONNECTION_HEART_BEAT_DELAY, Integer.class);
put(STATISTICS_REPORTING_PERIOD, Integer.class);
- put(ACL_FILE, String.class);
put(NAME, String.class);
put(DEFAULT_VIRTUAL_HOST, String.class);
- put(DEFAULT_AUTHENTICATION_PROVIDER, String.class);
-
- put(KEY_STORE_PATH, String.class);
- put(KEY_STORE_PASSWORD, String.class);
- put(KEY_STORE_CERT_ALIAS, String.class);
- put(TRUST_STORE_PATH, String.class);
- put(TRUST_STORE_PASSWORD, String.class);
- put(PEER_STORE_PATH, String.class);
- put(PEER_STORE_PASSWORD, String.class);
- put(GROUP_FILE, String.class);
+
put(VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, Long.class);
put(VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN, Long.class);
put(VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, Long.class);
@@ -133,12 +121,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
public static final long DEFAULT_STORE_TRANSACTION_IDLE_TIMEOUT_WARN = 0l;
public static final long DEFAULT_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE = 0l;
public static final long DEFAULT_STORE_TRANSACTION_OPEN_TIMEOUT_WARN = 0l;
- private static final String DEFAULT_KEY_STORE_NAME = "defaultKeyStore";
- private static final String DEFAULT_TRUST_STORE_NAME = "defaultTrustStore";
- private static final String DEFAULT_GROUP_PROVIDER_NAME = "defaultGroupProvider";
- private static final String DEFAULT_PEER_STORE_NAME = "defaultPeerStore";
-
- private static final String DUMMY_PASSWORD_MASK = "********";
@SuppressWarnings("serial")
private static final Map<String, Object> DEFAULTS = Collections.unmodifiableMap(new HashMap<String, Object>(){{
@@ -182,25 +164,28 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
private final Map<UUID, AuthenticationProvider> _authenticationProviders = new HashMap<UUID, AuthenticationProvider>();
private final Map<String, GroupProvider> _groupProviders = new HashMap<String, GroupProvider>();
private final Map<UUID, ConfiguredObject> _plugins = new HashMap<UUID, ConfiguredObject>();
- private final Map<UUID, KeyStore> _keyStores = new HashMap<UUID, KeyStore>();
- private final Map<UUID, TrustStore> _trustStores = new HashMap<UUID, TrustStore>();
+ private final Map<String, KeyStore> _keyStores = new HashMap<String, KeyStore>();
+ private final Map<String, TrustStore> _trustStores = new HashMap<String, TrustStore>();
+ private final Map<UUID, AccessControlProvider> _accessControlProviders = new HashMap<UUID, AccessControlProvider>();
+ private final GroupProviderFactory _groupProviderFactory;
private final AuthenticationProviderFactory _authenticationProviderFactory;
- private AuthenticationProvider _defaultAuthenticationProvider;
+ private final AccessControlProviderFactory _accessControlProviderFactory;
private final PortFactory _portFactory;
private final SecurityManager _securityManager;
- private final UUID _defaultKeyStoreId;
- private final UUID _defaultTrustStoreId;
- private final Collection<String> _supportedStoreTypes;
+ private final Collection<String> _supportedVirtualHostStoreTypes;
+ private Collection<String> _supportedBrokerStoreTypes;
private final ConfigurationEntryStore _brokerStore;
- private boolean _managementMode;
+ private AuthenticationProvider _managementAuthenticationProvider;
+ private BrokerOptions _brokerOptions;
public BrokerAdapter(UUID id, Map<String, Object> attributes, StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry,
LogRecorder logRecorder, RootMessageLogger rootMessageLogger, AuthenticationProviderFactory authenticationProviderFactory,
- PortFactory portFactory, TaskExecutor taskExecutor, ConfigurationEntryStore brokerStore)
+ GroupProviderFactory groupProviderFactory, AccessControlProviderFactory accessControlProviderFactory, PortFactory portFactory, TaskExecutor taskExecutor,
+ ConfigurationEntryStore brokerStore, BrokerOptions brokerOptions)
{
super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor);
_statisticsGatherer = statisticsGatherer;
@@ -209,109 +194,20 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
_rootMessageLogger = rootMessageLogger;
_statistics = new StatisticsAdapter(statisticsGatherer);
_authenticationProviderFactory = authenticationProviderFactory;
+ _groupProviderFactory = groupProviderFactory;
+ _accessControlProviderFactory = accessControlProviderFactory;
_portFactory = portFactory;
- _securityManager = new SecurityManager((String)getAttribute(ACL_FILE));
- addChangeListener(_securityManager);
- _defaultKeyStoreId = UUIDGenerator.generateBrokerChildUUID(KeyStore.class.getSimpleName(), DEFAULT_KEY_STORE_NAME);
- _defaultTrustStoreId = UUIDGenerator.generateBrokerChildUUID(TrustStore.class.getSimpleName(), DEFAULT_TRUST_STORE_NAME);
- createBrokerChildrenFromAttributes();
- _supportedStoreTypes = new MessageStoreCreator().getStoreTypes();
+ _brokerOptions = brokerOptions;
+ _securityManager = new SecurityManager(this, _brokerOptions.isManagementMode());
+ _supportedVirtualHostStoreTypes = new MessageStoreCreator().getStoreTypes();
+ _supportedBrokerStoreTypes = new BrokerConfigurationStoreCreator().getStoreTypes();
_brokerStore = brokerStore;
- _managementMode = brokerStore instanceof ManagementModeStoreHandler;
- }
-
- /*
- * A temporary method to create broker children that can be only configured via broker attributes
- */
- private void createBrokerChildrenFromAttributes()
- {
- createGroupProvider();
- createKeyStore();
- createTrustStore();
- createPeerStore();
- }
-
- private void createGroupProvider()
- {
- String groupFile = (String) getAttribute(GROUP_FILE);
- if (groupFile != null)
- {
- GroupManager groupManager = new FileGroupManager(groupFile);
- UUID groupProviderId = UUIDGenerator.generateBrokerChildUUID(GroupProvider.class.getSimpleName(),
- DEFAULT_GROUP_PROVIDER_NAME);
- GroupProviderAdapter groupProviderAdapter = new GroupProviderAdapter(groupProviderId, groupManager, this);
- _groupProviders.put(DEFAULT_GROUP_PROVIDER_NAME, groupProviderAdapter);
- }
- else
- {
- _groupProviders.remove(DEFAULT_GROUP_PROVIDER_NAME);
- }
- }
-
- private void createKeyStore()
- {
- Map<String, Object> actualAttributes = getActualAttributes();
- String keyStorePath = (String) getAttribute(KEY_STORE_PATH);
- if (keyStorePath != null)
+ if (_brokerOptions.isManagementMode())
{
- Map<String, Object> keyStoreAttributes = new HashMap<String, Object>();
- keyStoreAttributes.put(KeyStore.NAME, DEFAULT_KEY_STORE_NAME);
- keyStoreAttributes.put(KeyStore.PATH, keyStorePath);
- keyStoreAttributes.put(KeyStore.PASSWORD, (String) actualAttributes.get(KEY_STORE_PASSWORD));
- keyStoreAttributes.put(KeyStore.TYPE, java.security.KeyStore.getDefaultType());
- keyStoreAttributes.put(KeyStore.CERTIFICATE_ALIAS, getAttribute(KEY_STORE_CERT_ALIAS));
- keyStoreAttributes.put(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM, KeyManagerFactory.getDefaultAlgorithm());
- KeyStoreAdapter keyStoreAdapter = new KeyStoreAdapter(_defaultKeyStoreId, this, keyStoreAttributes);
- _keyStores.put(keyStoreAdapter.getId(), keyStoreAdapter);
- }
- else
- {
- _keyStores.remove(_defaultKeyStoreId);
- }
- }
-
- private void createTrustStore()
- {
- Map<String, Object> actualAttributes = getActualAttributes();
- String trustStorePath = (String) getAttribute(TRUST_STORE_PATH);
- if (trustStorePath != null)
- {
- Map<String, Object> trsustStoreAttributes = new HashMap<String, Object>();
- trsustStoreAttributes.put(TrustStore.NAME, DEFAULT_TRUST_STORE_NAME);
- trsustStoreAttributes.put(TrustStore.PATH, trustStorePath);
- trsustStoreAttributes.put(TrustStore.PEERS_ONLY, Boolean.FALSE);
- trsustStoreAttributes.put(TrustStore.PASSWORD, (String) actualAttributes.get(TRUST_STORE_PASSWORD));
- trsustStoreAttributes.put(TrustStore.TYPE, java.security.KeyStore.getDefaultType());
- trsustStoreAttributes.put(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM, KeyManagerFactory.getDefaultAlgorithm());
- TrustStoreAdapter trustStore = new TrustStoreAdapter(_defaultTrustStoreId, this, trsustStoreAttributes);
- _trustStores.put(trustStore.getId(), trustStore);
- }
- else
- {
- _trustStores.remove(_defaultTrustStoreId);
- }
- }
-
- private void createPeerStore()
- {
- Map<String, Object> actualAttributes = getActualAttributes();
- String peerStorePath = (String) getAttribute(PEER_STORE_PATH);
- UUID peerStoreId = UUIDGenerator.generateBrokerChildUUID(TrustStore.class.getSimpleName(), DEFAULT_PEER_STORE_NAME);
- if (peerStorePath != null)
- {
- Map<String, Object> peerStoreAttributes = new HashMap<String, Object>();
- peerStoreAttributes.put(TrustStore.NAME, peerStoreId.toString());
- peerStoreAttributes.put(TrustStore.PATH, peerStorePath);
- peerStoreAttributes.put(TrustStore.PEERS_ONLY, Boolean.TRUE);
- peerStoreAttributes.put(TrustStore.PASSWORD, (String) actualAttributes.get(PEER_STORE_PASSWORD));
- peerStoreAttributes.put(TrustStore.TYPE, java.security.KeyStore.getDefaultType());
- peerStoreAttributes.put(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM, KeyManagerFactory.getDefaultAlgorithm());
- TrustStoreAdapter trustStore = new TrustStoreAdapter(peerStoreId, this, peerStoreAttributes);
- _trustStores.put(trustStore.getId(), trustStore);
- }
- else
- {
- _trustStores.remove(peerStoreId);
+ AuthenticationManager authManager = new SimpleAuthenticationManager(BrokerOptions.MANAGEMENT_MODE_USER_NAME, _brokerOptions.getManagementModePassword());
+ AuthenticationProvider authenticationProvider = new SimpleAuthenticationProviderAdapter(UUID.randomUUID(), this,
+ authManager, Collections.<String, Object> emptyMap(), Collections.<String> emptySet());
+ _managementAuthenticationProvider = authenticationProvider;
}
}
@@ -321,7 +217,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
{
return new ArrayList<VirtualHost>(_vhostAdapters.values());
}
-
}
public Collection<Port> getPorts()
@@ -343,6 +238,10 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
public AuthenticationProvider findAuthenticationProviderByName(String authenticationProviderName)
{
+ if (isManagementMode())
+ {
+ return _managementAuthenticationProvider;
+ }
Collection<AuthenticationProvider> providers = getAuthenticationProviders();
for (AuthenticationProvider authenticationProvider : providers)
{
@@ -354,15 +253,20 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
return null;
}
- @Override
- public AuthenticationProvider getDefaultAuthenticationProvider()
+ public KeyStore findKeyStoreByName(String keyStoreName)
{
- return _defaultAuthenticationProvider;
+ synchronized(_keyStores)
+ {
+ return _keyStores.get(keyStoreName);
+ }
}
- public void setDefaultAuthenticationProvider(AuthenticationProvider provider)
+ public TrustStore findTrustStoreByName(String trustStoreName)
{
- _defaultAuthenticationProvider = provider;
+ synchronized(_trustStores)
+ {
+ return _trustStores.get(trustStoreName);
+ }
}
@Override
@@ -376,17 +280,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
}
}
- public VirtualHost createVirtualHost(final String name,
- final State initialState,
- final boolean durable,
- final LifetimePolicy lifetime,
- final long ttl,
- final Map<String, Object> attributes)
- throws AccessControlException, IllegalArgumentException
- {
- return null; //TODO
- }
-
private VirtualHost createVirtualHost(final Map<String, Object> attributes)
throws AccessControlException, IllegalArgumentException
{
@@ -396,14 +289,14 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
// permission has already been granted to create the virtual host
// disable further access check on other operations, e.g. create exchange
- _securityManager.setAccessChecksDisabled(true);
+ SecurityManager.setAccessChecksDisabled(true);
try
{
virtualHostAdapter.setDesiredState(State.INITIALISING, State.ACTIVE);
}
finally
{
- _securityManager.setAccessChecksDisabled(false);
+ SecurityManager.setAccessChecksDisabled(false);
}
return virtualHostAdapter;
}
@@ -486,6 +379,10 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
{
return (Collection<C>) getPorts();
}
+ else if(clazz == AccessControlProvider.class)
+ {
+ return (Collection<C>) getAccessControlProviders();
+ }
else if(clazz == AuthenticationProvider.class)
{
return (Collection<C>) getAuthenticationProviders();
@@ -522,10 +419,26 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
{
return (C) createPort(attributes);
}
+ else if(childClass == AccessControlProvider.class)
+ {
+ return (C) createAccessControlProvider(attributes);
+ }
else if(childClass == AuthenticationProvider.class)
{
return (C) createAuthenticationProvider(attributes);
}
+ else if(childClass == KeyStore.class)
+ {
+ return (C) createKeyStore(attributes);
+ }
+ else if(childClass == TrustStore.class)
+ {
+ return (C) createTrustStore(attributes);
+ }
+ else if(childClass == GroupProvider.class)
+ {
+ return (C) createGroupProvider(attributes);
+ }
else
{
throw new IllegalArgumentException("Cannot create child of class " + childClass.getSimpleName());
@@ -563,6 +476,64 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
return port;
}
+ private AccessControlProvider createAccessControlProvider(Map<String, Object> attributes)
+ {
+ AccessControlProvider accessControlProvider = null;
+ synchronized (_accessControlProviders)
+ {
+ accessControlProvider = _accessControlProviderFactory.create(UUID.randomUUID(), this, attributes);
+ addAccessControlProvider(accessControlProvider);
+ }
+
+ boolean quiesce = isManagementMode() ;
+ accessControlProvider.setDesiredState(State.INITIALISING, quiesce ? State.QUIESCED : State.ACTIVE);
+
+ return accessControlProvider;
+ }
+
+ /**
+ * @throws IllegalConfigurationException if an AuthenticationProvider with the same name already exists
+ */
+ private void addAccessControlProvider(AccessControlProvider accessControlProvider)
+ {
+ String name = accessControlProvider.getName();
+ synchronized (_authenticationProviders)
+ {
+ if (_accessControlProviders.containsKey(accessControlProvider.getId()))
+ {
+ throw new IllegalConfigurationException("Can't add AccessControlProvider because one with id " + accessControlProvider.getId() + " already exists");
+ }
+ for (AccessControlProvider provider : _accessControlProviders.values())
+ {
+ if (provider.getName().equals(name))
+ {
+ throw new IllegalConfigurationException("Can't add AccessControlProvider because one with name " + name + " already exists");
+ }
+ }
+ _accessControlProviders.put(accessControlProvider.getId(), accessControlProvider);
+ }
+
+ accessControlProvider.addChangeListener(this);
+ accessControlProvider.addChangeListener(_securityManager);
+ }
+
+ private boolean deleteAccessControlProvider(AccessControlProvider accessControlProvider)
+ {
+ AccessControlProvider removedAccessControlProvider = null;
+ synchronized (_accessControlProviders)
+ {
+ removedAccessControlProvider = _accessControlProviders.remove(accessControlProvider.getId());
+ }
+
+ if(removedAccessControlProvider != null)
+ {
+ removedAccessControlProvider.removeChangeListener(this);
+ removedAccessControlProvider.removeChangeListener(_securityManager);
+ }
+
+ return removedAccessControlProvider != null;
+ }
+
private AuthenticationProvider createAuthenticationProvider(Map<String, Object> attributes)
{
AuthenticationProvider authenticationProvider = null;
@@ -599,6 +570,14 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
authenticationProvider.addChangeListener(this);
}
+ private GroupProvider createGroupProvider(Map<String, Object> attributes)
+ {
+ GroupProvider groupProvider = _groupProviderFactory.create(UUID.randomUUID(), this, attributes);
+ groupProvider.setDesiredState(State.INITIALISING, State.ACTIVE);
+ addGroupProvider(groupProvider);
+ return groupProvider;
+ }
+
private void addGroupProvider(GroupProvider groupProvider)
{
synchronized (_groupProviders)
@@ -613,45 +592,92 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
groupProvider.addChangeListener(this);
}
- private boolean deleteGroupProvider(GroupProvider object)
+ private boolean deleteGroupProvider(GroupProvider groupProvider)
+ {
+ GroupProvider removedGroupProvider = null;
+ synchronized (_groupProviders)
+ {
+ removedGroupProvider = _groupProviders.remove(groupProvider.getName());
+ }
+
+ if(removedGroupProvider != null)
+ {
+ removedGroupProvider.removeChangeListener(this);
+ }
+
+ return removedGroupProvider != null;
+ }
+
+ private KeyStore createKeyStore(Map<String, Object> attributes)
+ {
+ KeyStore keyStore = new KeyStoreAdapter(UUIDGenerator.generateRandomUUID(), this, attributes);
+ addKeyStore(keyStore);
+
+ return keyStore;
+ }
+
+ private TrustStore createTrustStore(Map<String, Object> attributes)
{
- throw new UnsupportedOperationException("Not implemented yet!");
+ TrustStore trustStore = new TrustStoreAdapter(UUIDGenerator.generateRandomUUID(), this, attributes);
+ addTrustStore(trustStore);
+
+ return trustStore;
}
private void addKeyStore(KeyStore keyStore)
{
synchronized (_keyStores)
{
- if(_keyStores.containsKey(keyStore.getId()))
+ if(_keyStores.containsKey(keyStore.getName()))
{
- throw new IllegalConfigurationException("Cannot add KeyStore because one with id " + keyStore.getId() + " already exists");
+ throw new IllegalConfigurationException("Can't add KeyStore because one with name " + keyStore.getName() + " already exists");
}
- _keyStores.put(keyStore.getId(), keyStore);
+ _keyStores.put(keyStore.getName(), keyStore);
}
keyStore.addChangeListener(this);
}
private boolean deleteKeyStore(KeyStore object)
{
- throw new UnsupportedOperationException("Not implemented yet!");
+ synchronized(_keyStores)
+ {
+ String name = object.getName();
+ KeyStore removedKeyStore = _keyStores.remove(name);
+ if(removedKeyStore != null)
+ {
+ removedKeyStore.removeChangeListener(this);
+ }
+
+ return removedKeyStore != null;
+ }
}
private void addTrustStore(TrustStore trustStore)
{
synchronized (_trustStores)
{
- if(_trustStores.containsKey(trustStore.getId()))
+ if(_trustStores.containsKey(trustStore.getName()))
{
- throw new IllegalConfigurationException("Cannot add TrustStore because one with id " + trustStore.getId() + " already exists");
+ throw new IllegalConfigurationException("Can't add TrustStore because one with name " + trustStore.getName() + " already exists");
}
- _trustStores.put(trustStore.getId(), trustStore);
+ _trustStores.put(trustStore.getName(), trustStore);
}
trustStore.addChangeListener(this);
}
private boolean deleteTrustStore(TrustStore object)
{
- throw new UnsupportedOperationException("Not implemented yet!");
+ synchronized(_trustStores)
+ {
+ String name = object.getName();
+ TrustStore removedTrustStore = _trustStores.remove(name);
+ if(removedTrustStore != null)
+ {
+ removedTrustStore.removeChangeListener(this);
+ }
+
+ return removedTrustStore != null;
+ }
}
@Override
@@ -718,21 +744,17 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
{
return QpidProperties.getReleaseVersion();
}
- else if(SUPPORTED_STORE_TYPES.equals(name))
+ else if(SUPPORTED_BROKER_STORE_TYPES.equals(name))
{
- return _supportedStoreTypes;
+ return _supportedBrokerStoreTypes;
}
- else if(SUPPORTED_AUTHENTICATION_PROVIDERS.equals(name))
+ else if(SUPPORTED_VIRTUALHOST_STORE_TYPES.equals(name))
{
- return _authenticationProviderFactory.getSupportedAuthenticationProviders();
+ return _supportedVirtualHostStoreTypes;
}
- else if (KEY_STORE_PASSWORD.equals(name) || TRUST_STORE_PASSWORD.equals(name) || PEER_STORE_PASSWORD.equals(name))
+ else if(SUPPORTED_AUTHENTICATION_PROVIDERS.equals(name))
{
- if (getActualAttributes().get(name) != null)
- {
- return DUMMY_PASSWORD_MASK;
- }
- return null;
+ return _authenticationProviderFactory.getSupportedAuthenticationProviders();
}
else if (MODEL_VERSION.equals(name))
{
@@ -760,6 +782,12 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
{
removedPort = _portAdapters.remove(portAdapter.getPort());
}
+
+ if (removedPort != null)
+ {
+ removedPort.removeChangeListener(this);
+ }
+
return removedPort != null;
}
@@ -770,6 +798,12 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
{
removedAuthenticationProvider = _authenticationProviders.remove(authenticationProvider.getId());
}
+
+ if(removedAuthenticationProvider != null)
+ {
+ removedAuthenticationProvider.removeChangeListener(this);
+ }
+
return removedAuthenticationProvider != null;
}
@@ -794,6 +828,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
{
changeState(_groupProviders, currentState, State.ACTIVE, false);
changeState(_authenticationProviders, currentState, State.ACTIVE, false);
+ changeState(_accessControlProviders, currentState, State.ACTIVE, false);
CurrentActor.set(new BrokerActor(getRootMessageLogger()));
try
@@ -807,6 +842,11 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
changeState(_portAdapters, currentState,State.ACTIVE, false);
changeState(_plugins, currentState,State.ACTIVE, false);
+
+ if (isManagementMode())
+ {
+ CurrentActor.get().message(BrokerMessages.MANAGEMENT_MODE(BrokerOptions.MANAGEMENT_MODE_USER_NAME, _brokerOptions.getManagementModePassword()));
+ }
return true;
}
else if (desiredState == State.STOPPED)
@@ -865,6 +905,10 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
{
childDeleted = deleteAuthenticationProvider((AuthenticationProvider)object);
}
+ else if(object instanceof AccessControlProvider)
+ {
+ childDeleted = deleteAccessControlProvider((AccessControlProvider)object);
+ }
else if(object instanceof Port)
{
childDeleted = deletePort((Port)object);
@@ -885,6 +929,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
{
childDeleted = deleteTrustStore((TrustStore)object);
}
+
if(childDeleted)
{
childRemoved(object);
@@ -938,6 +983,10 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
{
addAuthenticationProvider((AuthenticationProvider)object);
}
+ else if(object instanceof AccessControlProvider)
+ {
+ addAccessControlProvider((AccessControlProvider)object);
+ }
else if(object instanceof Port)
{
addPort((Port)object);
@@ -996,7 +1045,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
public SubjectCreator getSubjectCreator(SocketAddress localAddress)
{
InetSocketAddress inetSocketAddress = (InetSocketAddress)localAddress;
- AuthenticationProvider provider = _defaultAuthenticationProvider;
+ AuthenticationProvider provider = null;
Collection<Port> ports = getPorts();
for (Port p : ports)
{
@@ -1006,6 +1055,12 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
break;
}
}
+
+ if(provider == null)
+ {
+ throw new IllegalConfigurationException("Unable to determine authentication provider for address: " + localAddress);
+ }
+
return provider.getSubjectCreator();
}
@@ -1034,18 +1089,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
}
@Override
- public KeyStore getDefaultKeyStore()
- {
- return _keyStores.get(_defaultKeyStoreId);
- }
-
- @Override
- public TrustStore getDefaultTrustStore()
- {
- return _trustStores.get(_defaultTrustStoreId);
- }
-
- @Override
public TaskExecutor getTaskExecutor()
{
return super.getTaskExecutor();
@@ -1054,13 +1097,9 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
@Override
protected void changeAttributes(Map<String, Object> attributes)
{
- //TODO: Add management mode check
Map<String, Object> convertedAttributes = MapValueConverter.convert(attributes, ATTRIBUTE_TYPES);
validateAttributes(convertedAttributes);
- boolean keyStoreChanged = false;
- boolean trustStoreChanged = false;
- boolean peerStoreChanged = false;
Collection<String> names = AVAILABLE_ATTRIBUTES;
for (String name : names)
{
@@ -1070,74 +1109,14 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
Object expected = getAttribute(name);
if (changeAttribute(name, expected, desired))
{
- if (GROUP_FILE.equals(name))
- {
- createGroupProvider();
- }
- else if (DEFAULT_AUTHENTICATION_PROVIDER.equals(name))
- {
- if (!_defaultAuthenticationProvider.getName().equals(desired))
- {
- _defaultAuthenticationProvider = findAuthenticationProviderByName((String)desired);
- }
- }
- else if (KEY_STORE_PATH.equals(name) || KEY_STORE_PASSWORD.equals(name) || KEY_STORE_CERT_ALIAS.equals(name))
- {
- keyStoreChanged = true;
- }
- else if (TRUST_STORE_PATH.equals(name) || TRUST_STORE_PASSWORD.equals(name))
- {
- trustStoreChanged = true;
- }
- else if (PEER_STORE_PATH.equals(name) || PEER_STORE_PASSWORD.equals(name))
- {
- peerStoreChanged = true;
- }
attributeSet(name, expected, desired);
}
}
}
- if (keyStoreChanged)
- {
- createKeyStore();
- }
- if (trustStoreChanged)
- {
- createTrustStore();
- }
- if (peerStoreChanged)
- {
- createPeerStore();
- }
}
private void validateAttributes(Map<String, Object> convertedAttributes)
{
- String aclFile = (String) convertedAttributes.get(ACL_FILE);
- if (aclFile != null)
- {
- // create a security manager to validate the ACL specified in file
- new SecurityManager(aclFile);
- }
- String groupFile = (String) convertedAttributes.get(GROUP_FILE);
- if (groupFile != null)
- {
- // create a group manager to validate the groups specified in file
- new FileGroupManager(groupFile);
- }
- validateKeyStoreAttributes(convertedAttributes, "key store", KEY_STORE_PATH, KEY_STORE_PASSWORD, KEY_STORE_CERT_ALIAS);
- validateKeyStoreAttributes(convertedAttributes, "trust store", TRUST_STORE_PATH, TRUST_STORE_PASSWORD, null);
- validateKeyStoreAttributes(convertedAttributes, "peer store", PEER_STORE_PATH, PEER_STORE_PASSWORD, null);
- String defaultAuthenticationProvider = (String) convertedAttributes.get(DEFAULT_AUTHENTICATION_PROVIDER);
- if (defaultAuthenticationProvider != null)
- {
- AuthenticationProvider provider = findAuthenticationProviderByName(defaultAuthenticationProvider);
- if (provider == null)
- {
- throw new IllegalConfigurationException("Authentication provider with name " + defaultAuthenticationProvider
- + " canot be set as a default as it does not exist");
- }
- }
String defaultVirtualHost = (String) convertedAttributes.get(DEFAULT_VIRTUAL_HOST);
if (defaultVirtualHost != null)
{
@@ -1176,59 +1155,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
}
}
- private void validateKeyStoreAttributes(Map<String, Object> convertedAttributes, String type, String pathAttribute,
- String passwordAttribute, String aliasAttribute)
- {
- String keyStoreFile = (String) convertedAttributes.get(pathAttribute);
- String password = (String) convertedAttributes.get(passwordAttribute);
- String alias = aliasAttribute!= null? (String) convertedAttributes.get(aliasAttribute) : null;
- if (keyStoreFile != null || password != null || alias != null)
- {
- if (keyStoreFile == null)
- {
- keyStoreFile = (String) getActualAttributes().get(pathAttribute);
- }
- if (password == null)
- {
- password = (String) getActualAttributes().get(passwordAttribute);
- }
- java.security.KeyStore keyStore = null;
- try
- {
- keyStore = SSLUtil.getInitializedKeyStore(keyStoreFile, password, java.security.KeyStore.getDefaultType());
- }
- catch (Exception e)
- {
- throw new IllegalConfigurationException("Cannot instantiate " + type + " at " + keyStoreFile, e);
- }
- if (aliasAttribute != null)
- {
- if (alias == null)
- {
- alias = (String) getActualAttributes().get(aliasAttribute);
- }
- if (alias != null)
- {
- Certificate cert = null;
- try
- {
- cert = keyStore.getCertificate(alias);
- }
- catch (KeyStoreException e)
- {
- // key store should be initialized above
- throw new RuntimeException("Key store has not been initialized", e);
- }
- if (cert == null)
- {
- throw new IllegalConfigurationException("Cannot find a certificate with alias " + alias + "in " + type
- + " : " + keyStoreFile);
- }
- }
- }
- }
- }
-
@Override
protected void authoriseSetAttribute(String name, Object expected, Object desired) throws AccessControlException
{
@@ -1260,6 +1186,15 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
@Override
public boolean isManagementMode()
{
- return _managementMode;
+ return _brokerOptions.isManagementMode();
+ }
+
+ @Override
+ public Collection<AccessControlProvider> getAccessControlProviders()
+ {
+ synchronized (_accessControlProviders)
+ {
+ return new ArrayList<AccessControlProvider>(_accessControlProviders.values());
+ }
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java
index 9ad58f9670..a0e5bdb0e8 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java
@@ -24,6 +24,7 @@ import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@@ -48,9 +49,11 @@ public class GroupProviderAdapter extends AbstractAdapter implements
{
private final GroupManager _groupManager;
private final Broker _broker;
- public GroupProviderAdapter(UUID id, GroupManager groupManager, Broker broker)
+ private Collection<String> _supportedAttributes;
+
+ public GroupProviderAdapter(UUID id, Broker broker, GroupManager groupManager, Map<String, Object> attributes, Collection<String> attributeNames)
{
- super(id, broker.getTaskExecutor());
+ super(id, null, null, broker.getTaskExecutor());
if (groupManager == null)
{
@@ -58,13 +61,37 @@ public class GroupProviderAdapter extends AbstractAdapter implements
}
_groupManager = groupManager;
_broker = broker;
+ _supportedAttributes = createSupportedAttributes(attributeNames);
addParent(Broker.class, broker);
+
+ // set attributes now after all attribute names are known
+ if (attributes != null)
+ {
+ for (String name : _supportedAttributes)
+ {
+ if (attributes.containsKey(name))
+ {
+ changeAttribute(name, null, attributes.get(name));
+ }
+ }
+ }
+ }
+
+ protected Collection<String> createSupportedAttributes(Collection<String> factoryAttributes)
+ {
+ List<String> attributesNames = new ArrayList<String>(AVAILABLE_ATTRIBUTES);
+ if (factoryAttributes != null)
+ {
+ attributesNames.addAll(factoryAttributes);
+ }
+
+ return Collections.unmodifiableCollection(attributesNames);
}
@Override
public String getName()
{
- return _groupManager.getClass().getSimpleName();
+ return (String)getAttribute(NAME);
}
@Override
@@ -129,17 +156,13 @@ public class GroupProviderAdapter extends AbstractAdapter implements
@Override
public Collection<String> getAttributeNames()
{
- return GroupProvider.AVAILABLE_ATTRIBUTES;
+ return _supportedAttributes;
}
@Override
public Object getAttribute(String name)
{
- if (TYPE.equals(name))
- {
- return getName();
- }
- else if (CREATED.equals(name))
+ if (CREATED.equals(name))
{
// TODO
}
@@ -155,10 +178,6 @@ public class GroupProviderAdapter extends AbstractAdapter implements
{
return LifetimePolicy.PERMANENT;
}
- else if (NAME.equals(name))
- {
- return getName();
- }
else if (STATE.equals(name))
{
return State.ACTIVE; // TODO
@@ -220,11 +239,91 @@ public class GroupProviderAdapter extends AbstractAdapter implements
}
}
+ public GroupManager getGroupManager()
+ {
+ return _groupManager;
+ }
+
private SecurityManager getSecurityManager()
{
return _broker.getSecurityManager();
}
+ @Override
+ protected boolean setState(State currentState, State desiredState)
+ {
+ if (desiredState == State.ACTIVE)
+ {
+ _groupManager.open();
+ return true;
+ }
+ else if (desiredState == State.STOPPED)
+ {
+ _groupManager.close();
+ return true;
+ }
+ else if (desiredState == State.DELETED)
+ {
+ _groupManager.close();
+ _groupManager.onDelete();
+ return true;
+ }
+ return false;
+ }
+
+ public Set<Principal> getGroupPrincipalsForUser(String username)
+ {
+ return _groupManager.getGroupPrincipalsForUser(username);
+ }
+
+ @Override
+ protected void childAdded(ConfiguredObject child)
+ {
+ // no-op, prevent storing groups in the broker store
+ }
+
+ @Override
+ protected void childRemoved(ConfiguredObject child)
+ {
+ // no-op, as per above, groups are not in the store
+ }
+
+ @Override
+ protected void authoriseSetDesiredState(State currentState, State desiredState) throws AccessControlException
+ {
+ if(desiredState == State.DELETED)
+ {
+ if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), GroupProvider.class, Operation.DELETE))
+ {
+ throw new AccessControlException("Deletion of groups provider is denied");
+ }
+ }
+ }
+
+ @Override
+ protected void authoriseSetAttribute(String name, Object expected, Object desired) throws AccessControlException
+ {
+ if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), GroupProvider.class, Operation.UPDATE))
+ {
+ throw new AccessControlException("Setting of group provider attributes is denied");
+ }
+ }
+
+ @Override
+ protected void authoriseSetAttributes(Map<String, Object> attributes) throws AccessControlException
+ {
+ if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), GroupProvider.class, Operation.UPDATE))
+ {
+ throw new AccessControlException("Setting of group provider attributes is denied");
+ }
+ }
+
+ @Override
+ protected void changeAttributes(Map<String, Object> attributes)
+ {
+ throw new UnsupportedOperationException("Changing attributes on group providers is not supported.");
+ }
+
private class GroupAdapter extends AbstractAdapter implements Group
{
private final String _group;
@@ -526,23 +625,5 @@ public class GroupProviderAdapter extends AbstractAdapter implements
}
}
- @Override
- protected boolean setState(State currentState, State desiredState)
- {
- if (desiredState == State.ACTIVE)
- {
- return true;
- }
- else if (desiredState == State.STOPPED)
- {
- return true;
- }
- // TODO: DELETE state is ignored for now
- return false;
- }
- public Set<Principal> getGroupPrincipalsForUser(String username)
- {
- return _groupManager.getGroupPrincipalsForUser(username);
- }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderFactory.java
new file mode 100644
index 0000000000..1d3ccd81b3
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderFactory.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.model.adapter;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.GroupProvider;
+import org.apache.qpid.server.plugin.GroupManagerFactory;
+import org.apache.qpid.server.plugin.QpidServiceLoader;
+import org.apache.qpid.server.security.group.GroupManager;
+
+public class GroupProviderFactory
+{
+ private final Map<String, GroupManagerFactory> _factories;
+ private Collection<String> _supportedGroupProviders;
+
+ public GroupProviderFactory(QpidServiceLoader<GroupManagerFactory> groupManagerFactoryServiceLoader)
+ {
+ Iterable<GroupManagerFactory> factories = groupManagerFactoryServiceLoader.instancesOf(GroupManagerFactory.class);
+
+ Map<String, GroupManagerFactory> registeredGroupProviderFactories = new HashMap<String, GroupManagerFactory>();
+ for (GroupManagerFactory factory : factories)
+ {
+ GroupManagerFactory existingFactory = registeredGroupProviderFactories.put(factory.getType(), factory);
+ if (existingFactory != null)
+ {
+ throw new IllegalConfigurationException("Group provider factory of the same type '" + factory.getType()
+ + "' is already registered using class '" + existingFactory.getClass().getName()
+ + "', can not register class '" + factory.getClass().getName() + "'");
+ }
+ }
+ _factories = registeredGroupProviderFactories;
+ _supportedGroupProviders = Collections.unmodifiableCollection(registeredGroupProviderFactories.keySet());
+ }
+
+ /**
+ * Creates {@link GroupProvider} for given ID, {@link Broker} and attributes.
+ * <p>
+ * The configured {@link GroupManagerFactory}'s are used to try to create the {@link GroupProvider}. The first non-null
+ * instance is returned. The factories are used in non-deterministic order.
+ */
+ public GroupProvider create(UUID id, Broker broker, Map<String, Object> attributes)
+ {
+ GroupProviderAdapter authenticationProvider = createGroupProvider(id, broker, attributes);
+ authenticationProvider.getGroupManager().onCreate();
+ return authenticationProvider;
+ }
+
+ /**
+ * Recovers {@link GroupProvider} with given ID, {@link Broker} and attributes.
+ * <p>
+ * The configured {@link GroupManagerFactory}'s are used to try to create the {@link GroupProvider}. The first non-null
+ * instance is returned. The factories are used in non-deterministic order.
+ */
+ public GroupProvider recover(UUID id, Broker broker, Map<String, Object> attributes)
+ {
+ return createGroupProvider(id, broker, attributes);
+ }
+
+ public Collection<String> getSupportedGroupProviders()
+ {
+ return _supportedGroupProviders;
+ }
+
+ private GroupProviderAdapter createGroupProvider(UUID id, Broker broker, Map<String, Object> attributes)
+ {
+ for (GroupManagerFactory factory : _factories.values())
+ {
+ GroupManager manager = factory.createInstance(attributes);
+ if (manager != null)
+ {
+ verifyGroupManager(manager, broker);
+ return new GroupProviderAdapter(id, broker, manager, attributes,factory.getAttributeNames());
+ }
+ }
+ throw new IllegalConfigurationException("No group provider factory found for configuration attributes " + attributes);
+ }
+
+ private void verifyGroupManager(GroupManager manager, Broker broker)
+ {
+ Collection<GroupProvider> groupProviders = broker.getGroupProviders();
+ for (GroupProvider groupProvider : groupProviders)
+ {
+ if (groupProvider instanceof GroupProviderAdapter)
+ {
+ GroupManager providerManager = ((GroupProviderAdapter) groupProvider).getGroupManager();
+ if (manager.equals(providerManager))
+ {
+ throw new IllegalConfigurationException("A group provider with the same settings already exists");
+ }
+ }
+ }
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java
index 113d895e62..4d4d3bb31d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java
@@ -20,23 +20,63 @@
*/
package org.apache.qpid.server.model.adapter;
+import java.lang.reflect.Type;
+import java.security.AccessControlException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
+import javax.net.ssl.KeyManagerFactory;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.IntegrityViolationException;
import org.apache.qpid.server.model.KeyStore;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.util.MapValueConverter;
+import org.apache.qpid.transport.network.security.ssl.SSLUtil;
public class KeyStoreAdapter extends AbstractKeyStoreAdapter implements KeyStore
{
+ @SuppressWarnings("serial")
+ public static final Map<String, Type> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Type>(){{
+ put(NAME, String.class);
+ put(PATH, String.class);
+ put(PASSWORD, String.class);
+ put(TYPE, String.class);
+ put(CERTIFICATE_ALIAS, String.class);
+ put(KEY_MANAGER_FACTORY_ALGORITHM, String.class);
+ }});
+
+ @SuppressWarnings("serial")
+ public static final Map<String, Object> DEFAULTS = Collections.unmodifiableMap(new HashMap<String, Object>(){{
+ put(KeyStore.TYPE, DEFAULT_KEYSTORE_TYPE);
+ put(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM, KeyManagerFactory.getDefaultAlgorithm());
+ }});
+
+ private Broker _broker;
public KeyStoreAdapter(UUID id, Broker broker, Map<String, Object> attributes)
{
- super(id, broker, attributes);
- if (attributes.get(CERTIFICATE_ALIAS) != null)
- {
- changeAttribute(CERTIFICATE_ALIAS, null, attributes.get(CERTIFICATE_ALIAS));
- }
+ super(id, broker, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES));
+ _broker = broker;
+
+ String keyStorePath = (String)getAttribute(KeyStore.PATH);
+ String keyStorePassword = getPassword();
+ String keyStoreType = (String)getAttribute(KeyStore.TYPE);
+ String keyManagerFactoryAlgorithm = (String)getAttribute(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM);
+ String certAlias = (String)getAttribute(KeyStore.CERTIFICATE_ALIAS);
+
+ validateKeyStoreAttributes(keyStoreType, keyStorePath, keyStorePassword,
+ certAlias, keyManagerFactoryAlgorithm);
}
@Override
@@ -45,4 +85,129 @@ public class KeyStoreAdapter extends AbstractKeyStoreAdapter implements KeyStore
return AVAILABLE_ATTRIBUTES;
}
+ @Override
+ protected boolean setState(State currentState, State desiredState)
+ {
+ if(desiredState == State.DELETED)
+ {
+ // verify that it is not in use
+ String storeName = getName();
+
+ Collection<Port> ports = new ArrayList<Port>(_broker.getPorts());
+ for (Port port : ports)
+ {
+ if (storeName.equals(port.getAttribute(Port.KEY_STORE)))
+ {
+ throw new IntegrityViolationException("Key store '" + storeName + "' can't be deleted as it is in use by a port:" + port.getName());
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ protected void authoriseSetDesiredState(State currentState, State desiredState) throws AccessControlException
+ {
+ if(desiredState == State.DELETED)
+ {
+ if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), KeyStore.class, Operation.DELETE))
+ {
+ throw new AccessControlException("Deletion of key store is denied");
+ }
+ }
+ }
+
+ @Override
+ protected void authoriseSetAttribute(String name, Object expected, Object desired) throws AccessControlException
+ {
+ authoriseSetAttribute();
+ }
+
+ @Override
+ protected void authoriseSetAttributes(Map<String, Object> attributes) throws AccessControlException
+ {
+ authoriseSetAttribute();
+ }
+
+ private void authoriseSetAttribute()
+ {
+ if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), KeyStore.class, Operation.UPDATE))
+ {
+ throw new AccessControlException("Setting key store attributes is denied");
+ }
+ }
+
+ @Override
+ protected void changeAttributes(Map<String, Object> attributes)
+ {
+ Map<String, Object> changedValues = MapValueConverter.convert(attributes, ATTRIBUTE_TYPES);
+ if(changedValues.containsKey(KeyStore.NAME))
+ {
+ String newName = (String) changedValues.get(KeyStore.NAME);
+ if(!getName().equals(newName))
+ {
+ throw new IllegalConfigurationException("Changing the key store name is not allowed");
+ }
+ }
+
+ Map<String, Object> merged = generateEffectiveAttributes(changedValues);
+
+ String keyStorePath = (String)merged.get(KeyStore.PATH);
+ String keyStorePassword = (String) merged.get(KeyStore.PASSWORD);
+ String keyStoreType = (String)merged.get(KeyStore.TYPE);
+ String keyManagerFactoryAlgorithm = (String)merged.get(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM);
+ String certAlias = (String)merged.get(KeyStore.CERTIFICATE_ALIAS);
+
+ validateKeyStoreAttributes(keyStoreType, keyStorePath, keyStorePassword,
+ certAlias, keyManagerFactoryAlgorithm);
+
+ super.changeAttributes(changedValues);
+ }
+
+ private void validateKeyStoreAttributes(String type, String keyStorePath,
+ String keyStorePassword, String alias,
+ String keyManagerFactoryAlgorithm)
+ {
+ java.security.KeyStore keyStore = null;
+ try
+ {
+ keyStore = SSLUtil.getInitializedKeyStore(keyStorePath, keyStorePassword, type);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalConfigurationException("Cannot instantiate key store at " + keyStorePath, e);
+ }
+
+ if (alias != null)
+ {
+ Certificate cert = null;
+ try
+ {
+ cert = keyStore.getCertificate(alias);
+ }
+ catch (KeyStoreException e)
+ {
+ // key store should be initialized above
+ throw new RuntimeException("Key store has not been initialized", e);
+ }
+ if (cert == null)
+ {
+ throw new IllegalConfigurationException("Cannot find a certificate with alias " + alias
+ + "in key store : " + keyStorePath);
+ }
+ }
+
+ try
+ {
+ KeyManagerFactory.getInstance(keyManagerFactoryAlgorithm);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new IllegalConfigurationException("Unknown keyManagerFactoryAlgorithm: "
+ + keyManagerFactoryAlgorithm);
+ }
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
index 4250de17a7..af6b1421a7 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
@@ -37,12 +37,14 @@ import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.KeyStore;
import org.apache.qpid.server.model.LifetimePolicy;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Protocol;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.Statistics;
import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.model.VirtualHostAlias;
import org.apache.qpid.server.security.access.Operation;
@@ -58,6 +60,8 @@ public class PortAdapter extends AbstractAdapter implements Port
put(NAME, String.class);
put(PROTOCOLS, new ParameterizedTypeImpl(Set.class, Protocol.class));
put(TRANSPORTS, new ParameterizedTypeImpl(Set.class, Transport.class));
+ put(TRUST_STORES, new ParameterizedTypeImpl(Set.class, String.class));
+ put(KEY_STORE, String.class);
put(PORT, Integer.class);
put(TCP_NO_DELAY, Boolean.class);
put(RECEIVE_BUFFER_SIZE, Integer.class);
@@ -78,6 +82,24 @@ public class PortAdapter extends AbstractAdapter implements Port
super(id, defaults, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor);
_broker = broker;
State state = MapValueConverter.getEnumAttribute(State.class, STATE, attributes, State.INITIALISING);
+
+ Collection<Protocol> protocols = getProtocols();
+ boolean rmiRegistry = protocols != null && protocols.contains(Protocol.RMI);
+ if (!rmiRegistry)
+ {
+ String authProvider = (String)getAttribute(Port.AUTHENTICATION_PROVIDER);
+ if (authProvider == null)
+ {
+ throw new IllegalConfigurationException("An authentication provider must be specified for port : " + getName());
+ }
+ _authenticationProvider = broker.findAuthenticationProviderByName(authProvider);
+
+ if(_authenticationProvider == null)
+ {
+ throw new IllegalConfigurationException("The authentication provider '" + authProvider + "' could not be found for port : " + getName());
+ }
+ }
+
_state = new AtomicReference<State>(state);
addParent(Broker.class, broker);
}
@@ -346,11 +368,6 @@ public class PortAdapter extends AbstractAdapter implements Port
return _authenticationProvider;
}
- public void setAuthenticationProvider(AuthenticationProvider authenticationProvider)
- {
- _authenticationProvider = authenticationProvider;
- }
-
@Override
protected void changeAttributes(Map<String, Object> attributes)
{
@@ -373,16 +390,40 @@ public class PortAdapter extends AbstractAdapter implements Port
boolean requiresCertificate = (needClientCertificate != null && needClientCertificate.booleanValue())
|| (wantClientCertificate != null && wantClientCertificate.booleanValue());
- if (transports != null && transports.contains(Transport.SSL))
+ String keyStoreName = (String) merged.get(KEY_STORE);
+ boolean hasKeyStore = keyStoreName != null;
+ if(keyStoreName != null)
{
- if (_broker.getKeyStores().isEmpty())
+ if (_broker.findKeyStoreByName(keyStoreName) == null)
{
- throw new IllegalConfigurationException("Can't create port which requires SSL as the broker has no keystore configured.");
+ throw new IllegalConfigurationException("Can't find key store with name '" + keyStoreName + "' for port " + getName());
}
+ }
- if (_broker.getTrustStores().isEmpty() && requiresCertificate)
+ Set<String> trustStoreNames = (Set<String>) merged.get(TRUST_STORES);
+ boolean hasTrustStore = trustStoreNames != null && !trustStoreNames.isEmpty();
+ if(hasTrustStore)
+ {
+ for (String trustStoreName : trustStoreNames)
{
- throw new IllegalConfigurationException("Can't create port which requests SSL client certificates as the broker has no trust/peer stores configured.");
+ if (_broker.findTrustStoreByName(trustStoreName) == null)
+ {
+ throw new IllegalConfigurationException("Cannot find trust store with name '" + trustStoreName + "'");
+ }
+ }
+ }
+
+ boolean usesSsl = transports != null && transports.contains(Transport.SSL);
+ if (usesSsl)
+ {
+ if (keyStoreName == null)
+ {
+ throw new IllegalConfigurationException("Can't create port which requires SSL but has no key store configured.");
+ }
+
+ if (!hasTrustStore && requiresCertificate)
+ {
+ throw new IllegalConfigurationException("Can't create port which requests SSL client certificates but has no trust store configured.");
}
}
else
@@ -393,9 +434,14 @@ public class PortAdapter extends AbstractAdapter implements Port
}
}
- if (protocols != null && protocols.contains(Protocol.HTTPS) && _broker.getKeyStores().isEmpty())
+ if (protocols != null && protocols.contains(Protocol.HTTPS) && !hasKeyStore)
+ {
+ throw new IllegalConfigurationException("Can't create port which requires SSL but has no key store configured.");
+ }
+
+ if (protocols != null && protocols.contains(Protocol.RMI) && usesSsl)
{
- throw new IllegalConfigurationException("Can't create port which requires SSL as the broker has no keystore configured.");
+ throw new IllegalConfigurationException("Can't create RMI Registry port which requires SSL.");
}
String authenticationProviderName = (String)merged.get(AUTHENTICATION_PROVIDER);
@@ -418,6 +464,14 @@ public class PortAdapter extends AbstractAdapter implements Port
+ authenticationProviderName + "'");
}
}
+ else
+ {
+ if (protocols != null && !protocols.contains(Protocol.RMI))
+ {
+ throw new IllegalConfigurationException("An authentication provider must be specified");
+ }
+ }
+
super.changeAttributes(converted);
}
@@ -450,4 +504,42 @@ public class PortAdapter extends AbstractAdapter implements Port
throw new AccessControlException("Setting of port attributes is denied");
}
}
+
+ @Override
+ public KeyStore getKeyStore()
+ {
+ String keyStoreName = (String)getAttribute(Port.KEY_STORE);
+ KeyStore keyStore = _broker.findKeyStoreByName(keyStoreName);
+
+ if (keyStoreName != null && keyStore == null)
+ {
+ throw new IllegalConfigurationException("Can't find key store with name '" + keyStoreName + "' for port " + getName());
+ }
+
+ return keyStore;
+ }
+
+ @Override
+ public Collection<TrustStore> getTrustStores()
+ {
+ Set<String> trustStoreNames = (Set<String>) getAttribute(TRUST_STORES);
+ boolean hasTrustStoreName = trustStoreNames != null && !trustStoreNames.isEmpty();
+
+ final Collection<TrustStore> trustStores = new ArrayList<TrustStore>();
+ if(hasTrustStoreName)
+ {
+ for (String name : trustStoreNames)
+ {
+ TrustStore trustStore = _broker.findTrustStoreByName(name);
+ if (trustStore == null)
+ {
+ throw new IllegalConfigurationException("Can't find trust store with name '" + name + "' for port " + getName());
+ }
+
+ trustStores.add(trustStore);
+ }
+ }
+
+ return trustStores;
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java
index ffbd24997a..2efe189d73 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java
@@ -106,9 +106,9 @@ public class PortFactory
port = new AmqpPortAdapter(id, broker, attributes, defaults, broker.getTaskExecutor());
boolean useClientAuth = (Boolean) port.getAttribute(Port.NEED_CLIENT_AUTH) || (Boolean) port.getAttribute(Port.WANT_CLIENT_AUTH);
- if(useClientAuth && broker.getTrustStores().isEmpty())
+ if(useClientAuth && port.getTrustStores().isEmpty())
{
- throw new IllegalConfigurationException("Can't create port which requests SSL client certificates as the broker has no trust/peer stores configured.");
+ throw new IllegalConfigurationException("Can't create port which requests SSL client certificates but has no trust stores configured.");
}
if(useClientAuth && !port.getTransports().contains(Transport.SSL))
@@ -142,13 +142,19 @@ public class PortFactory
defaults.put(Port.NAME, portValue + "-" + protocol.name());
port = new PortAdapter(id, broker, attributes, defaults, broker.getTaskExecutor());
+
+ boolean rmiPort = port.getProtocols().contains(Protocol.RMI);
+ if (rmiPort && port.getTransports().contains(Transport.SSL))
+ {
+ throw new IllegalConfigurationException("Can't create RMI registry port which requires SSL");
+ }
}
if(port.getTransports().contains(Transport.SSL) || port.getProtocols().contains(Protocol.HTTPS))
{
- if(broker.getKeyStores().isEmpty())
+ if(port.getKeyStore() == null)
{
- throw new IllegalConfigurationException("Can't create port which requires SSL as the broker has no keystore configured.");
+ throw new IllegalConfigurationException("Can't create port which requires SSL but has no key store configured.");
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java
index bdffe605ec..06089e43c6 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java
@@ -20,18 +20,61 @@
*/
package org.apache.qpid.server.model.adapter;
+import java.lang.reflect.Type;
+import java.security.AccessControlException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
+import javax.net.ssl.TrustManagerFactory;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.IntegrityViolationException;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.TrustStore;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.util.MapValueConverter;
+import org.apache.qpid.transport.network.security.ssl.SSLUtil;
public class TrustStoreAdapter extends AbstractKeyStoreAdapter implements TrustStore
{
+ @SuppressWarnings("serial")
+ public static final Map<String, Type> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Type>(){{
+ put(NAME, String.class);
+ put(PATH, String.class);
+ put(PASSWORD, String.class);
+ put(TYPE, String.class);
+ put(PEERS_ONLY, Boolean.class);
+ put(TRUST_MANAGER_FACTORY_ALGORITHM, String.class);
+ }});
+
+ @SuppressWarnings("serial")
+ public static final Map<String, Object> DEFAULTS = Collections.unmodifiableMap(new HashMap<String, Object>(){{
+ put(TrustStore.TYPE, DEFAULT_KEYSTORE_TYPE);
+ put(TrustStore.PEERS_ONLY, Boolean.FALSE);
+ put(TrustStore.TRUST_MANAGER_FACTORY_ALGORITHM, TrustManagerFactory.getDefaultAlgorithm());
+ }});
+
+ private Broker _broker;
+
public TrustStoreAdapter(UUID id, Broker broker, Map<String, Object> attributes)
{
- super(id, broker, attributes);
+ super(id, broker, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES));
+ _broker = broker;
+
+ String trustStorePath = (String) getAttribute(TrustStore.PATH);
+ String trustStorePassword = getPassword();
+ String trustStoreType = (String) getAttribute(TrustStore.TYPE);
+ String trustManagerFactoryAlgorithm = (String) getAttribute(TrustStore.TRUST_MANAGER_FACTORY_ALGORITHM);
+
+ validateTrustStoreAttributes(trustStoreType, trustStorePath,
+ trustStorePassword, trustManagerFactoryAlgorithm);
}
@Override
@@ -40,4 +83,110 @@ public class TrustStoreAdapter extends AbstractKeyStoreAdapter implements TrustS
return AVAILABLE_ATTRIBUTES;
}
+ @Override
+ protected boolean setState(State currentState, State desiredState)
+ {
+ if(desiredState == State.DELETED)
+ {
+ // verify that it is not in use
+ String storeName = getName();
+
+ Collection<Port> ports = new ArrayList<Port>(_broker.getPorts());
+ for (Port port : ports)
+ {
+ Collection<TrustStore> trustStores = port.getTrustStores();
+ for(TrustStore store : trustStores)
+ {
+ if (storeName.equals(store.getAttribute(TrustStore.NAME)))
+ {
+ throw new IntegrityViolationException("Trust store '" + storeName + "' can't be deleted as it is in use by a port: " + port.getName());
+ }
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ protected void authoriseSetDesiredState(State currentState, State desiredState) throws AccessControlException
+ {
+ if(desiredState == State.DELETED)
+ {
+ if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), TrustStore.class, Operation.DELETE))
+ {
+ throw new AccessControlException("Deletion of key store is denied");
+ }
+ }
+ }
+
+ @Override
+ protected void authoriseSetAttribute(String name, Object expected, Object desired) throws AccessControlException
+ {
+ authoriseSetAttribute();
+ }
+
+ @Override
+ protected void authoriseSetAttributes(Map<String, Object> attributes) throws AccessControlException
+ {
+ authoriseSetAttribute();
+ }
+
+ private void authoriseSetAttribute()
+ {
+ if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), TrustStore.class, Operation.UPDATE))
+ {
+ throw new AccessControlException("Setting key store attributes is denied");
+ }
+ }
+
+ @Override
+ protected void changeAttributes(Map<String, Object> attributes)
+ {
+ Map<String, Object> changedValues = MapValueConverter.convert(attributes, ATTRIBUTE_TYPES);
+ if(changedValues.containsKey(TrustStore.NAME))
+ {
+ String newName = (String) changedValues.get(TrustStore.NAME);
+ if(!getName().equals(newName))
+ {
+ throw new IllegalConfigurationException("Changing the trust store name is not allowed");
+ }
+ }
+
+ Map<String, Object> merged = generateEffectiveAttributes(changedValues);
+
+ String trustStorePath = (String)merged.get(TrustStore.PATH);
+ String trustStorePassword = (String) merged.get(TrustStore.PASSWORD);
+ String trustStoreType = (String)merged.get(TrustStore.TYPE);
+ String trustManagerFactoryAlgorithm = (String)merged.get(TrustStore.TRUST_MANAGER_FACTORY_ALGORITHM);
+
+ validateTrustStoreAttributes(trustStoreType, trustStorePath,
+ trustStorePassword, trustManagerFactoryAlgorithm);
+
+ super.changeAttributes(changedValues);
+ }
+
+ private void validateTrustStoreAttributes(String type, String trustStorePath,
+ String password, String trustManagerFactoryAlgorithm)
+ {
+ try
+ {
+ SSLUtil.getInitializedKeyStore(trustStorePath, password, type);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalConfigurationException("Cannot instantiate trust store at " + trustStorePath, e);
+ }
+
+ try
+ {
+ TrustManagerFactory.getInstance(trustManagerFactoryAlgorithm);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new IllegalConfigurationException("Unknown trustManagerFactoryAlgorithm: " + trustManagerFactoryAlgorithm);
+ }
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/AccessControlFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/AccessControlFactory.java
index 7708b90efc..0694032db2 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/AccessControlFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/AccessControlFactory.java
@@ -18,11 +18,34 @@
*/
package org.apache.qpid.server.plugin;
+import java.util.Collection;
import java.util.Map;
+import org.apache.qpid.server.model.AccessControlProvider;
import org.apache.qpid.server.security.AccessControl;
public interface AccessControlFactory
{
+ public static final String ATTRIBUTE_TYPE = AccessControlProvider.TYPE;
+
AccessControl createInstance(Map<String, Object> attributes);
+
+ /**
+ * Returns the access control provider type
+ * @return authentication provider type
+ */
+ String getType();
+
+ /**
+ * Get the names of attributes of the access control which can be passed into
+ * {@link #createInstance(Map)} to create the group manager
+ *
+ * @return the collection of attribute names
+ */
+ Collection<String> getAttributeNames();
+
+ /**
+ * @return returns human readable descriptions for the attributes
+ */
+ Map<String, String> getAttributeDescriptions();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/ConfigurationStoreFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/ConfigurationStoreFactory.java
index a625579ece..c451ae2adc 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/ConfigurationStoreFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/ConfigurationStoreFactory.java
@@ -34,11 +34,12 @@ public interface ConfigurationStoreFactory
/**
* Creates and opens the store from a given location using initial store if provided.
* <p>
- * If location does not exists than a new store is created either empty or from the initial store if it is provided
+ * If location does not exist, or the overwrite option is specified, then a new store is created from the initial store if it is provided
*
* @param storeLocation store location
* @param initialStore initial store
+ * @param overwrite overwrite existing store with initial store
* @throws IllegalConfigurationException if store cannot be opened in the given location
*/
- public ConfigurationEntryStore createStore(String storeLocation, ConfigurationEntryStore initialStore);
+ public ConfigurationEntryStore createStore(String storeLocation, ConfigurationEntryStore initialStore, boolean overwrite);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.java
index 5d80ca24fd..2ab9701e2e 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.java
@@ -18,11 +18,34 @@
*/
package org.apache.qpid.server.plugin;
+import java.util.Collection;
import java.util.Map;
+import org.apache.qpid.server.model.GroupProvider;
import org.apache.qpid.server.security.group.GroupManager;
public interface GroupManagerFactory
{
+ public static final String ATTRIBUTE_TYPE = GroupProvider.TYPE;
+
GroupManager createInstance(Map<String, Object> attributes);
+
+ /**
+ * Returns the authentication provider type
+ * @return authentication provider type
+ */
+ String getType();
+
+ /**
+ * Get the names of attributes the group manager which can be passed into {@link #createInstance(Map)} to create the
+ * group manager
+ *
+ * @return the collection of attribute names
+ */
+ Collection<String> getAttributeNames();
+
+ /**
+ * @return returns human readable descriptions for the attributes
+ */
+ Map<String, String> getAttributeDescriptions();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0.java
index 96b1172a57..c2a3256ba6 100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0.java
@@ -22,6 +22,7 @@ package org.apache.qpid.server.protocol.v1_0;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
+import java.security.Principal;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -41,6 +42,7 @@ import org.apache.qpid.protocol.ServerProtocolEngine;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.protocol.v1_0.Connection_1_0;
import org.apache.qpid.server.security.SubjectCreator;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.Sender;
import org.apache.qpid.transport.network.NetworkConnection;
@@ -170,6 +172,12 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa
{
return subjectCreator.createSaslServer(mechanism, fqdn, null);
}
+
+ @Override
+ public Principal getAuthenticatedPrincipal(SaslServer server)
+ {
+ return new UsernamePrincipal(server.getAuthorizationID());
+ }
};
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java
index ec76d7e581..10ebb6e05e 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.protocol.v1_0;
import java.io.PrintWriter;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
+import java.security.Principal;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.sasl.SaslException;
@@ -42,6 +43,7 @@ import org.apache.qpid.protocol.ServerProtocolEngine;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.protocol.v1_0.Connection_1_0;
import org.apache.qpid.server.security.SubjectCreator;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.Sender;
import org.apache.qpid.transport.network.NetworkConnection;
@@ -162,7 +164,8 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut
Container container = new Container(_broker.getId().toString());
VirtualHost virtualHost = _broker.getVirtualHostRegistry().getVirtualHost((String)_broker.getAttribute(Broker.DEFAULT_VIRTUAL_HOST));
- _conn = new ConnectionEndpoint(container, asSaslServerProvider(_broker.getSubjectCreator(getLocalAddress())));
+ SubjectCreator subjectCreator = _broker.getSubjectCreator(getLocalAddress());
+ _conn = new ConnectionEndpoint(container, asSaslServerProvider(subjectCreator));
_conn.setRemoteAddress(getRemoteAddress());
_conn.setConnectionEventListener(new Connection_1_0(virtualHost, _conn, _connectionId));
_conn.setFrameOutputHandler(this);
@@ -189,7 +192,7 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut
_sender.send(HEADER.duplicate());
_sender.flush();
- _conn.initiateSASL();
+ _conn.initiateSASL(subjectCreator.getMechanisms().split(" "));
}
@@ -201,7 +204,13 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut
@Override
public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException
{
- return subjectCreator.createSaslServer(mechanism, fqdn, null);
+ return subjectCreator.createSaslServer(mechanism, fqdn, _network.getPeerPrincipal());
+ }
+
+ @Override
+ public Principal getAuthenticatedPrincipal(SaslServer server)
+ {
+ return new UsernamePrincipal(server.getAuthorizationID());
}
};
}
@@ -230,7 +239,7 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut
Binary bin = new Binary(data);
RAW_LOGGER.fine("RECV[" + getRemoteAddress() + "] : " + bin.toString());
}
- _readBytes += msg.remaining();
+ _readBytes += msg.remaining();
switch(_state)
{
case A:
@@ -392,7 +401,6 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut
RAW_LOGGER.fine("SEND[" + getRemoteAddress() + "] : " + bin.toString());
}
-
_sender.send(dup);
_sender.flush();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java
index 35b7cac1a1..cef7e2d0c8 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java
@@ -38,6 +38,7 @@ public interface BaseQueue extends TransactionLogResource
void enqueue(ServerMessage message, boolean transactional, PostEnqueueAction action) throws AMQException;
boolean isDurable();
+ boolean isDeleted();
AMQShortString getNameShortString();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
index 1379b375cf..fa5024c1fe 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
@@ -27,6 +27,7 @@ import java.util.TimerTask;
import org.apache.log4j.Logger;
import org.apache.qpid.common.Closeable;
import org.apache.qpid.common.QpidProperties;
+import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.configuration.BrokerProperties;
import org.apache.qpid.server.configuration.ConfigurationEntryStore;
import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer;
@@ -89,7 +90,7 @@ public class ApplicationRegistry implements IApplicationRegistry
initialiseStatistics();
}
- public void initialise() throws Exception
+ public void initialise(BrokerOptions brokerOptions) throws Exception
{
// Create the RootLogger to be used during broker operation
boolean statusUpdatesEnabled = Boolean.parseBoolean(System.getProperty(BrokerProperties.PROPERTY_STATUS_UPDATES, "true"));
@@ -112,7 +113,7 @@ public class ApplicationRegistry implements IApplicationRegistry
_taskExecutor = new TaskExecutor();
_taskExecutor.start();
- RecovererProvider provider = new DefaultRecovererProvider((StatisticsGatherer)this, _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor);
+ RecovererProvider provider = new DefaultRecovererProvider((StatisticsGatherer)this, _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor, brokerOptions);
ConfiguredObjectRecoverer<? extends ConfiguredObject> brokerRecoverer = provider.getRecoverer(Broker.class.getSimpleName());
_broker = (Broker) brokerRecoverer.create(provider, _store.getRootEntry());
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
index d12258d194..7341922bd0 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
@@ -20,17 +20,14 @@
*/
package org.apache.qpid.server.registry;
+import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.stats.StatisticsGatherer;
public interface IApplicationRegistry extends StatisticsGatherer
{
- /**
- * Initialise the application registry. All initialisation must be done in this method so that any components
- * that need access to the application registry itself for initialisation are able to use it. Attempting to
- * initialise in the constructor will lead to failures since the registry reference will not have been set.
- */
- void initialise() throws Exception;
+
+ void initialise(BrokerOptions brokerOptions) throws Exception;
/**
* Shutdown this Registry
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AccessControl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AccessControl.java
index b4831f83e5..61e928a38c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AccessControl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AccessControl.java
@@ -42,4 +42,25 @@ public interface AccessControl
* Authorise an operation on an object defined by a set of properties.
*/
Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties);
+
+ /**
+ * Called to open any resources required by the implementation.
+ */
+ void open();
+
+ /**
+ * Called to close any resources required by the implementation.
+ */
+ void close();
+
+ /**
+ * Called when deleting to allow clearing any resources used by the implementation.
+ */
+ void onDelete();
+
+ /**
+ * Called when first creating (but not when recovering after startup) to allow
+ * creating any resources required by the implementation.
+ */
+ void onCreate();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java
index 3fb3f70f2e..375b731d85 100755
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java
@@ -23,6 +23,7 @@ import org.apache.log4j.Logger;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.model.AccessControlProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
@@ -30,6 +31,7 @@ import org.apache.qpid.server.model.State;
import org.apache.qpid.server.plugin.AccessControlFactory;
import org.apache.qpid.server.plugin.QpidServiceLoader;
import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.security.access.FileAccessControlProviderConstants;
import org.apache.qpid.server.security.access.ObjectProperties;
import org.apache.qpid.server.security.access.ObjectType;
import org.apache.qpid.server.security.access.Operation;
@@ -53,22 +55,13 @@ import static org.apache.qpid.server.security.access.Operation.UNBIND;
import javax.security.auth.Subject;
import java.net.SocketAddress;
-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;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
-/**
- * The security manager contains references to all loaded {@link AccessControl}s and delegates security decisions to them based
- * on virtual host name. The plugins can be external <em>OSGi</em> .jar files that export the required classes or just internal
- * objects for simpler plugins.
- *
- * @see AccessControl
- */
public class SecurityManager implements ConfigurationChangeListener
{
private static final Logger _logger = Logger.getLogger(SecurityManager.class);
@@ -78,9 +71,12 @@ public class SecurityManager implements ConfigurationChangeListener
public static final ThreadLocal<Boolean> _accessChecksDisabled = new ClearingThreadLocal(false);
- private Map<String, AccessControl> _globalPlugins = new ConcurrentHashMap<String, AccessControl>();
- private Map<String, AccessControl> _hostPlugins = new ConcurrentHashMap<String, AccessControl>();
- private Map<String, List<String>> _aclConfigurationToPluginNamesMapping = new ConcurrentHashMap<String, List<String>>();
+ private ConcurrentHashMap<String, AccessControl> _globalPlugins = new ConcurrentHashMap<String, AccessControl>();
+ private ConcurrentHashMap<String, AccessControl> _hostPlugins = new ConcurrentHashMap<String, AccessControl>();
+
+ private boolean _managementMode;
+
+ private Broker _broker;
/**
* A special ThreadLocal, which calls remove() on itself whenever the value is
@@ -128,34 +124,53 @@ public class SecurityManager implements ConfigurationChangeListener
}
/*
- * Used by the VirtualHost to allow deferring to the broker level security plugins if required.
+ * Used by the Broker.
*/
- public SecurityManager(SecurityManager parent, String aclFile)
+ public SecurityManager(Broker broker, boolean managementMode)
{
- this(aclFile);
-
- // our global plugins are the parent's host plugins
- _globalPlugins = parent._hostPlugins;
+ _managementMode = managementMode;
+ _broker = broker;
}
- public SecurityManager(String aclFile)
+ /*
+ * Used by the VirtualHost to allow deferring to the broker level security plugins if required.
+ */
+ public SecurityManager(SecurityManager parent, String aclFile, String vhostName)
{
- configureACLPlugin(aclFile);
+ if(!_managementMode)
+ {
+ configureVirtualHostAclPlugin(aclFile, vhostName);
+
+ // our global plugins are the parent's host plugins
+ _globalPlugins = parent._hostPlugins;
+ }
}
- private void configureACLPlugin(String aclFile)
+ private void configureVirtualHostAclPlugin(String aclFile, String vhostName)
{
- Map<String, Object> attributes = new HashMap<String, Object>();
- attributes.put("aclFile", aclFile);
-
- for (AccessControlFactory provider : (new QpidServiceLoader<AccessControlFactory>()).instancesOf(AccessControlFactory.class))
+ if(aclFile != null)
{
- AccessControl accessControl = provider.createInstance(attributes);
- if(accessControl != null)
- {
- addHostPlugin(accessControl);
+ Map<String, Object> attributes = new HashMap<String, Object>();
- mapAclConfigurationToPluginName(aclFile, accessControl.getClass().getName());
+ attributes.put(AccessControlProvider.TYPE, FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE);
+ attributes.put(FileAccessControlProviderConstants.PATH, aclFile);
+
+ for (AccessControlFactory provider : (new QpidServiceLoader<AccessControlFactory>()).instancesOf(AccessControlFactory.class))
+ {
+ AccessControl accessControl = provider.createInstance(attributes);
+ accessControl.open();
+ if(accessControl != null)
+ {
+ String pluginTypeName = getPluginTypeName(accessControl);
+ _hostPlugins.put(pluginTypeName, accessControl);
+
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("Added access control to host plugins with name: " + vhostName);
+ }
+
+ break;
+ }
}
}
@@ -165,15 +180,9 @@ public class SecurityManager implements ConfigurationChangeListener
}
}
- private void mapAclConfigurationToPluginName(String aclFile, String pluginName)
+ private String getPluginTypeName(AccessControl accessControl)
{
- List<String> pluginNames = _aclConfigurationToPluginNamesMapping.get(aclFile);
- if (pluginNames == null)
- {
- pluginNames = new ArrayList<String>();
- _aclConfigurationToPluginNamesMapping.put(aclFile, pluginNames);
- }
- pluginNames.add(pluginName);
+ return accessControl.getClass().getName();
}
public static Subject getThreadSubject()
@@ -191,15 +200,6 @@ public class SecurityManager implements ConfigurationChangeListener
return _logger;
}
- private static class CachedPropertiesMap extends LinkedHashMap<String, PublishAccessCheck>
- {
- @Override
- protected boolean removeEldestEntry(Entry<String, PublishAccessCheck> eldest)
- {
- return size() >= 200;
- }
- }
-
private abstract class AccessCheck
{
abstract Result allowed(AccessControl plugin);
@@ -500,16 +500,72 @@ public class SecurityManager implements ConfigurationChangeListener
}
}
-
- public void addHostPlugin(AccessControl plugin)
- {
- _hostPlugins.put(plugin.getClass().getName(), plugin);
- }
-
@Override
public void stateChanged(ConfiguredObject object, State oldState, State newState)
{
- // no op
+ if(_managementMode)
+ {
+ //AccessControl is disabled in ManagementMode
+ return;
+ }
+
+ if(object instanceof AccessControlProvider)
+ {
+ if(newState == State.ACTIVE)
+ {
+ synchronized (_hostPlugins)
+ {
+ AccessControl accessControl = ((AccessControlProvider)object).getAccessControl();
+ String pluginTypeName = getPluginTypeName(accessControl);
+
+ _hostPlugins.put(pluginTypeName, accessControl);
+ }
+ }
+ else if(newState == State.DELETED)
+ {
+ synchronized (_hostPlugins)
+ {
+ AccessControl control = ((AccessControlProvider)object).getAccessControl();
+ String pluginTypeName = getPluginTypeName(control);
+
+ // Remove the type->control mapping for this type key only if the
+ // given control is actually referred to.
+ if(_hostPlugins.containsValue(control))
+ {
+ // If we are removing this control, check if another of the same
+ // type already exists on the broker and use it in instead.
+ AccessControl other = null;
+ Collection<AccessControlProvider> providers = _broker.getAccessControlProviders();
+ for(AccessControlProvider p : providers)
+ {
+ if(p == object || p.getActualState() != State.ACTIVE)
+ {
+ //we don't count ourself as another
+ continue;
+ }
+
+ AccessControl ac = p.getAccessControl();
+ if(pluginTypeName.equals(getPluginTypeName(ac)))
+ {
+ other = ac;
+ break;
+ }
+ }
+
+ if(other != null)
+ {
+ //Another control of this type was found, use it instead
+ _hostPlugins.replace(pluginTypeName, control, other);
+ }
+ else
+ {
+ //No other was found, remove the type entirely
+ _hostPlugins.remove(pluginTypeName);
+ }
+ }
+ }
+ }
+ }
}
@Override
@@ -527,29 +583,7 @@ public class SecurityManager implements ConfigurationChangeListener
@Override
public void attributeSet(ConfiguredObject object, String attributeName, Object oldAttributeValue, Object newAttributeValue)
{
- if (object instanceof Broker && Broker.ACL_FILE.equals(attributeName))
- {
- // the code below is not thread safe, however, it should be fine in a management mode
- // as there will be no user connected
-
- if (oldAttributeValue != null)
- {
- List<String> pluginNames = _aclConfigurationToPluginNamesMapping.remove(oldAttributeValue);
- if (pluginNames != null)
- {
- for (String name : pluginNames)
- {
- _hostPlugins.remove(name);
- }
- }
- }
- if (newAttributeValue != null)
- {
- configureACLPlugin((String)newAttributeValue);
- }
- _immediatePublishPropsCache.clear();
- _publishPropsCache.clear();
- }
+ // no op
}
public boolean authoriseConfiguringBroker(String configuredObjectName, Class<? extends ConfiguredObject> configuredObjectType, Operation configuredObjectOperation)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SubjectCreator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SubjectCreator.java
index 213f19dc5c..244ab0dd94 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SubjectCreator.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SubjectCreator.java
@@ -35,6 +35,7 @@ import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
import org.apache.qpid.server.security.auth.AuthenticationResult;
import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
+import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager;
import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
/**
@@ -153,4 +154,9 @@ public class SubjectCreator
return Collections.unmodifiableSet(principals);
}
+
+ public boolean isAnonymousAuthenticationAllowed()
+ {
+ return _authenticationManager instanceof AnonymousAuthenticationManager;
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/FileAccessControlProviderConstants.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/FileAccessControlProviderConstants.java
new file mode 100644
index 0000000000..3a98a947df
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/FileAccessControlProviderConstants.java
@@ -0,0 +1,27 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security.access;
+
+public class FileAccessControlProviderConstants
+{
+ public static final String ACL_FILE_PROVIDER_TYPE = "AclFile";
+ public static final String PATH = "path";
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticator.java
index abb8677e90..bf8d489e61 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticator.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpid.server.security.auth.rmi;
+package org.apache.qpid.server.security.auth.jmx;
import java.net.SocketAddress;
@@ -31,7 +31,7 @@ import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
import javax.management.remote.JMXAuthenticator;
import javax.security.auth.Subject;
-public class RMIPasswordAuthenticator implements JMXAuthenticator
+public class JMXPasswordAuthenticator implements JMXAuthenticator
{
static final String UNABLE_TO_LOOKUP = "The broker was unable to lookup the user details";
static final String SHOULD_BE_STRING_ARRAY = "User details should be String[]";
@@ -45,7 +45,7 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator
private final Broker _broker;
private final SocketAddress _address;
- public RMIPasswordAuthenticator(Broker broker, SocketAddress address)
+ public JMXPasswordAuthenticator(Broker broker, SocketAddress address)
{
_broker = broker;
_address = address;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java
new file mode 100644
index 0000000000..903f54dd8e
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java
@@ -0,0 +1,214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.qpid.server.security.auth.manager;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.AuthorizeCallback;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.sasl.plain.PlainPasswordCallback;
+import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer;
+
+public class SimpleAuthenticationManager implements AuthenticationManager
+{
+ private static final Logger _logger = Logger.getLogger(SimpleAuthenticationManager.class);
+
+ private static final String PLAIN_MECHANISM = "PLAIN";
+ private static final String CRAM_MD5_MECHANISM = "CRAM-MD5";
+
+ private Map<String, String> _users;
+
+ public SimpleAuthenticationManager(String userName, String userPassword)
+ {
+ this(Collections.singletonMap(userName, userPassword));
+ }
+
+ public SimpleAuthenticationManager(Map<String, String> users)
+ {
+ _users = new HashMap<String, String>(users);
+ }
+
+ @Override
+ public void initialise()
+ {
+ }
+
+ @Override
+ public String getMechanisms()
+ {
+ return PLAIN_MECHANISM + " " + CRAM_MD5_MECHANISM;
+ }
+
+ @Override
+ public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
+ {
+ if (PLAIN_MECHANISM.equals(mechanism))
+ {
+ return new PlainSaslServer(new SimplePlainCallbackHandler());
+ }
+ else if (CRAM_MD5_MECHANISM.equals(mechanism))
+ {
+ return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, null, new SimpleCramMd5CallbackHandler());
+ }
+ else
+ {
+ throw new SaslException("Unknown mechanism: " + mechanism);
+ }
+ }
+
+ @Override
+ public AuthenticationResult authenticate(SaslServer server, byte[] response)
+ {
+ try
+ {
+ // Process response from the client
+ byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
+
+ if (server.isComplete())
+ {
+ String authorizationID = server.getAuthorizationID();
+ _logger.debug("Authenticated as " + authorizationID);
+
+ return new AuthenticationResult(new UsernamePrincipal(authorizationID));
+ }
+ else
+ {
+ return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE);
+ }
+ }
+ catch (SaslException e)
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
+ }
+ }
+
+ @Override
+ public AuthenticationResult authenticate(String username, String password)
+ {
+ if (_users.containsKey(username))
+ {
+ String userPassword = _users.get(username);
+ if (userPassword.equals(password))
+ {
+ return new AuthenticationResult(new UsernamePrincipal(username));
+ }
+ }
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR);
+ }
+
+ @Override
+ public void close()
+ {
+ }
+
+ @Override
+ public void onCreate()
+ {
+ // nothing to do, no external resource is required
+ }
+
+ @Override
+ public void onDelete()
+ {
+ // nothing to do, no external resource is used
+ }
+
+ private class SimpleCramMd5CallbackHandler implements CallbackHandler
+ {
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+ {
+ String username = null;
+ for (Callback callback : callbacks)
+ {
+ if (callback instanceof NameCallback)
+ {
+ username = ((NameCallback) callback).getDefaultName();
+ }
+ else if (callback instanceof PasswordCallback)
+ {
+ if (_users.containsKey(username))
+ {
+ String password = _users.get(username);
+ ((PasswordCallback) callback).setPassword(password.toCharArray());
+ }
+ else
+ {
+ throw new SaslException("Authentication failed");
+ }
+ }
+ else if (callback instanceof AuthorizeCallback)
+ {
+ ((AuthorizeCallback) callback).setAuthorized(true);
+ }
+ else
+ {
+ throw new UnsupportedCallbackException(callback);
+ }
+ }
+ }
+ }
+
+ private class SimplePlainCallbackHandler implements CallbackHandler
+ {
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+ {
+ String username = null;
+ for (Callback callback : callbacks)
+ {
+ if (callback instanceof NameCallback)
+ {
+ username = ((NameCallback) callback).getDefaultName();
+ }
+ else if (callback instanceof PlainPasswordCallback)
+ {
+ if (_users.containsKey(username))
+ {
+ PlainPasswordCallback plainPasswordCallback = (PlainPasswordCallback) callback;
+ String password = plainPasswordCallback.getPlainPassword();
+ plainPasswordCallback.setAuthenticated(password.equals(_users.get(username)));
+ }
+ }
+ else if (callback instanceof AuthorizeCallback)
+ {
+ ((AuthorizeCallback) callback).setAuthorized(true);
+ }
+ else
+ {
+ throw new UnsupportedCallbackException(callback);
+ }
+ }
+ }
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java
index 509442b14b..475f74180e 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java
@@ -61,7 +61,7 @@ public class ExternalSaslServer implements SaslServer
public String getAuthorizationID()
{
- return null;
+ return getAuthenticatedPrincipal().getName();
}
public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManager.java
index 8295f28f9e..e11a4f83db 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManager.java
@@ -19,6 +19,7 @@
*/
package org.apache.qpid.server.security.group;
+import java.io.File;
import java.io.IOException;
import java.security.Principal;
import java.util.Collections;
@@ -34,32 +35,26 @@ import org.apache.qpid.server.security.auth.UsernamePrincipal;
* This plugin is configured in the following manner:
* </p>
* <pre>
- * &lt;file-group-manager&gt;
- * &lt;attributes&gt;
- * &lt;attribute&gt;
- * &lt;name>groupFile&lt;/name&gt;
- * &lt;value>${conf}/groups&lt;/value&gt;
- * &lt;/attribute&gt;
- * &lt;/attributes&gt;
- * &lt;/file-group-manager&gt;
+ * "groupproviders":[
+ * ...
+ * {
+ * "name" : "...",
+ * "type" : "GroupFile",
+ * "path" : "path/to/file/with/groups",
+ * }
+ * ...
+ * ]
* </pre>
*/
public class FileGroupManager implements GroupManager
{
private final FileGroupDatabase _groupDatabase;
-
+ private final String _groupFile;
public FileGroupManager(String groupFile)
{
+ _groupFile = groupFile;
_groupDatabase = new FileGroupDatabase();
- try
- {
- _groupDatabase.setGroupFile(groupFile);
- }
- catch (IOException e)
- {
- throw new IllegalConfigurationException("Unable to set group file " + groupFile, e);
- }
}
@Override
@@ -144,4 +139,101 @@ public class FileGroupManager implements GroupManager
}
+ @Override
+ public void onDelete()
+ {
+ File file = new File(_groupFile);
+ if (file.exists())
+ {
+ if (!file.delete())
+ {
+ throw new IllegalConfigurationException("Cannot delete group file");
+ }
+ }
+ }
+
+ @Override
+ public void onCreate()
+ {
+ File file = new File(_groupFile);
+ if (!file.exists())
+ {
+ File parent = file.getParentFile();
+ if (!parent.exists())
+ {
+ parent.mkdirs();
+ }
+ if (parent.exists())
+ {
+ try
+ {
+ file.createNewFile();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalConfigurationException("Cannot create group file");
+ }
+ }
+ else
+ {
+ throw new IllegalConfigurationException("Cannot create group file");
+ }
+ }
+ }
+
+ @Override
+ public void open()
+ {
+ try
+ {
+ _groupDatabase.setGroupFile(_groupFile);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalConfigurationException("Unable to set group file " + _groupFile, e);
+ }
+ }
+
+ @Override
+ public void close()
+ {
+ // no-op
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return ((_groupFile == null) ? 0 : _groupFile.hashCode());
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ FileGroupManager other = (FileGroupManager) obj;
+ if (_groupFile == null)
+ {
+ if (other._groupFile != null)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ return _groupFile.equals(other._groupFile);
+ }
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java
index 5c4730a9c8..50f08623cd 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java
@@ -20,32 +20,60 @@ package org.apache.qpid.server.security.group;
import static org.apache.qpid.server.util.MapValueConverter.getStringAttribute;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Map;
-import org.apache.commons.lang.StringUtils;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
-import org.apache.qpid.server.model.GroupProvider;
import org.apache.qpid.server.plugin.GroupManagerFactory;
+import org.apache.qpid.server.util.ResourceBundleLoader;
public class FileGroupManagerFactory implements GroupManagerFactory
{
- static final String FILE_GROUP_MANAGER_TYPE = "file-group-manager";
- static final String FILE = "file";
+ public static final String RESOURCE_BUNDLE = "org.apache.qpid.server.security.group.FileGroupProviderAttributeDescriptions";
+
+ public static final String GROUP_FILE_PROVIDER_TYPE = "GroupFile";
+ public static final String PATH = "path";
+
+ public static final Collection<String> ATTRIBUTES = Collections.<String> unmodifiableList(Arrays.asList(
+ ATTRIBUTE_TYPE,
+ PATH
+ ));
@Override
public GroupManager createInstance(Map<String, Object> attributes)
{
- if(!FILE_GROUP_MANAGER_TYPE.equals(getStringAttribute(GroupProvider.TYPE, attributes, null)))
+ if(attributes == null || !GROUP_FILE_PROVIDER_TYPE.equals(attributes.get(ATTRIBUTE_TYPE)))
{
return null;
}
- String groupFile = getStringAttribute(FILE, attributes, null);
- if (StringUtils.isBlank(groupFile))
+ String groupFile = getStringAttribute(PATH, attributes, null);
+ if (groupFile == null || "".equals(groupFile.trim()))
{
throw new IllegalConfigurationException("Path to file containing groups is not specified!");
}
+
return new FileGroupManager(groupFile);
}
+ @Override
+ public String getType()
+ {
+ return GROUP_FILE_PROVIDER_TYPE;
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return ATTRIBUTES;
+ }
+
+ @Override
+ public Map<String, String> getAttributeDescriptions()
+ {
+ return ResourceBundleLoader.getResources(RESOURCE_BUNDLE);
+ }
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupManager.java
index 6d2df86919..3fd6dd2800 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupManager.java
@@ -37,4 +37,12 @@ public interface GroupManager
void addUserToGroup(String user, String group);
void removeUserFromGroup(String user, String group);
+
+ void open();
+
+ void close();
+
+ void onDelete();
+
+ void onCreate();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
new file mode 100644
index 0000000000..2950fdb039
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
@@ -0,0 +1,2041 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.store;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.ref.SoftReference;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import org.apache.commons.configuration.Configuration;
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.binding.Binding;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.message.EnqueableMessage;
+import org.apache.qpid.server.plugin.MessageMetaDataType;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BindingRecoveryHandler;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler.ExchangeRecoveryHandler;
+import org.apache.qpid.server.store.ConfigurationRecoveryHandler.QueueRecoveryHandler;
+
+abstract public class AbstractJDBCMessageStore implements MessageStore
+{
+ private static final String DB_VERSION_TABLE_NAME = "QPID_DB_VERSION";
+
+ private static final String QUEUE_ENTRY_TABLE_NAME = "QPID_QUEUE_ENTRIES";
+
+ private static final String META_DATA_TABLE_NAME = "QPID_MESSAGE_METADATA";
+ private static final String MESSAGE_CONTENT_TABLE_NAME = "QPID_MESSAGE_CONTENT";
+
+ private static final String LINKS_TABLE_NAME = "QPID_LINKS";
+ private static final String BRIDGES_TABLE_NAME = "QPID_BRIDGES";
+
+ private static final String XID_TABLE_NAME = "QPID_XIDS";
+ private static final String XID_ACTIONS_TABLE_NAME = "QPID_XID_ACTIONS";
+
+ private static final String CONFIGURED_OBJECTS_TABLE_NAME = "QPID_CONFIGURED_OBJECTS";
+
+ private static final int DB_VERSION = 6;
+
+ private final AtomicLong _messageId = new AtomicLong(0);
+ private AtomicBoolean _closed = new AtomicBoolean(false);
+
+ protected String _connectionURL;
+
+
+ private static final String CREATE_DB_VERSION_TABLE = "CREATE TABLE "+ DB_VERSION_TABLE_NAME + " ( version int not null )";
+ private static final String INSERT_INTO_DB_VERSION = "INSERT INTO "+ DB_VERSION_TABLE_NAME + " ( version ) VALUES ( ? )";
+
+ private static final String INSERT_INTO_QUEUE_ENTRY = "INSERT INTO " + QUEUE_ENTRY_TABLE_NAME + " (queue_id, message_id) values (?,?)";
+ private static final String DELETE_FROM_QUEUE_ENTRY = "DELETE FROM " + QUEUE_ENTRY_TABLE_NAME + " WHERE queue_id = ? AND message_id =?";
+ private static final String SELECT_FROM_QUEUE_ENTRY = "SELECT queue_id, message_id FROM " + QUEUE_ENTRY_TABLE_NAME + " ORDER BY queue_id, message_id";
+ private static final String INSERT_INTO_MESSAGE_CONTENT = "INSERT INTO " + MESSAGE_CONTENT_TABLE_NAME
+ + "( message_id, content ) values (?, ?)";
+ private static final String SELECT_FROM_MESSAGE_CONTENT = "SELECT content FROM " + MESSAGE_CONTENT_TABLE_NAME
+ + " WHERE message_id = ?";
+ private static final String DELETE_FROM_MESSAGE_CONTENT = "DELETE FROM " + MESSAGE_CONTENT_TABLE_NAME
+ + " WHERE message_id = ?";
+
+ private static final String INSERT_INTO_META_DATA = "INSERT INTO " + META_DATA_TABLE_NAME + "( message_id , meta_data ) values (?, ?)";
+ private static final String SELECT_FROM_META_DATA =
+ "SELECT meta_data FROM " + META_DATA_TABLE_NAME + " WHERE message_id = ?";
+ private static final String DELETE_FROM_META_DATA = "DELETE FROM " + META_DATA_TABLE_NAME + " WHERE message_id = ?";
+ private static final String SELECT_ALL_FROM_META_DATA = "SELECT message_id, meta_data FROM " + META_DATA_TABLE_NAME;
+
+ private static final String SELECT_FROM_LINKS =
+ "SELECT create_time, arguments FROM " + LINKS_TABLE_NAME + " WHERE id_lsb = ? and id_msb";
+ private static final String DELETE_FROM_LINKS = "DELETE FROM " + LINKS_TABLE_NAME
+ + " WHERE id_lsb = ? and id_msb = ?";
+ private static final String SELECT_ALL_FROM_LINKS = "SELECT id_lsb, id_msb, create_time, "
+ + "arguments FROM " + LINKS_TABLE_NAME;
+ private static final String FIND_LINK = "SELECT id_lsb, id_msb FROM " + LINKS_TABLE_NAME + " WHERE id_lsb = ? and"
+ + " id_msb = ?";
+ private static final String INSERT_INTO_LINKS = "INSERT INTO " + LINKS_TABLE_NAME + "( id_lsb, "
+ + "id_msb, create_time, arguments ) values (?, ?, ?, ?)";
+ private static final String SELECT_FROM_BRIDGES =
+ "SELECT create_time, link_id_lsb, link_id_msb, arguments FROM "
+ + BRIDGES_TABLE_NAME + " WHERE id_lsb = ? and id_msb = ?";
+ private static final String DELETE_FROM_BRIDGES = "DELETE FROM " + BRIDGES_TABLE_NAME
+ + " WHERE id_lsb = ? and id_msb = ?";
+ private static final String SELECT_ALL_FROM_BRIDGES = "SELECT id_lsb, id_msb, "
+ + " create_time,"
+ + " link_id_lsb, link_id_msb, "
+ + "arguments FROM " + BRIDGES_TABLE_NAME
+ + " WHERE link_id_lsb = ? and link_id_msb = ?";
+ private static final String FIND_BRIDGE = "SELECT id_lsb, id_msb FROM " + BRIDGES_TABLE_NAME +
+ " WHERE id_lsb = ? and id_msb = ?";
+ private static final String INSERT_INTO_BRIDGES = "INSERT INTO " + BRIDGES_TABLE_NAME + "( id_lsb, id_msb, "
+ + "create_time, "
+ + "link_id_lsb, link_id_msb, "
+ + "arguments )"
+ + " values (?, ?, ?, ?, ?, ?)";
+
+ private static final String INSERT_INTO_XIDS =
+ "INSERT INTO "+ XID_TABLE_NAME +" ( format, global_id, branch_id ) values (?, ?, ?)";
+ private static final String DELETE_FROM_XIDS = "DELETE FROM " + XID_TABLE_NAME
+ + " WHERE format = ? and global_id = ? and branch_id = ?";
+ private static final String SELECT_ALL_FROM_XIDS = "SELECT format, global_id, branch_id FROM " + XID_TABLE_NAME;
+ private static final String INSERT_INTO_XID_ACTIONS =
+ "INSERT INTO "+ XID_ACTIONS_TABLE_NAME +" ( format, global_id, branch_id, action_type, " +
+ "queue_id, message_id ) values (?,?,?,?,?,?) ";
+ private static final String DELETE_FROM_XID_ACTIONS = "DELETE FROM " + XID_ACTIONS_TABLE_NAME
+ + " WHERE format = ? and global_id = ? and branch_id = ?";
+ private static final String SELECT_ALL_FROM_XID_ACTIONS =
+ "SELECT action_type, queue_id, message_id FROM " + XID_ACTIONS_TABLE_NAME +
+ " WHERE format = ? and global_id = ? and branch_id = ?";
+ private static final String INSERT_INTO_CONFIGURED_OBJECTS = "INSERT INTO " + CONFIGURED_OBJECTS_TABLE_NAME
+ + " ( id, object_type, attributes) VALUES (?,?,?)";
+ private static final String UPDATE_CONFIGURED_OBJECTS = "UPDATE " + CONFIGURED_OBJECTS_TABLE_NAME
+ + " set object_type =?, attributes = ? where id = ?";
+ private static final String DELETE_FROM_CONFIGURED_OBJECTS = "DELETE FROM " + CONFIGURED_OBJECTS_TABLE_NAME
+ + " where id = ?";
+ private static final String FIND_CONFIGURED_OBJECT = "SELECT object_type, attributes FROM " + CONFIGURED_OBJECTS_TABLE_NAME
+ + " where id = ?";
+ private static final String SELECT_FROM_CONFIGURED_OBJECTS = "SELECT id, object_type, attributes FROM " + CONFIGURED_OBJECTS_TABLE_NAME;
+
+ protected static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
+
+ protected final EventManager _eventManager = new EventManager();
+
+ protected final StateManager _stateManager;
+
+ private MessageStoreRecoveryHandler _messageRecoveryHandler;
+ private TransactionLogRecoveryHandler _tlogRecoveryHandler;
+ private ConfigurationRecoveryHandler _configRecoveryHandler;
+
+ public AbstractJDBCMessageStore()
+ {
+ _stateManager = new StateManager(_eventManager);
+ }
+
+ private ConfiguredObjectHelper _configuredObjectHelper = new ConfiguredObjectHelper();
+
+ @Override
+ public void configureConfigStore(String name,
+ ConfigurationRecoveryHandler configRecoveryHandler,
+ Configuration storeConfiguration) throws Exception
+ {
+ _stateManager.attainState(State.INITIALISING);
+ _configRecoveryHandler = configRecoveryHandler;
+
+ commonConfiguration(name, storeConfiguration);
+
+ }
+
+ @Override
+ public void configureMessageStore(String name,
+ MessageStoreRecoveryHandler recoveryHandler,
+ TransactionLogRecoveryHandler tlogRecoveryHandler,
+ Configuration storeConfiguration) throws Exception
+ {
+ _tlogRecoveryHandler = tlogRecoveryHandler;
+ _messageRecoveryHandler = recoveryHandler;
+
+ _stateManager.attainState(State.INITIALISED);
+ }
+
+ @Override
+ public void activate() throws Exception
+ {
+ _stateManager.attainState(State.ACTIVATING);
+
+ // this recovers durable exchanges, queues, and bindings
+ recoverConfiguration(_configRecoveryHandler);
+ recoverMessages(_messageRecoveryHandler);
+ TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh = recoverQueueEntries(_tlogRecoveryHandler);
+ recoverXids(dtxrh);
+
+ _stateManager.attainState(State.ACTIVE);
+ }
+
+ private void commonConfiguration(String name, Configuration storeConfiguration)
+ throws ClassNotFoundException, SQLException
+ {
+ implementationSpecificConfiguration(name, storeConfiguration);
+ createOrOpenDatabase();
+
+ }
+
+ protected abstract void implementationSpecificConfiguration(String name, Configuration storeConfiguration) throws ClassNotFoundException;
+
+ abstract protected Logger getLogger();
+
+ abstract protected String getSqlBlobType();
+
+ abstract protected String getSqlVarBinaryType(int size);
+
+ abstract protected String getSqlBigIntType();
+
+ protected void createOrOpenDatabase() throws SQLException
+ {
+ Connection conn = newAutoCommitConnection();
+
+ createVersionTable(conn);
+ createConfiguredObjectsTable(conn);
+ createQueueEntryTable(conn);
+ createMetaDataTable(conn);
+ createMessageContentTable(conn);
+ createLinkTable(conn);
+ createBridgeTable(conn);
+ createXidTable(conn);
+ createXidActionTable(conn);
+ conn.close();
+ }
+
+ private void createVersionTable(final Connection conn) throws SQLException
+ {
+ if(!tableExists(DB_VERSION_TABLE_NAME, conn))
+ {
+ Statement stmt = conn.createStatement();
+ try
+ {
+ stmt.execute(CREATE_DB_VERSION_TABLE);
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ PreparedStatement pstmt = conn.prepareStatement(INSERT_INTO_DB_VERSION);
+ try
+ {
+ pstmt.setInt(1, DB_VERSION);
+ pstmt.execute();
+ }
+ finally
+ {
+ pstmt.close();
+ }
+ }
+
+ }
+
+ private void createConfiguredObjectsTable(final Connection conn) throws SQLException
+ {
+ if(!tableExists(CONFIGURED_OBJECTS_TABLE_NAME, conn))
+ {
+ Statement stmt = conn.createStatement();
+ try
+ {
+ stmt.execute("CREATE TABLE " + CONFIGURED_OBJECTS_TABLE_NAME
+ + " ( id VARCHAR(36) not null, object_type varchar(255), attributes "+getSqlBlobType()+", PRIMARY KEY (id))");
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ }
+
+ private void createQueueEntryTable(final Connection conn) throws SQLException
+ {
+ if(!tableExists(QUEUE_ENTRY_TABLE_NAME, conn))
+ {
+ Statement stmt = conn.createStatement();
+ try
+ {
+ stmt.execute("CREATE TABLE "+ QUEUE_ENTRY_TABLE_NAME +" ( queue_id varchar(36) not null, message_id "
+ + getSqlBigIntType() + " not null, PRIMARY KEY (queue_id, message_id) )");
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+
+ }
+
+ private void createMetaDataTable(final Connection conn) throws SQLException
+ {
+ if(!tableExists(META_DATA_TABLE_NAME, conn))
+ {
+ Statement stmt = conn.createStatement();
+ try
+ {
+ stmt.execute("CREATE TABLE "
+ + META_DATA_TABLE_NAME
+ + " ( message_id "
+ + getSqlBigIntType()
+ + " not null, meta_data "
+ + getSqlBlobType()
+ + ", PRIMARY KEY ( message_id ) )");
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+
+ }
+
+ private void createMessageContentTable(final Connection conn) throws SQLException
+ {
+ if(!tableExists(MESSAGE_CONTENT_TABLE_NAME, conn))
+ {
+ Statement stmt = conn.createStatement();
+ try
+ {
+ stmt.execute("CREATE TABLE "
+ + MESSAGE_CONTENT_TABLE_NAME
+ + " ( message_id "
+ + getSqlBigIntType()
+ + " not null, content "
+ + getSqlBlobType()
+ + ", PRIMARY KEY (message_id) )");
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+
+ }
+
+ private void createLinkTable(final Connection conn) throws SQLException
+ {
+ if(!tableExists(LINKS_TABLE_NAME, conn))
+ {
+ Statement stmt = conn.createStatement();
+ try
+ {
+ stmt.execute("CREATE TABLE "+ LINKS_TABLE_NAME +" ( id_lsb " + getSqlBigIntType() + " not null,"
+ + " id_msb " + getSqlBigIntType() + " not null,"
+ + " create_time " + getSqlBigIntType() + " not null,"
+ + " arguments "+getSqlBlobType()+", PRIMARY KEY ( id_lsb, id_msb ))");
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ }
+
+ private void createBridgeTable(final Connection conn) throws SQLException
+ {
+ if(!tableExists(BRIDGES_TABLE_NAME, conn))
+ {
+ Statement stmt = conn.createStatement();
+ try
+ {
+ stmt.execute("CREATE TABLE "+ BRIDGES_TABLE_NAME +" ( id_lsb " + getSqlBigIntType() + " not null,"
+ + " id_msb " + getSqlBigIntType() + " not null,"
+ + " create_time " + getSqlBigIntType() + " not null,"
+ + " link_id_lsb " + getSqlBigIntType() + " not null,"
+ + " link_id_msb " + getSqlBigIntType() + " not null,"
+ + " arguments "+getSqlBlobType()+", PRIMARY KEY ( id_lsb, id_msb ))");
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ }
+
+ private void createXidTable(final Connection conn) throws SQLException
+ {
+ if(!tableExists(XID_TABLE_NAME, conn))
+ {
+ Statement stmt = conn.createStatement();
+ try
+ {
+ stmt.execute("CREATE TABLE "
+ + XID_TABLE_NAME
+ + " ( format " + getSqlBigIntType() + " not null,"
+ + " global_id "
+ + getSqlVarBinaryType(64)
+ + ", branch_id "
+ + getSqlVarBinaryType(64)
+ + " , PRIMARY KEY ( format, "
+ +
+ "global_id, branch_id ))");
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ }
+
+ private void createXidActionTable(final Connection conn) throws SQLException
+ {
+ if(!tableExists(XID_ACTIONS_TABLE_NAME, conn))
+ {
+ Statement stmt = conn.createStatement();
+ try
+ {
+ stmt.execute("CREATE TABLE " + XID_ACTIONS_TABLE_NAME + " ( format " + getSqlBigIntType() + " not null,"
+ + " global_id " + getSqlVarBinaryType(64) + " not null, branch_id " + getSqlVarBinaryType(
+ 64) + " not null, " +
+ "action_type char not null, queue_id varchar(36) not null, message_id " + getSqlBigIntType() + " not null" +
+ ", PRIMARY KEY ( " +
+ "format, global_id, branch_id, action_type, queue_id, message_id))");
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ }
+
+ protected boolean tableExists(final String tableName, final Connection conn) throws SQLException
+ {
+ DatabaseMetaData metaData = conn.getMetaData();
+ ResultSet rs = metaData.getTables(null, null, "%", null);
+
+ try
+ {
+
+ while(rs.next())
+ {
+ final String table = rs.getString(3);
+ if(tableName.equalsIgnoreCase(table))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+
+ protected void recoverConfiguration(ConfigurationRecoveryHandler recoveryHandler) throws AMQException
+ {
+ try
+ {
+ List<ConfiguredObjectRecord> configuredObjects = loadConfiguredObjects();
+
+ ExchangeRecoveryHandler erh = recoveryHandler.begin(this);
+ _configuredObjectHelper.recoverExchanges(erh, configuredObjects);
+
+ QueueRecoveryHandler qrh = erh.completeExchangeRecovery();
+ _configuredObjectHelper.recoverQueues(qrh, configuredObjects);
+
+ BindingRecoveryHandler brh = qrh.completeQueueRecovery();
+ _configuredObjectHelper.recoverBindings(brh, configuredObjects);
+
+ brh.completeBindingRecovery();
+ }
+ catch (SQLException e)
+ {
+ throw new AMQStoreException("Error recovering persistent state: " + e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public void close() throws Exception
+ {
+ _closed.getAndSet(true);
+ _stateManager.attainState(State.CLOSING);
+
+ doClose();
+
+ _stateManager.attainState(State.CLOSED);
+ }
+
+
+ protected abstract void doClose() throws Exception;
+
+ @Override
+ public StoredMessage addMessage(StorableMessageMetaData metaData)
+ {
+ if(metaData.isPersistent())
+ {
+ return new StoredJDBCMessage(_messageId.incrementAndGet(), metaData);
+ }
+ else
+ {
+ return new StoredMemoryMessage(_messageId.incrementAndGet(), metaData);
+ }
+ }
+
+ public StoredMessage getMessage(long messageNumber)
+ {
+ return null;
+ }
+
+ public void removeMessage(long messageId)
+ {
+ try
+ {
+ Connection conn = newConnection();
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_META_DATA);
+ try
+ {
+ stmt.setLong(1,messageId);
+ int results = stmt.executeUpdate();
+ stmt.close();
+
+ if (results == 0)
+ {
+ getLogger().warn("Message metadata not found for message id " + messageId);
+ }
+
+ if (getLogger().isDebugEnabled())
+ {
+ getLogger().debug("Deleted metadata for message " + messageId);
+ }
+
+ stmt = conn.prepareStatement(DELETE_FROM_MESSAGE_CONTENT);
+ stmt.setLong(1,messageId);
+ results = stmt.executeUpdate();
+ }
+ finally
+ {
+ stmt.close();
+ }
+ conn.commit();
+ }
+ catch(SQLException e)
+ {
+ try
+ {
+ conn.rollback();
+ }
+ catch(SQLException t)
+ {
+ // ignore - we are re-throwing underlying exception
+ }
+
+ throw e;
+
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new RuntimeException("Error removing message with id " + messageId + " from database: " + e.getMessage(), e);
+ }
+
+ }
+
+ @Override
+ public void createExchange(Exchange exchange) throws AMQStoreException
+ {
+ if (_stateManager.isInState(State.ACTIVE))
+ {
+ ConfiguredObjectRecord configuredObject = _configuredObjectHelper.createExchangeConfiguredObject(exchange);
+ insertConfiguredObject(configuredObject);
+ }
+
+ }
+
+ @Override
+ public void removeExchange(Exchange exchange) throws AMQStoreException
+ {
+ int results = removeConfiguredObject(exchange.getId());
+ if (results == 0)
+ {
+ throw new AMQStoreException("Exchange " + exchange.getName() + " with id " + exchange.getId() + " not found");
+ }
+ }
+
+ @Override
+ public void bindQueue(Binding binding)
+ throws AMQStoreException
+ {
+ if (_stateManager.isInState(State.ACTIVE))
+ {
+ ConfiguredObjectRecord configuredObject = _configuredObjectHelper.createBindingConfiguredObject(binding);
+ insertConfiguredObject(configuredObject);
+ }
+ }
+
+ @Override
+ public void unbindQueue(Binding binding)
+ throws AMQStoreException
+ {
+ int results = removeConfiguredObject(binding.getId());
+ if (results == 0)
+ {
+ throw new AMQStoreException("Binding " + binding + " not found");
+ }
+ }
+
+ @Override
+ public void createQueue(AMQQueue queue) throws AMQStoreException
+ {
+ createQueue(queue, null);
+ }
+
+ @Override
+ public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQStoreException
+ {
+ getLogger().debug("public void createQueue(AMQQueue queue = " + queue + "): called");
+
+ if (_stateManager.isInState(State.ACTIVE))
+ {
+ ConfiguredObjectRecord queueConfiguredObject = _configuredObjectHelper.createQueueConfiguredObject(queue, arguments);
+ insertConfiguredObject(queueConfiguredObject);
+ }
+ }
+
+ /**
+ * Updates the specified queue in the persistent store, IF it is already present. If the queue
+ * is not present in the store, it will not be added.
+ *
+ * NOTE: Currently only updates the exclusivity.
+ *
+ * @param queue The queue to update the entry for.
+ * @throws org.apache.qpid.AMQStoreException If the operation fails for any reason.
+ */
+ @Override
+ public void updateQueue(final AMQQueue queue) throws AMQStoreException
+ {
+ if (_stateManager.isInState(State.ACTIVE))
+ {
+ ConfiguredObjectRecord queueConfiguredObject = loadConfiguredObject(queue.getId());
+ if (queueConfiguredObject != null)
+ {
+ ConfiguredObjectRecord newQueueRecord = _configuredObjectHelper.updateQueueConfiguredObject(queue, queueConfiguredObject);
+ updateConfiguredObject(newQueueRecord);
+ }
+ }
+
+ }
+
+
+ /**
+ * Convenience method to create a new Connection configured for TRANSACTION_READ_COMMITED
+ * isolation and with auto-commit transactions enabled.
+ */
+ protected Connection newAutoCommitConnection() throws SQLException
+ {
+ final Connection connection = newConnection();
+ try
+ {
+ connection.setAutoCommit(true);
+ }
+ catch (SQLException sqlEx)
+ {
+
+ try
+ {
+ connection.close();
+ }
+ finally
+ {
+ throw sqlEx;
+ }
+ }
+
+ return connection;
+ }
+
+ /**
+ * Convenience method to create a new Connection configured for TRANSACTION_READ_COMMITED
+ * isolation and with auto-commit transactions disabled.
+ */
+ protected Connection newConnection() throws SQLException
+ {
+ final Connection connection = DriverManager.getConnection(_connectionURL);
+ try
+ {
+ connection.setAutoCommit(false);
+ connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+ }
+ catch (SQLException sqlEx)
+ {
+ try
+ {
+ connection.close();
+ }
+ finally
+ {
+ throw sqlEx;
+ }
+ }
+ return connection;
+ }
+
+ @Override
+ public void removeQueue(final AMQQueue queue) throws AMQStoreException
+ {
+ AMQShortString name = queue.getNameShortString();
+ getLogger().debug("public void removeQueue(AMQShortString name = " + name + "): called");
+ int results = removeConfiguredObject(queue.getId());
+ if (results == 0)
+ {
+ throw new AMQStoreException("Queue " + name + " with id " + queue.getId() + " not found");
+ }
+ }
+
+ private byte[] convertStringMapToBytes(final Map<String, String> arguments) throws AMQStoreException
+ {
+ byte[] argumentBytes;
+ if(arguments == null)
+ {
+ argumentBytes = new byte[0];
+ }
+ else
+ {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ DataOutputStream dos = new DataOutputStream(bos);
+
+
+ try
+ {
+ dos.writeInt(arguments.size());
+ for(Map.Entry<String,String> arg : arguments.entrySet())
+ {
+ dos.writeUTF(arg.getKey());
+ dos.writeUTF(arg.getValue());
+ }
+ }
+ catch (IOException e)
+ {
+ // This should never happen
+ throw new AMQStoreException(e.getMessage(), e);
+ }
+ argumentBytes = bos.toByteArray();
+ }
+ return argumentBytes;
+ }
+
+ @Override
+ public Transaction newTransaction()
+ {
+ return new JDBCTransaction();
+ }
+
+ public void enqueueMessage(ConnectionWrapper connWrapper, final TransactionLogResource queue, Long messageId) throws AMQStoreException
+ {
+ Connection conn = connWrapper.getConnection();
+
+
+ try
+ {
+ if (getLogger().isDebugEnabled())
+ {
+ getLogger().debug("Enqueuing message "
+ + messageId
+ + " on queue "
+ + (queue instanceof AMQQueue
+ ? ((AMQQueue) queue).getName()
+ : "")
+ + queue.getId()
+ + "[Connection"
+ + conn
+ + "]");
+ }
+
+ PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_QUEUE_ENTRY);
+ try
+ {
+ stmt.setString(1, queue.getId().toString());
+ stmt.setLong(2,messageId);
+ stmt.executeUpdate();
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ }
+ catch (SQLException e)
+ {
+ getLogger().error("Failed to enqueue: " + e.getMessage(), e);
+ throw new AMQStoreException("Error writing enqueued message with id " + messageId + " for queue " + (queue instanceof AMQQueue ? ((AMQQueue)queue).getName() : "" ) + " with id " + queue.getId()
+ + " to database", e);
+ }
+
+ }
+
+ public void dequeueMessage(ConnectionWrapper connWrapper, final TransactionLogResource queue, Long messageId) throws AMQStoreException
+ {
+
+ Connection conn = connWrapper.getConnection();
+
+
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_QUEUE_ENTRY);
+ try
+ {
+ stmt.setString(1, queue.getId().toString());
+ stmt.setLong(2, messageId);
+ int results = stmt.executeUpdate();
+
+
+
+ if(results != 1)
+ {
+ throw new AMQStoreException("Unable to find message with id " + messageId + " on queue " + (queue instanceof AMQQueue ? ((AMQQueue)queue).getName() : "" )
+ + " with id " + queue.getId());
+ }
+
+ if (getLogger().isDebugEnabled())
+ {
+ getLogger().debug("Dequeuing message " + messageId + " on queue " + (queue instanceof AMQQueue
+ ? ((AMQQueue) queue).getName()
+ : "")
+ + " with id " + queue.getId());
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ }
+ catch (SQLException e)
+ {
+ getLogger().error("Failed to dequeue: " + e.getMessage(), e);
+ throw new AMQStoreException("Error deleting enqueued message with id " + messageId + " for queue " + (queue instanceof AMQQueue ? ((AMQQueue)queue).getName() : "" )
+ + " with id " + queue.getId() + " from database", e);
+ }
+
+ }
+
+ private void removeXid(ConnectionWrapper connWrapper, long format, byte[] globalId, byte[] branchId)
+ throws AMQStoreException
+ {
+ Connection conn = connWrapper.getConnection();
+
+
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_XIDS);
+ try
+ {
+ stmt.setLong(1,format);
+ stmt.setBytes(2,globalId);
+ stmt.setBytes(3,branchId);
+ int results = stmt.executeUpdate();
+
+
+
+ if(results != 1)
+ {
+ throw new AMQStoreException("Unable to find message with xid");
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ stmt = conn.prepareStatement(DELETE_FROM_XID_ACTIONS);
+ try
+ {
+ stmt.setLong(1,format);
+ stmt.setBytes(2,globalId);
+ stmt.setBytes(3,branchId);
+ int results = stmt.executeUpdate();
+
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ }
+ catch (SQLException e)
+ {
+ getLogger().error("Failed to dequeue: " + e.getMessage(), e);
+ throw new AMQStoreException("Error deleting enqueued message with xid", e);
+ }
+
+ }
+
+ private void recordXid(ConnectionWrapper connWrapper, long format, byte[] globalId, byte[] branchId,
+ Transaction.Record[] enqueues, Transaction.Record[] dequeues) throws AMQStoreException
+ {
+ Connection conn = connWrapper.getConnection();
+
+
+ try
+ {
+
+ PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_XIDS);
+ try
+ {
+ stmt.setLong(1,format);
+ stmt.setBytes(2, globalId);
+ stmt.setBytes(3, branchId);
+ stmt.executeUpdate();
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ stmt = conn.prepareStatement(INSERT_INTO_XID_ACTIONS);
+
+ try
+ {
+ stmt.setLong(1,format);
+ stmt.setBytes(2, globalId);
+ stmt.setBytes(3, branchId);
+
+ if(enqueues != null)
+ {
+ stmt.setString(4, "E");
+ for(Transaction.Record record : enqueues)
+ {
+ stmt.setString(5, record.getQueue().getId().toString());
+ stmt.setLong(6, record.getMessage().getMessageNumber());
+ stmt.executeUpdate();
+ }
+ }
+
+ if(dequeues != null)
+ {
+ stmt.setString(4, "D");
+ for(Transaction.Record record : dequeues)
+ {
+ stmt.setString(5, record.getQueue().getId().toString());
+ stmt.setLong(6, record.getMessage().getMessageNumber());
+ stmt.executeUpdate();
+ }
+ }
+
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ }
+ catch (SQLException e)
+ {
+ getLogger().error("Failed to enqueue: " + e.getMessage(), e);
+ throw new AMQStoreException("Error writing xid ", e);
+ }
+
+ }
+
+ private static final class ConnectionWrapper
+ {
+ private final Connection _connection;
+
+ public ConnectionWrapper(Connection conn)
+ {
+ _connection = conn;
+ }
+
+ public Connection getConnection()
+ {
+ return _connection;
+ }
+ }
+
+
+ public void commitTran(ConnectionWrapper connWrapper) throws AMQStoreException
+ {
+
+ try
+ {
+ Connection conn = connWrapper.getConnection();
+ conn.commit();
+
+ if (getLogger().isDebugEnabled())
+ {
+ getLogger().debug("commit tran completed");
+ }
+
+ conn.close();
+ }
+ catch (SQLException e)
+ {
+ throw new AMQStoreException("Error commit tx: " + e.getMessage(), e);
+ }
+ finally
+ {
+
+ }
+ }
+
+ public StoreFuture commitTranAsync(ConnectionWrapper connWrapper) throws AMQStoreException
+ {
+ commitTran(connWrapper);
+ return StoreFuture.IMMEDIATE_FUTURE;
+ }
+
+ public void abortTran(ConnectionWrapper connWrapper) throws AMQStoreException
+ {
+ if (connWrapper == null)
+ {
+ throw new AMQStoreException("Fatal internal error: transactional context is empty at abortTran");
+ }
+
+ if (getLogger().isDebugEnabled())
+ {
+ getLogger().debug("abort tran called: " + connWrapper.getConnection());
+ }
+
+ try
+ {
+ Connection conn = connWrapper.getConnection();
+ conn.rollback();
+ conn.close();
+ }
+ catch (SQLException e)
+ {
+ throw new AMQStoreException("Error aborting transaction: " + e.getMessage(), e);
+ }
+
+ }
+
+ public Long getNewMessageId()
+ {
+ return _messageId.incrementAndGet();
+ }
+
+ private void storeMetaData(Connection conn, long messageId, StorableMessageMetaData metaData)
+ throws SQLException
+ {
+ if(getLogger().isDebugEnabled())
+ {
+ getLogger().debug("Adding metadata for message " + messageId);
+ }
+
+ PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_META_DATA);
+ try
+ {
+ stmt.setLong(1,messageId);
+
+ final int bodySize = 1 + metaData.getStorableSize();
+ byte[] underlying = new byte[bodySize];
+ underlying[0] = (byte) metaData.getType().ordinal();
+ ByteBuffer buf = ByteBuffer.wrap(underlying);
+ buf.position(1);
+ buf = buf.slice();
+
+ metaData.writeToBuffer(0, buf);
+ ByteArrayInputStream bis = new ByteArrayInputStream(underlying);
+ try
+ {
+ stmt.setBinaryStream(2,bis,underlying.length);
+ int result = stmt.executeUpdate();
+
+ if(result == 0)
+ {
+ throw new RuntimeException("Unable to add meta data for message " +messageId);
+ }
+ }
+ finally
+ {
+ try
+ {
+ bis.close();
+ }
+ catch (IOException e)
+ {
+
+ throw new SQLException(e);
+ }
+ }
+
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ }
+
+ protected void recoverMessages(MessageStoreRecoveryHandler recoveryHandler) throws SQLException
+ {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ MessageStoreRecoveryHandler.StoredMessageRecoveryHandler messageHandler = recoveryHandler.begin();
+
+ Statement stmt = conn.createStatement();
+ try
+ {
+ ResultSet rs = stmt.executeQuery(SELECT_ALL_FROM_META_DATA);
+ try
+ {
+
+ long maxId = 0;
+
+ while(rs.next())
+ {
+
+ long messageId = rs.getLong(1);
+ if(messageId > maxId)
+ {
+ maxId = messageId;
+ }
+
+ byte[] dataAsBytes = getBlobAsBytes(rs, 2);
+
+ ByteBuffer buf = ByteBuffer.wrap(dataAsBytes);
+ buf.position(1);
+ buf = buf.slice();
+ MessageMetaDataType type = MessageMetaDataTypeRegistry.fromOrdinal(dataAsBytes[0]);
+ StorableMessageMetaData metaData = type.createMetaData(buf);
+ StoredJDBCMessage message = new StoredJDBCMessage(messageId, metaData, true);
+ messageHandler.message(message);
+ }
+
+ _messageId.set(maxId);
+
+ messageHandler.completeMessageRecovery();
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
+
+
+ protected TransactionLogRecoveryHandler.DtxRecordRecoveryHandler recoverQueueEntries(TransactionLogRecoveryHandler recoveryHandler) throws SQLException
+ {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ TransactionLogRecoveryHandler.QueueEntryRecoveryHandler queueEntryHandler = recoveryHandler.begin(this);
+
+ Statement stmt = conn.createStatement();
+ try
+ {
+ ResultSet rs = stmt.executeQuery(SELECT_FROM_QUEUE_ENTRY);
+ try
+ {
+ while(rs.next())
+ {
+
+ String id = rs.getString(1);
+ long messageId = rs.getLong(2);
+ queueEntryHandler.queueEntry(UUID.fromString(id), messageId);
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ return queueEntryHandler.completeQueueEntryRecovery();
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
+
+ private static final class Xid
+ {
+
+ private final long _format;
+ private final byte[] _globalId;
+ private final byte[] _branchId;
+
+ public Xid(long format, byte[] globalId, byte[] branchId)
+ {
+ _format = format;
+ _globalId = globalId;
+ _branchId = branchId;
+ }
+
+ public long getFormat()
+ {
+ return _format;
+ }
+
+ public byte[] getGlobalId()
+ {
+ return _globalId;
+ }
+
+ public byte[] getBranchId()
+ {
+ return _branchId;
+ }
+ }
+
+ private static class RecordImpl implements Transaction.Record, TransactionLogResource, EnqueableMessage
+ {
+
+ private long _messageNumber;
+ private UUID _queueId;
+
+ public RecordImpl(UUID queueId, long messageNumber)
+ {
+ _messageNumber = messageNumber;
+ _queueId = queueId;
+ }
+
+ @Override
+ public TransactionLogResource getQueue()
+ {
+ return this;
+ }
+
+ @Override
+ public EnqueableMessage getMessage()
+ {
+ return this;
+ }
+
+ @Override
+ public long getMessageNumber()
+ {
+ return _messageNumber;
+ }
+
+ @Override
+ public boolean isPersistent()
+ {
+ return true;
+ }
+
+ @Override
+ public StoredMessage getStoredMessage()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public UUID getId()
+ {
+ return _queueId;
+ }
+ }
+
+ protected void recoverXids(TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh) throws SQLException
+ {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ List<Xid> xids = new ArrayList<Xid>();
+
+ Statement stmt = conn.createStatement();
+ try
+ {
+ ResultSet rs = stmt.executeQuery(SELECT_ALL_FROM_XIDS);
+ try
+ {
+ while(rs.next())
+ {
+
+ long format = rs.getLong(1);
+ byte[] globalId = rs.getBytes(2);
+ byte[] branchId = rs.getBytes(3);
+ xids.add(new Xid(format, globalId, branchId));
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+
+
+ for(Xid xid : xids)
+ {
+ List<RecordImpl> enqueues = new ArrayList<RecordImpl>();
+ List<RecordImpl> dequeues = new ArrayList<RecordImpl>();
+
+ PreparedStatement pstmt = conn.prepareStatement(SELECT_ALL_FROM_XID_ACTIONS);
+
+ try
+ {
+ pstmt.setLong(1, xid.getFormat());
+ pstmt.setBytes(2, xid.getGlobalId());
+ pstmt.setBytes(3, xid.getBranchId());
+
+ ResultSet rs = pstmt.executeQuery();
+ try
+ {
+ while(rs.next())
+ {
+
+ String actionType = rs.getString(1);
+ UUID queueId = UUID.fromString(rs.getString(2));
+ long messageId = rs.getLong(3);
+
+ RecordImpl record = new RecordImpl(queueId, messageId);
+ List<RecordImpl> records = "E".equals(actionType) ? enqueues : dequeues;
+ records.add(record);
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ pstmt.close();
+ }
+
+ dtxrh.dtxRecord(xid.getFormat(), xid.getGlobalId(), xid.getBranchId(),
+ enqueues.toArray(new RecordImpl[enqueues.size()]),
+ dequeues.toArray(new RecordImpl[dequeues.size()]));
+ }
+
+
+ dtxrh.completeDtxRecordRecovery();
+ }
+ finally
+ {
+ conn.close();
+ }
+
+ }
+
+ StorableMessageMetaData getMetaData(long messageId) throws SQLException
+ {
+
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_META_DATA);
+ try
+ {
+ stmt.setLong(1,messageId);
+ ResultSet rs = stmt.executeQuery();
+ try
+ {
+
+ if(rs.next())
+ {
+ byte[] dataAsBytes = getBlobAsBytes(rs, 1);
+ ByteBuffer buf = ByteBuffer.wrap(dataAsBytes);
+ buf.position(1);
+ buf = buf.slice();
+ MessageMetaDataType type = MessageMetaDataTypeRegistry.fromOrdinal(dataAsBytes[0]);
+ StorableMessageMetaData metaData = type.createMetaData(buf);
+
+ return metaData;
+ }
+ else
+ {
+ throw new RuntimeException("Meta data not found for message with id " + messageId);
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
+
+ protected abstract byte[] getBlobAsBytes(ResultSet rs, int col) throws SQLException;
+
+ private void addContent(Connection conn, long messageId, ByteBuffer src)
+ {
+ if(getLogger().isDebugEnabled())
+ {
+ getLogger().debug("Adding content for message " + messageId);
+ }
+ PreparedStatement stmt = null;
+
+ try
+ {
+ src = src.slice();
+
+ byte[] chunkData = new byte[src.limit()];
+ src.duplicate().get(chunkData);
+
+ stmt = conn.prepareStatement(INSERT_INTO_MESSAGE_CONTENT);
+ stmt.setLong(1,messageId);
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(chunkData);
+ stmt.setBinaryStream(2, bis, chunkData.length);
+ stmt.executeUpdate();
+ }
+ catch (SQLException e)
+ {
+ closeConnection(conn);
+ throw new RuntimeException("Error adding content for message " + messageId + ": " + e.getMessage(), e);
+ }
+ finally
+ {
+ closePreparedStatement(stmt);
+ }
+
+ }
+
+ public int getContent(long messageId, int offset, ByteBuffer dst)
+ {
+ Connection conn = null;
+ PreparedStatement stmt = null;
+
+ try
+ {
+ conn = newAutoCommitConnection();
+
+ stmt = conn.prepareStatement(SELECT_FROM_MESSAGE_CONTENT);
+ stmt.setLong(1,messageId);
+ ResultSet rs = stmt.executeQuery();
+
+ int written = 0;
+
+ if (rs.next())
+ {
+
+ byte[] dataAsBytes = getBlobAsBytes(rs, 1);
+ int size = dataAsBytes.length;
+
+ if (offset > size)
+ {
+ throw new RuntimeException("Offset " + offset + " is greater than message size " + size
+ + " for message id " + messageId + "!");
+
+ }
+
+ written = size - offset;
+ if(written > dst.remaining())
+ {
+ written = dst.remaining();
+ }
+
+ dst.put(dataAsBytes, offset, written);
+ }
+
+ return written;
+
+ }
+ catch (SQLException e)
+ {
+ throw new RuntimeException("Error retrieving content from offset " + offset + " for message " + messageId + ": " + e.getMessage(), e);
+ }
+ finally
+ {
+ closePreparedStatement(stmt);
+ closeConnection(conn);
+ }
+
+
+ }
+
+ @Override
+ public boolean isPersistent()
+ {
+ return true;
+ }
+
+
+ protected class JDBCTransaction implements Transaction
+ {
+ private final ConnectionWrapper _connWrapper;
+ private int _storeSizeIncrease;
+
+
+ protected JDBCTransaction()
+ {
+ try
+ {
+ _connWrapper = new ConnectionWrapper(newConnection());
+ }
+ catch (SQLException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
+ {
+ final StoredMessage storedMessage = message.getStoredMessage();
+ if(storedMessage instanceof StoredJDBCMessage)
+ {
+ try
+ {
+ ((StoredJDBCMessage) storedMessage).store(_connWrapper.getConnection());
+ }
+ catch (SQLException e)
+ {
+ throw new AMQStoreException("Exception on enqueuing message " + _messageId, e);
+ }
+ }
+ _storeSizeIncrease += storedMessage.getMetaData().getContentSize();
+ AbstractJDBCMessageStore.this.enqueueMessage(_connWrapper, queue, message.getMessageNumber());
+ }
+
+ @Override
+ public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
+ {
+ AbstractJDBCMessageStore.this.dequeueMessage(_connWrapper, queue, message.getMessageNumber());
+
+ }
+
+ @Override
+ public void commitTran() throws AMQStoreException
+ {
+ AbstractJDBCMessageStore.this.commitTran(_connWrapper);
+ storedSizeChange(_storeSizeIncrease);
+ }
+
+ @Override
+ public StoreFuture commitTranAsync() throws AMQStoreException
+ {
+ final StoreFuture storeFuture = AbstractJDBCMessageStore.this.commitTranAsync(_connWrapper);
+ storedSizeChange(_storeSizeIncrease);
+ return storeFuture;
+ }
+
+ @Override
+ public void abortTran() throws AMQStoreException
+ {
+ AbstractJDBCMessageStore.this.abortTran(_connWrapper);
+ }
+
+ @Override
+ public void removeXid(long format, byte[] globalId, byte[] branchId) throws AMQStoreException
+ {
+ AbstractJDBCMessageStore.this.removeXid(_connWrapper, format, globalId, branchId);
+ }
+
+ @Override
+ public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
+ throws AMQStoreException
+ {
+ AbstractJDBCMessageStore.this.recordXid(_connWrapper, format, globalId, branchId, enqueues, dequeues);
+ }
+ }
+
+ private class StoredJDBCMessage implements StoredMessage
+ {
+
+ private final long _messageId;
+ private final boolean _isRecovered;
+
+ private StorableMessageMetaData _metaData;
+ private volatile SoftReference<StorableMessageMetaData> _metaDataRef;
+ private byte[] _data;
+ private volatile SoftReference<byte[]> _dataRef;
+
+
+ StoredJDBCMessage(long messageId, StorableMessageMetaData metaData)
+ {
+ this(messageId, metaData, false);
+ }
+
+
+ StoredJDBCMessage(long messageId,
+ StorableMessageMetaData metaData, boolean isRecovered)
+ {
+ _messageId = messageId;
+ _isRecovered = isRecovered;
+
+ if(!_isRecovered)
+ {
+ _metaData = metaData;
+ }
+ _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData);
+ }
+
+ @Override
+ public StorableMessageMetaData getMetaData()
+ {
+ StorableMessageMetaData metaData = _metaData == null ? _metaDataRef.get() : _metaData;
+ if(metaData == null)
+ {
+ try
+ {
+ metaData = AbstractJDBCMessageStore.this.getMetaData(_messageId);
+ }
+ catch (SQLException e)
+ {
+ throw new RuntimeException(e);
+ }
+ _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData);
+ }
+
+ return metaData;
+ }
+
+ @Override
+ public long getMessageNumber()
+ {
+ return _messageId;
+ }
+
+ @Override
+ public void addContent(int offsetInMessage, ByteBuffer src)
+ {
+ src = src.slice();
+
+ if(_data == null)
+ {
+ _data = new byte[src.remaining()];
+ _dataRef = new SoftReference<byte[]>(_data);
+ src.duplicate().get(_data);
+ }
+ else
+ {
+ byte[] oldData = _data;
+ _data = new byte[oldData.length + src.remaining()];
+ _dataRef = new SoftReference<byte[]>(_data);
+
+ System.arraycopy(oldData,0,_data,0,oldData.length);
+ src.duplicate().get(_data, oldData.length, src.remaining());
+ }
+
+ }
+
+ @Override
+ public int getContent(int offsetInMessage, ByteBuffer dst)
+ {
+ byte[] data = _dataRef == null ? null : _dataRef.get();
+ if(data != null)
+ {
+ int length = Math.min(dst.remaining(), data.length - offsetInMessage);
+ dst.put(data, offsetInMessage, length);
+ return length;
+ }
+ else
+ {
+ return AbstractJDBCMessageStore.this.getContent(_messageId, offsetInMessage, dst);
+ }
+ }
+
+
+ @Override
+ public ByteBuffer getContent(int offsetInMessage, int size)
+ {
+ ByteBuffer buf = ByteBuffer.allocate(size);
+ int length = getContent(offsetInMessage, buf);
+ buf.position(0);
+ buf.limit(length);
+ return buf;
+ }
+
+ @Override
+ public synchronized StoreFuture flushToStore()
+ {
+ Connection conn = null;
+ try
+ {
+ if(!stored())
+ {
+ conn = newConnection();
+
+ store(conn);
+
+ conn.commit();
+ storedSizeChange(getMetaData().getContentSize());
+ }
+ }
+ catch (SQLException e)
+ {
+ if(getLogger().isDebugEnabled())
+ {
+ getLogger().debug("Error when trying to flush message " + _messageId + " to store: " + e);
+ }
+ throw new RuntimeException(e);
+ }
+ finally
+ {
+ closeConnection(conn);
+ }
+ return StoreFuture.IMMEDIATE_FUTURE;
+ }
+
+ @Override
+ public void remove()
+ {
+ int delta = getMetaData().getContentSize();
+ AbstractJDBCMessageStore.this.removeMessage(_messageId);
+ storedSizeChange(-delta);
+ }
+
+ private synchronized void store(final Connection conn) throws SQLException
+ {
+ if (!stored())
+ {
+ try
+ {
+ storeMetaData(conn, _messageId, _metaData);
+ AbstractJDBCMessageStore.this.addContent(conn, _messageId,
+ _data == null ? ByteBuffer.allocate(0) : ByteBuffer.wrap(_data));
+ }
+ finally
+ {
+ _metaData = null;
+ _data = null;
+ }
+
+ if(getLogger().isDebugEnabled())
+ {
+ getLogger().debug("Storing message " + _messageId + " to store");
+ }
+ }
+ }
+
+ private boolean stored()
+ {
+ return _metaData == null || _isRecovered;
+ }
+ }
+
+ protected void closeConnection(final Connection conn)
+ {
+ if(conn != null)
+ {
+ try
+ {
+ conn.close();
+ }
+ catch (SQLException e)
+ {
+ getLogger().error("Problem closing connection", e);
+ }
+ }
+ }
+
+ protected void closePreparedStatement(final PreparedStatement stmt)
+ {
+ if (stmt != null)
+ {
+ try
+ {
+ stmt.close();
+ }
+ catch(SQLException e)
+ {
+ getLogger().error("Problem closing prepared statement", e);
+ }
+ }
+ }
+
+ @Override
+ public void addEventListener(EventListener eventListener, Event... events)
+ {
+ _eventManager.addEventListener(eventListener, events);
+ }
+
+ private void insertConfiguredObject(ConfiguredObjectRecord configuredObject) throws AMQStoreException
+ {
+ if (_stateManager.isInState(State.ACTIVE))
+ {
+ try
+ {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT);
+ try
+ {
+ stmt.setString(1, configuredObject.getId().toString());
+ ResultSet rs = stmt.executeQuery();
+ try
+ {
+ // If we don't have any data in the result set then we can add this configured object
+ if (!rs.next())
+ {
+ PreparedStatement insertStmt = conn.prepareStatement(INSERT_INTO_CONFIGURED_OBJECTS);
+ try
+ {
+ insertStmt.setString(1, configuredObject.getId().toString());
+ insertStmt.setString(2, configuredObject.getType());
+ if(configuredObject.getAttributes() == null)
+ {
+ insertStmt.setNull(3, Types.BLOB);
+ }
+ else
+ {
+ byte[] attributesAsBytes = configuredObject.getAttributes().getBytes(UTF8_CHARSET);
+ ByteArrayInputStream bis = new ByteArrayInputStream(attributesAsBytes);
+ insertStmt.setBinaryStream(3, bis, attributesAsBytes.length);
+ }
+ insertStmt.execute();
+ }
+ finally
+ {
+ insertStmt.close();
+ }
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new AMQStoreException("Error inserting of configured object " + configuredObject + " into database: " + e.getMessage(), e);
+ }
+ }
+ }
+
+ private int removeConfiguredObject(UUID id) throws AMQStoreException
+ {
+ int results = 0;
+ try
+ {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_CONFIGURED_OBJECTS);
+ try
+ {
+ stmt.setString(1, id.toString());
+ results = stmt.executeUpdate();
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new AMQStoreException("Error deleting of configured object with id " + id + " from database: " + e.getMessage(), e);
+ }
+ return results;
+ }
+
+ private void updateConfiguredObject(final ConfiguredObjectRecord configuredObject) throws AMQStoreException
+ {
+ if (_stateManager.isInState(State.ACTIVE))
+ {
+ try
+ {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT);
+ try
+ {
+ stmt.setString(1, configuredObject.getId().toString());
+ ResultSet rs = stmt.executeQuery();
+ try
+ {
+ if (rs.next())
+ {
+ PreparedStatement stmt2 = conn.prepareStatement(UPDATE_CONFIGURED_OBJECTS);
+ try
+ {
+ stmt2.setString(1, configuredObject.getType());
+ if (configuredObject.getAttributes() != null)
+ {
+ byte[] attributesAsBytes = configuredObject.getAttributes().getBytes(UTF8_CHARSET);
+ ByteArrayInputStream bis = new ByteArrayInputStream(attributesAsBytes);
+ stmt2.setBinaryStream(2, bis, attributesAsBytes.length);
+ }
+ else
+ {
+ stmt2.setNull(2, Types.BLOB);
+ }
+ stmt2.setString(3, configuredObject.getId().toString());
+ stmt2.execute();
+ }
+ finally
+ {
+ stmt2.close();
+ }
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new AMQStoreException("Error updating configured object " + configuredObject + " in database: " + e.getMessage(), e);
+ }
+ }
+ }
+
+ private ConfiguredObjectRecord loadConfiguredObject(final UUID id) throws AMQStoreException
+ {
+ ConfiguredObjectRecord result = null;
+ try
+ {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT);
+ try
+ {
+ stmt.setString(1, id.toString());
+ ResultSet rs = stmt.executeQuery();
+ try
+ {
+ if (rs.next())
+ {
+ String type = rs.getString(1);
+ String attributes = getBlobAsString(rs, 2);
+ result = new ConfiguredObjectRecord(id, type, attributes);
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new AMQStoreException("Error loading of configured object with id " + id + " from database: "
+ + e.getMessage(), e);
+ }
+ return result;
+ }
+
+ private List<ConfiguredObjectRecord> loadConfiguredObjects() throws SQLException
+ {
+ ArrayList<ConfiguredObjectRecord> results = new ArrayList<ConfiguredObjectRecord>();
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_CONFIGURED_OBJECTS);
+ try
+ {
+ ResultSet rs = stmt.executeQuery();
+ try
+ {
+ while (rs.next())
+ {
+ String id = rs.getString(1);
+ String objectType = rs.getString(2);
+ String attributes = getBlobAsString(rs, 3);
+ results.add(new ConfiguredObjectRecord(UUID.fromString(id), objectType, attributes));
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ finally
+ {
+ conn.close();
+ }
+ return results;
+ }
+
+ protected abstract String getBlobAsString(ResultSet rs, int col) throws SQLException;
+
+ protected abstract void storedSizeChange(int storeSizeIncrease);
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java
index e89bdd57fb..d0e48b5e8a 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java
@@ -21,14 +21,7 @@
package org.apache.qpid.server.store.derby;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
import java.io.File;
-import java.io.IOException;
-import java.lang.ref.SoftReference;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Connection;
@@ -37,1853 +30,209 @@ import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.configuration.Configuration;
import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.AMQStoreException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.binding.Binding;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.message.EnqueableMessage;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.store.*;
-import org.apache.qpid.server.plugin.MessageMetaDataType;
-import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BindingRecoveryHandler;
-import org.apache.qpid.server.store.ConfigurationRecoveryHandler.ExchangeRecoveryHandler;
-import org.apache.qpid.server.store.ConfigurationRecoveryHandler.QueueRecoveryHandler;
+import org.apache.qpid.server.store.AbstractJDBCMessageStore;
+import org.apache.qpid.server.store.Event;
+import org.apache.qpid.server.store.EventListener;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.MessageStoreConstants;
/**
* An implementation of a {@link MessageStore} that uses Apache Derby as the persistence
* mechanism.
*
- * TODO extract the SQL statements into a generic JDBC store
*/
-public class DerbyMessageStore implements MessageStore
+public class DerbyMessageStore extends AbstractJDBCMessageStore implements MessageStore
{
private static final Logger _logger = Logger.getLogger(DerbyMessageStore.class);
private static final String SQL_DRIVER_NAME = "org.apache.derby.jdbc.EmbeddedDriver";
- private static final String DB_VERSION_TABLE_NAME = "QPID_DB_VERSION";
-
- private static final String QUEUE_ENTRY_TABLE_NAME = "QPID_QUEUE_ENTRIES";
-
- private static final String META_DATA_TABLE_NAME = "QPID_MESSAGE_METADATA";
- private static final String MESSAGE_CONTENT_TABLE_NAME = "QPID_MESSAGE_CONTENT";
-
- private static final String LINKS_TABLE_NAME = "QPID_LINKS";
- private static final String BRIDGES_TABLE_NAME = "QPID_BRIDGES";
-
- private static final String XID_TABLE_NAME = "QPID_XIDS";
- private static final String XID_ACTIONS_TABLE_NAME = "QPID_XID_ACTIONS";
-
- private static final String CONFIGURED_OBJECTS_TABLE_NAME = "QPID_CONFIGURED_OBJECTS";
-
- private static final int DB_VERSION = 6;
-
-
-
- private static Class<Driver> DRIVER_CLASS;
public static final String MEMORY_STORE_LOCATION = ":memory:";
- private final AtomicLong _messageId = new AtomicLong(0);
- private AtomicBoolean _closed = new AtomicBoolean(false);
-
- private String _connectionURL;
-
private static final String TABLE_EXISTANCE_QUERY = "SELECT 1 FROM SYS.SYSTABLES WHERE TABLENAME = ?";
- private static final String CREATE_DB_VERSION_TABLE = "CREATE TABLE "+DB_VERSION_TABLE_NAME+" ( version int not null )";
- private static final String INSERT_INTO_DB_VERSION = "INSERT INTO "+DB_VERSION_TABLE_NAME+" ( version ) VALUES ( ? )";
-
- private static final String CREATE_QUEUE_ENTRY_TABLE = "CREATE TABLE "+QUEUE_ENTRY_TABLE_NAME+" ( queue_id varchar(36) not null, message_id bigint not null, PRIMARY KEY (queue_id, message_id) )";
- private static final String INSERT_INTO_QUEUE_ENTRY = "INSERT INTO " + QUEUE_ENTRY_TABLE_NAME + " (queue_id, message_id) values (?,?)";
- private static final String DELETE_FROM_QUEUE_ENTRY = "DELETE FROM " + QUEUE_ENTRY_TABLE_NAME + " WHERE queue_id = ? AND message_id =?";
- private static final String SELECT_FROM_QUEUE_ENTRY = "SELECT queue_id, message_id FROM " + QUEUE_ENTRY_TABLE_NAME + " ORDER BY queue_id, message_id";
-
-
- private static final String CREATE_META_DATA_TABLE = "CREATE TABLE " + META_DATA_TABLE_NAME
- + " ( message_id bigint not null, meta_data blob, PRIMARY KEY ( message_id ) )";
- private static final String CREATE_MESSAGE_CONTENT_TABLE = "CREATE TABLE " + MESSAGE_CONTENT_TABLE_NAME
- + " ( message_id bigint not null, content blob , PRIMARY KEY (message_id) )";
-
- private static final String INSERT_INTO_MESSAGE_CONTENT = "INSERT INTO " + MESSAGE_CONTENT_TABLE_NAME
- + "( message_id, content ) values (?, ?)";
- private static final String SELECT_FROM_MESSAGE_CONTENT = "SELECT content FROM " + MESSAGE_CONTENT_TABLE_NAME
- + " WHERE message_id = ?";
- private static final String DELETE_FROM_MESSAGE_CONTENT = "DELETE FROM " + MESSAGE_CONTENT_TABLE_NAME
- + " WHERE message_id = ?";
-
- private static final String INSERT_INTO_META_DATA = "INSERT INTO " + META_DATA_TABLE_NAME + "( message_id , meta_data ) values (?, ?)";;
- private static final String SELECT_FROM_META_DATA =
- "SELECT meta_data FROM " + META_DATA_TABLE_NAME + " WHERE message_id = ?";
- private static final String DELETE_FROM_META_DATA = "DELETE FROM " + META_DATA_TABLE_NAME + " WHERE message_id = ?";
- private static final String SELECT_ALL_FROM_META_DATA = "SELECT message_id, meta_data FROM " + META_DATA_TABLE_NAME;
-
- private static final String CREATE_LINKS_TABLE =
- "CREATE TABLE "+LINKS_TABLE_NAME+" ( id_lsb bigint not null,"
- + " id_msb bigint not null,"
- + " create_time bigint not null,"
- + " arguments blob, PRIMARY KEY ( id_lsb, id_msb ))";
- private static final String SELECT_FROM_LINKS =
- "SELECT create_time, arguments FROM " + LINKS_TABLE_NAME + " WHERE id_lsb = ? and id_msb";
- private static final String DELETE_FROM_LINKS = "DELETE FROM " + LINKS_TABLE_NAME
- + " WHERE id_lsb = ? and id_msb = ?";
- private static final String SELECT_ALL_FROM_LINKS = "SELECT id_lsb, id_msb, create_time, "
- + "arguments FROM " + LINKS_TABLE_NAME;
- private static final String FIND_LINK = "SELECT id_lsb, id_msb FROM " + LINKS_TABLE_NAME + " WHERE id_lsb = ? and"
- + " id_msb = ?";
- private static final String INSERT_INTO_LINKS = "INSERT INTO " + LINKS_TABLE_NAME + "( id_lsb, "
- + "id_msb, create_time, arguments ) values (?, ?, ?, ?)";
-
-
- private static final String CREATE_BRIDGES_TABLE =
- "CREATE TABLE "+BRIDGES_TABLE_NAME+" ( id_lsb bigint not null,"
- + " id_msb bigint not null,"
- + " create_time bigint not null,"
- + " link_id_lsb bigint not null,"
- + " link_id_msb bigint not null,"
- + " arguments blob, PRIMARY KEY ( id_lsb, id_msb ))";
- private static final String SELECT_FROM_BRIDGES =
- "SELECT create_time, link_id_lsb, link_id_msb, arguments FROM "
- + BRIDGES_TABLE_NAME + " WHERE id_lsb = ? and id_msb = ?";
- private static final String DELETE_FROM_BRIDGES = "DELETE FROM " + BRIDGES_TABLE_NAME
- + " WHERE id_lsb = ? and id_msb = ?";
- private static final String SELECT_ALL_FROM_BRIDGES = "SELECT id_lsb, id_msb, "
- + " create_time,"
- + " link_id_lsb, link_id_msb, "
- + "arguments FROM " + BRIDGES_TABLE_NAME
- + " WHERE link_id_lsb = ? and link_id_msb = ?";
- private static final String FIND_BRIDGE = "SELECT id_lsb, id_msb FROM " + BRIDGES_TABLE_NAME +
- " WHERE id_lsb = ? and id_msb = ?";
- private static final String INSERT_INTO_BRIDGES = "INSERT INTO " + BRIDGES_TABLE_NAME + "( id_lsb, id_msb, "
- + "create_time, "
- + "link_id_lsb, link_id_msb, "
- + "arguments )"
- + " values (?, ?, ?, ?, ?, ?)";
-
- private static final String CREATE_XIDS_TABLE =
- "CREATE TABLE "+XID_TABLE_NAME+" ( format bigint not null,"
- + " global_id varchar(64) for bit data, branch_id varchar(64) for bit data, PRIMARY KEY ( format, " +
- "global_id, branch_id ))";
- private static final String INSERT_INTO_XIDS =
- "INSERT INTO "+XID_TABLE_NAME+" ( format, global_id, branch_id ) values (?, ?, ?)";
- private static final String DELETE_FROM_XIDS = "DELETE FROM " + XID_TABLE_NAME
- + " WHERE format = ? and global_id = ? and branch_id = ?";
- private static final String SELECT_ALL_FROM_XIDS = "SELECT format, global_id, branch_id FROM " + XID_TABLE_NAME;
-
-
- private static final String CREATE_XID_ACTIONS_TABLE =
- "CREATE TABLE "+XID_ACTIONS_TABLE_NAME+" ( format bigint not null,"
- + " global_id varchar(64) for bit data not null, branch_id varchar(64) for bit data not null, " +
- "action_type char not null, queue_id varchar(36) not null, message_id bigint not null" +
- ", PRIMARY KEY ( " +
- "format, global_id, branch_id, action_type, queue_id, message_id))";
- private static final String INSERT_INTO_XID_ACTIONS =
- "INSERT INTO "+XID_ACTIONS_TABLE_NAME+" ( format, global_id, branch_id, action_type, " +
- "queue_id, message_id ) values (?,?,?,?,?,?) ";
- private static final String DELETE_FROM_XID_ACTIONS = "DELETE FROM " + XID_ACTIONS_TABLE_NAME
- + " WHERE format = ? and global_id = ? and branch_id = ?";
- private static final String SELECT_ALL_FROM_XID_ACTIONS =
- "SELECT action_type, queue_id, message_id FROM " + XID_ACTIONS_TABLE_NAME +
- " WHERE format = ? and global_id = ? and branch_id = ?";
-
- private static final String CREATE_CONFIGURED_OBJECTS_TABLE = "CREATE TABLE " + CONFIGURED_OBJECTS_TABLE_NAME
- + " ( id VARCHAR(36) not null, object_type varchar(255), attributes blob, PRIMARY KEY (id))";
- private static final String INSERT_INTO_CONFIGURED_OBJECTS = "INSERT INTO " + CONFIGURED_OBJECTS_TABLE_NAME
- + " ( id, object_type, attributes) VALUES (?,?,?)";
- private static final String UPDATE_CONFIGURED_OBJECTS = "UPDATE " + CONFIGURED_OBJECTS_TABLE_NAME
- + " set object_type =?, attributes = ? where id = ?";
- private static final String DELETE_FROM_CONFIGURED_OBJECTS = "DELETE FROM " + CONFIGURED_OBJECTS_TABLE_NAME
- + " where id = ?";
- private static final String FIND_CONFIGURED_OBJECT = "SELECT object_type, attributes FROM " + CONFIGURED_OBJECTS_TABLE_NAME
- + " where id = ?";
- private static final String SELECT_FROM_CONFIGURED_OBJECTS = "SELECT id, object_type, attributes FROM " + CONFIGURED_OBJECTS_TABLE_NAME;
-
- private final Charset UTF8_CHARSET = Charset.forName("UTF-8");
-
private static final String DERBY_SINGLE_DB_SHUTDOWN_CODE = "08006";
public static final String TYPE = "DERBY";
- private final StateManager _stateManager;
-
- private final EventManager _eventManager = new EventManager();
-
private long _totalStoreSize;
private boolean _limitBusted;
private long _persistentSizeLowThreshold;
private long _persistentSizeHighThreshold;
- private MessageStoreRecoveryHandler _messageRecoveryHandler;
-
- private TransactionLogRecoveryHandler _tlogRecoveryHandler;
-
- private ConfigurationRecoveryHandler _configRecoveryHandler;
private String _storeLocation;
+ private Class<Driver> _driverClass;
public DerbyMessageStore()
{
- _stateManager = new StateManager(_eventManager);
}
- private ConfiguredObjectHelper _configuredObjectHelper = new ConfiguredObjectHelper();
-
- @Override
- public void configureConfigStore(String name,
- ConfigurationRecoveryHandler configRecoveryHandler,
- Configuration storeConfiguration) throws Exception
+ protected Logger getLogger()
{
- _stateManager.attainState(State.INITIALISING);
- _configRecoveryHandler = configRecoveryHandler;
-
- commonConfiguration(name, storeConfiguration);
-
+ return _logger;
}
@Override
- public void configureMessageStore(String name,
- MessageStoreRecoveryHandler recoveryHandler,
- TransactionLogRecoveryHandler tlogRecoveryHandler,
- Configuration storeConfiguration) throws Exception
+ protected String getSqlBlobType()
{
- _tlogRecoveryHandler = tlogRecoveryHandler;
- _messageRecoveryHandler = recoveryHandler;
-
- _stateManager.attainState(State.INITIALISED);
+ return "blob";
}
@Override
- public void activate() throws Exception
- {
- _stateManager.attainState(State.ACTIVATING);
-
- // this recovers durable exchanges, queues, and bindings
- recoverConfiguration(_configRecoveryHandler);
- recoverMessages(_messageRecoveryHandler);
- TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh = recoverQueueEntries(_tlogRecoveryHandler);
- recoverXids(dtxrh);
-
- _stateManager.attainState(State.ACTIVE);
- }
-
- private void commonConfiguration(String name, Configuration storeConfiguration)
- throws ClassNotFoundException, SQLException
- {
- initialiseDriver();
-
- //Update to pick up QPID_WORK and use that as the default location not just derbyDB
-
- final String databasePath = storeConfiguration.getString(MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY, System.getProperty("QPID_WORK")
- + File.separator + "derbyDB");
-
- if(!MEMORY_STORE_LOCATION.equals(databasePath))
- {
- File environmentPath = new File(databasePath);
- if (!environmentPath.exists())
- {
- if (!environmentPath.mkdirs())
- {
- throw new IllegalArgumentException("Environment path " + environmentPath + " could not be read or created. "
- + "Ensure the path is correct and that the permissions are correct.");
- }
- }
- }
-
- _storeLocation = databasePath;
-
- _persistentSizeHighThreshold = storeConfiguration.getLong(MessageStoreConstants.OVERFULL_SIZE_PROPERTY, -1l);
- _persistentSizeLowThreshold = storeConfiguration.getLong(MessageStoreConstants.UNDERFULL_SIZE_PROPERTY, _persistentSizeHighThreshold);
- if(_persistentSizeLowThreshold > _persistentSizeHighThreshold || _persistentSizeLowThreshold < 0l)
- {
- _persistentSizeLowThreshold = _persistentSizeHighThreshold;
- }
-
- createOrOpenDatabase(name, databasePath);
-
- Connection conn = newAutoCommitConnection();;
- try
- {
- _totalStoreSize = getSizeOnDisk(conn);
- }
- finally
- {
- conn.close();
- }
- }
-
- private static synchronized void initialiseDriver() throws ClassNotFoundException
- {
- if(DRIVER_CLASS == null)
- {
- DRIVER_CLASS = (Class<Driver>) Class.forName(SQL_DRIVER_NAME);
- }
- }
-
- private void createOrOpenDatabase(String name, final String environmentPath) throws SQLException
- {
- //FIXME this the _vhost name should not be added here, but derby wont use an empty directory as was possibly just created.
- _connectionURL = "jdbc:derby" + (environmentPath.equals(MEMORY_STORE_LOCATION) ? environmentPath : ":" + environmentPath + "/") + name + ";create=true";
-
- Connection conn = newAutoCommitConnection();
-
- createVersionTable(conn);
- createConfiguredObjectsTable(conn);
- createQueueEntryTable(conn);
- createMetaDataTable(conn);
- createMessageContentTable(conn);
- createLinkTable(conn);
- createBridgeTable(conn);
- createXidTable(conn);
- createXidActionTable(conn);
- conn.close();
- }
-
-
-
- private void createVersionTable(final Connection conn) throws SQLException
- {
- if(!tableExists(DB_VERSION_TABLE_NAME, conn))
- {
- Statement stmt = conn.createStatement();
- try
- {
- stmt.execute(CREATE_DB_VERSION_TABLE);
- }
- finally
- {
- stmt.close();
- }
-
- PreparedStatement pstmt = conn.prepareStatement(INSERT_INTO_DB_VERSION);
- try
- {
- pstmt.setInt(1, DB_VERSION);
- pstmt.execute();
- }
- finally
- {
- pstmt.close();
- }
- }
-
- }
-
- private void createConfiguredObjectsTable(final Connection conn) throws SQLException
- {
- if(!tableExists(CONFIGURED_OBJECTS_TABLE_NAME, conn))
- {
- Statement stmt = conn.createStatement();
- try
- {
- stmt.execute(CREATE_CONFIGURED_OBJECTS_TABLE);
- }
- finally
- {
- stmt.close();
- }
- }
- }
-
- private void createQueueEntryTable(final Connection conn) throws SQLException
- {
- if(!tableExists(QUEUE_ENTRY_TABLE_NAME, conn))
- {
- Statement stmt = conn.createStatement();
- try
- {
- stmt.execute(CREATE_QUEUE_ENTRY_TABLE);
- }
- finally
- {
- stmt.close();
- }
- }
-
- }
-
- private void createMetaDataTable(final Connection conn) throws SQLException
- {
- if(!tableExists(META_DATA_TABLE_NAME, conn))
- {
- Statement stmt = conn.createStatement();
- try
- {
- stmt.execute(CREATE_META_DATA_TABLE);
- }
- finally
- {
- stmt.close();
- }
- }
-
- }
-
-
- private void createMessageContentTable(final Connection conn) throws SQLException
- {
- if(!tableExists(MESSAGE_CONTENT_TABLE_NAME, conn))
- {
- Statement stmt = conn.createStatement();
- try
- {
- stmt.execute(CREATE_MESSAGE_CONTENT_TABLE);
- }
- finally
- {
- stmt.close();
- }
- }
-
- }
-
- private void createLinkTable(final Connection conn) throws SQLException
- {
- if(!tableExists(LINKS_TABLE_NAME, conn))
- {
- Statement stmt = conn.createStatement();
- try
- {
- stmt.execute(CREATE_LINKS_TABLE);
- }
- finally
- {
- stmt.close();
- }
- }
- }
-
-
- private void createBridgeTable(final Connection conn) throws SQLException
+ protected String getSqlVarBinaryType(int size)
{
- if(!tableExists(BRIDGES_TABLE_NAME, conn))
- {
- Statement stmt = conn.createStatement();
- try
- {
- stmt.execute(CREATE_BRIDGES_TABLE);
- }
- finally
- {
- stmt.close();
- }
- }
+ return "varchar("+size+") for bit data";
}
- private void createXidTable(final Connection conn) throws SQLException
- {
- if(!tableExists(XID_TABLE_NAME, conn))
- {
- Statement stmt = conn.createStatement();
- try
- {
- stmt.execute(CREATE_XIDS_TABLE);
- }
- finally
- {
- stmt.close();
- }
- }
- }
-
-
- private void createXidActionTable(final Connection conn) throws SQLException
- {
- if(!tableExists(XID_ACTIONS_TABLE_NAME, conn))
- {
- Statement stmt = conn.createStatement();
- try
- {
- stmt.execute(CREATE_XID_ACTIONS_TABLE);
- }
- finally
- {
- stmt.close();
- }
- }
- }
-
- private boolean tableExists(final String tableName, final Connection conn) throws SQLException
- {
- PreparedStatement stmt = conn.prepareStatement(TABLE_EXISTANCE_QUERY);
- try
- {
- stmt.setString(1, tableName);
- ResultSet rs = stmt.executeQuery();
- try
- {
- return rs.next();
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
- }
-
- private void recoverConfiguration(ConfigurationRecoveryHandler recoveryHandler) throws AMQException
+ @Override
+ protected String getSqlBigIntType()
{
- try
- {
- List<ConfiguredObjectRecord> configuredObjects = loadConfiguredObjects();
-
- ExchangeRecoveryHandler erh = recoveryHandler.begin(this);
- _configuredObjectHelper.recoverExchanges(erh, configuredObjects);
-
- QueueRecoveryHandler qrh = erh.completeExchangeRecovery();
- _configuredObjectHelper.recoverQueues(qrh, configuredObjects);
-
- BindingRecoveryHandler brh = qrh.completeQueueRecovery();
- _configuredObjectHelper.recoverBindings(brh, configuredObjects);
-
- brh.completeBindingRecovery();
- }
- catch (SQLException e)
- {
- throw new AMQStoreException("Error recovering persistent state: " + e.getMessage(), e);
- }
+ return "bigint";
}
- @Override
- public void close() throws Exception
+ protected void doClose() throws SQLException
{
- _closed.getAndSet(true);
- _stateManager.attainState(State.CLOSING);
-
try
{
Connection conn = DriverManager.getConnection(_connectionURL + ";shutdown=true");
// Shouldn't reach this point - shutdown=true should throw SQLException
conn.close();
- _logger.error("Unable to shut down the store");
+ getLogger().error("Unable to shut down the store");
}
catch (SQLException e)
{
- if (e.getSQLState().equalsIgnoreCase(DERBY_SINGLE_DB_SHUTDOWN_CODE))
+ if (e.getSQLState().equalsIgnoreCase(DerbyMessageStore.DERBY_SINGLE_DB_SHUTDOWN_CODE))
{
//expected and represents a clean shutdown of this database only, do nothing.
}
else
{
- _logger.error("Exception whilst shutting down the store: " + e);
- }
- }
-
- _stateManager.attainState(State.CLOSED);
- }
-
- @Override
- public StoredMessage addMessage(StorableMessageMetaData metaData)
- {
- if(metaData.isPersistent())
- {
- return new StoredDerbyMessage(_messageId.incrementAndGet(), metaData);
- }
- else
- {
- return new StoredMemoryMessage(_messageId.incrementAndGet(), metaData);
- }
- }
-
- public StoredMessage getMessage(long messageNumber)
- {
- return null;
- }
-
- public void removeMessage(long messageId)
- {
- try
- {
- Connection conn = newConnection();
- try
- {
- PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_META_DATA);
- try
- {
- stmt.setLong(1,messageId);
- int results = stmt.executeUpdate();
- stmt.close();
-
- if (results == 0)
- {
- _logger.warn("Message metadata not found for message id " + messageId);
- }
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Deleted metadata for message " + messageId);
- }
-
- stmt = conn.prepareStatement(DELETE_FROM_MESSAGE_CONTENT);
- stmt.setLong(1,messageId);
- results = stmt.executeUpdate();
- }
- finally
- {
- stmt.close();
- }
- conn.commit();
- }
- catch(SQLException e)
- {
- try
- {
- conn.rollback();
- }
- catch(SQLException t)
- {
- // ignore - we are re-throwing underlying exception
- }
-
+ getLogger().error("Exception whilst shutting down the store: " + e);
throw e;
-
}
- finally
- {
- conn.close();
- }
- }
- catch (SQLException e)
- {
- throw new RuntimeException("Error removing message with id " + messageId + " from database: " + e.getMessage(), e);
- }
-
- }
-
- @Override
- public void createExchange(Exchange exchange) throws AMQStoreException
- {
- if (_stateManager.isInState(State.ACTIVE))
- {
- ConfiguredObjectRecord configuredObject = _configuredObjectHelper.createExchangeConfiguredObject(exchange);
- insertConfiguredObject(configuredObject);
- }
-
- }
-
- @Override
- public void removeExchange(Exchange exchange) throws AMQStoreException
- {
- int results = removeConfiguredObject(exchange.getId());
- if (results == 0)
- {
- throw new AMQStoreException("Exchange " + exchange.getName() + " with id " + exchange.getId() + " not found");
- }
- }
-
- @Override
- public void bindQueue(Binding binding)
- throws AMQStoreException
- {
- if (_stateManager.isInState(State.ACTIVE))
- {
- ConfiguredObjectRecord configuredObject = _configuredObjectHelper.createBindingConfiguredObject(binding);
- insertConfiguredObject(configuredObject);
}
}
@Override
- public void unbindQueue(Binding binding)
- throws AMQStoreException
+ protected void implementationSpecificConfiguration(String name, Configuration storeConfiguration)
+ throws ClassNotFoundException
{
- int results = removeConfiguredObject(binding.getId());
- if (results == 0)
- {
- throw new AMQStoreException("Binding " + binding + " not found");
- }
- }
-
- @Override
- public void createQueue(AMQQueue queue) throws AMQStoreException
- {
- createQueue(queue, null);
- }
-
- @Override
- public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQStoreException
- {
- _logger.debug("public void createQueue(AMQQueue queue = " + queue + "): called");
-
- if (_stateManager.isInState(State.ACTIVE))
- {
- ConfiguredObjectRecord queueConfiguredObject = _configuredObjectHelper.createQueueConfiguredObject(queue, arguments);
- insertConfiguredObject(queueConfiguredObject);
- }
- }
-
- /**
- * Updates the specified queue in the persistent store, IF it is already present. If the queue
- * is not present in the store, it will not be added.
- *
- * NOTE: Currently only updates the exclusivity.
- *
- * @param queue The queue to update the entry for.
- * @throws AMQStoreException If the operation fails for any reason.
- */
- @Override
- public void updateQueue(final AMQQueue queue) throws AMQStoreException
- {
- if (_stateManager.isInState(State.ACTIVE))
- {
- ConfiguredObjectRecord queueConfiguredObject = loadConfiguredObject(queue.getId());
- if (queueConfiguredObject != null)
- {
- ConfiguredObjectRecord newQueueRecord = _configuredObjectHelper.updateQueueConfiguredObject(queue, queueConfiguredObject);
- updateConfiguredObject(newQueueRecord);
- }
- }
-
- }
-
- /**
- * Convenience method to create a new Connection configured for TRANSACTION_READ_COMMITED
- * isolation and with auto-commit transactions enabled.
- */
- private Connection newAutoCommitConnection() throws SQLException
- {
- final Connection connection = newConnection();
- try
- {
- connection.setAutoCommit(true);
- }
- catch (SQLException sqlEx)
- {
-
- try
- {
- connection.close();
- }
- finally
- {
- throw sqlEx;
- }
- }
+ //Update to pick up QPID_WORK and use that as the default location not just derbyDB
- return connection;
- }
+ _driverClass = (Class<Driver>) Class.forName(SQL_DRIVER_NAME);
- /**
- * Convenience method to create a new Connection configured for TRANSACTION_READ_COMMITED
- * isolation and with auto-commit transactions disabled.
- */
- private Connection newConnection() throws SQLException
- {
- final Connection connection = DriverManager.getConnection(_connectionURL);
- try
- {
- connection.setAutoCommit(false);
- connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
- }
- catch (SQLException sqlEx)
- {
- try
- {
- connection.close();
- }
- finally
- {
- throw sqlEx;
- }
- }
- return connection;
- }
-
- @Override
- public void removeQueue(final AMQQueue queue) throws AMQStoreException
- {
- AMQShortString name = queue.getNameShortString();
- _logger.debug("public void removeQueue(AMQShortString name = " + name + "): called");
- int results = removeConfiguredObject(queue.getId());
- if (results == 0)
- {
- throw new AMQStoreException("Queue " + name + " with id " + queue.getId() + " not found");
- }
- }
+ final String databasePath = storeConfiguration.getString(MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY, System.getProperty("QPID_WORK")
+ + File.separator + "derbyDB");
- private byte[] convertStringMapToBytes(final Map<String, String> arguments) throws AMQStoreException
- {
- byte[] argumentBytes;
- if(arguments == null)
- {
- argumentBytes = new byte[0];
- }
- else
+ if(!MEMORY_STORE_LOCATION.equals(databasePath))
{
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- DataOutputStream dos = new DataOutputStream(bos);
-
-
- try
+ File environmentPath = new File(databasePath);
+ if (!environmentPath.exists())
{
- dos.writeInt(arguments.size());
- for(Map.Entry<String,String> arg : arguments.entrySet())
+ if (!environmentPath.mkdirs())
{
- dos.writeUTF(arg.getKey());
- dos.writeUTF(arg.getValue());
+ throw new IllegalArgumentException("Environment path " + environmentPath + " could not be read or created. "
+ + "Ensure the path is correct and that the permissions are correct.");
}
}
- catch (IOException e)
- {
- // This should never happen
- throw new AMQStoreException(e.getMessage(), e);
- }
- argumentBytes = bos.toByteArray();
}
- return argumentBytes;
- }
-
-
-
- @Override
- public Transaction newTransaction()
- {
- return new DerbyTransaction();
- }
-
- public void enqueueMessage(ConnectionWrapper connWrapper, final TransactionLogResource queue, Long messageId) throws AMQStoreException
- {
- Connection conn = connWrapper.getConnection();
+ _storeLocation = databasePath;
- try
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Enqueuing message " + messageId + " on queue " + (queue instanceof AMQQueue ? ((AMQQueue)queue).getName() : "" ) + queue.getId()+ "[Connection" + conn + "]");
- }
-
- PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_QUEUE_ENTRY);
- try
- {
- stmt.setString(1, queue.getId().toString());
- stmt.setLong(2,messageId);
- stmt.executeUpdate();
- }
- finally
- {
- stmt.close();
- }
- }
- catch (SQLException e)
+ _persistentSizeHighThreshold = storeConfiguration.getLong(MessageStoreConstants.OVERFULL_SIZE_PROPERTY, -1l);
+ _persistentSizeLowThreshold = storeConfiguration.getLong(MessageStoreConstants.UNDERFULL_SIZE_PROPERTY, _persistentSizeHighThreshold);
+ if(_persistentSizeLowThreshold > _persistentSizeHighThreshold || _persistentSizeLowThreshold < 0l)
{
- _logger.error("Failed to enqueue: " + e.getMessage(), e);
- throw new AMQStoreException("Error writing enqueued message with id " + messageId + " for queue " + (queue instanceof AMQQueue ? ((AMQQueue)queue).getName() : "" ) + " with id " + queue.getId()
- + " to database", e);
+ _persistentSizeLowThreshold = _persistentSizeHighThreshold;
}
- }
-
- public void dequeueMessage(ConnectionWrapper connWrapper, final TransactionLogResource queue, Long messageId) throws AMQStoreException
- {
-
- Connection conn = connWrapper.getConnection();
-
-
- try
- {
- PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_QUEUE_ENTRY);
- try
- {
- stmt.setString(1, queue.getId().toString());
- stmt.setLong(2,messageId);
- int results = stmt.executeUpdate();
-
+ //FIXME this the _vhost name should not be added here, but derby wont use an empty directory as was possibly just created.
+ _connectionURL = "jdbc:derby" + (databasePath.equals(MEMORY_STORE_LOCATION) ? databasePath: ":" + databasePath+ "/") + name + ";create=true";
- if(results != 1)
- {
- throw new AMQStoreException("Unable to find message with id " + messageId + " on queue " + (queue instanceof AMQQueue ? ((AMQQueue)queue).getName() : "" )
- + " with id " + queue.getId());
- }
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Dequeuing message " + messageId + " on queue " + (queue instanceof AMQQueue ? ((AMQQueue)queue).getName() : "" )
- + " with id " + queue.getId());
- }
- }
- finally
- {
- stmt.close();
- }
- }
- catch (SQLException e)
- {
- _logger.error("Failed to dequeue: " + e.getMessage(), e);
- throw new AMQStoreException("Error deleting enqueued message with id " + messageId + " for queue " + (queue instanceof AMQQueue ? ((AMQQueue)queue).getName() : "" )
- + " with id " + queue.getId() + " from database", e);
- }
+ _eventManager.addEventListener(new EventListener()
+ {
+ @Override
+ public void event(Event event)
+ {
+ setInitialSize();
+ }
+ }, Event.BEFORE_ACTIVATE);
}
-
- private void removeXid(ConnectionWrapper connWrapper, long format, byte[] globalId, byte[] branchId)
- throws AMQStoreException
+ private void setInitialSize()
{
- Connection conn = connWrapper.getConnection();
-
-
+ Connection conn = null;
try
{
- PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_XIDS);
- try
- {
- stmt.setLong(1,format);
- stmt.setBytes(2,globalId);
- stmt.setBytes(3,branchId);
- int results = stmt.executeUpdate();
-
- if(results != 1)
- {
- throw new AMQStoreException("Unable to find message with xid");
- }
- }
- finally
- {
- stmt.close();
- }
-
- stmt = conn.prepareStatement(DELETE_FROM_XID_ACTIONS);
try
{
- stmt.setLong(1,format);
- stmt.setBytes(2,globalId);
- stmt.setBytes(3,branchId);
- int results = stmt.executeUpdate();
-
+ conn = newAutoCommitConnection();
+ _totalStoreSize = getSizeOnDisk(conn);
}
finally
{
- stmt.close();
- }
-
- }
- catch (SQLException e)
- {
- _logger.error("Failed to dequeue: " + e.getMessage(), e);
- throw new AMQStoreException("Error deleting enqueued message with xid", e);
- }
-
- }
-
-
- private void recordXid(ConnectionWrapper connWrapper, long format, byte[] globalId, byte[] branchId,
- Transaction.Record[] enqueues, Transaction.Record[] dequeues) throws AMQStoreException
- {
- Connection conn = connWrapper.getConnection();
-
-
- try
- {
-
- PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_XIDS);
- try
- {
- stmt.setLong(1,format);
- stmt.setBytes(2, globalId);
- stmt.setBytes(3, branchId);
- stmt.executeUpdate();
- }
- finally
- {
- stmt.close();
- }
-
- stmt = conn.prepareStatement(INSERT_INTO_XID_ACTIONS);
-
- try
- {
- stmt.setLong(1,format);
- stmt.setBytes(2, globalId);
- stmt.setBytes(3, branchId);
-
- if(enqueues != null)
+ if(conn != null)
{
- stmt.setString(4, "E");
- for(Transaction.Record record : enqueues)
- {
- stmt.setString(5, record.getQueue().getId().toString());
- stmt.setLong(6, record.getMessage().getMessageNumber());
- stmt.executeUpdate();
- }
- }
+ conn.close();
- if(dequeues != null)
- {
- stmt.setString(4, "D");
- for(Transaction.Record record : dequeues)
- {
- stmt.setString(5, record.getQueue().getId().toString());
- stmt.setLong(6, record.getMessage().getMessageNumber());
- stmt.executeUpdate();
- }
- }
+ }
}
- finally
- {
- stmt.close();
- }
-
- }
- catch (SQLException e)
- {
- _logger.error("Failed to enqueue: " + e.getMessage(), e);
- throw new AMQStoreException("Error writing xid ", e);
- }
-
- }
-
- private static final class ConnectionWrapper
- {
- private final Connection _connection;
-
- public ConnectionWrapper(Connection conn)
- {
- _connection = conn;
- }
-
- public Connection getConnection()
- {
- return _connection;
- }
- }
-
-
- public void commitTran(ConnectionWrapper connWrapper) throws AMQStoreException
- {
-
- try
- {
- Connection conn = connWrapper.getConnection();
- conn.commit();
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("commit tran completed");
- }
-
- conn.close();
}
catch (SQLException e)
{
- throw new AMQStoreException("Error commit tx: " + e.getMessage(), e);
- }
- finally
- {
-
+ getLogger().error("Unable to set initial store size", e);
}
}
- public StoreFuture commitTranAsync(ConnectionWrapper connWrapper) throws AMQStoreException
- {
- commitTran(connWrapper);
- return StoreFuture.IMMEDIATE_FUTURE;
- }
-
- public void abortTran(ConnectionWrapper connWrapper) throws AMQStoreException
+ protected String getBlobAsString(ResultSet rs, int col) throws SQLException
{
- if (connWrapper == null)
+ Blob blob = rs.getBlob(col);
+ if(blob == null)
{
- throw new AMQStoreException("Fatal internal error: transactional context is empty at abortTran");
- }
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("abort tran called: " + connWrapper.getConnection());
- }
-
- try
- {
- Connection conn = connWrapper.getConnection();
- conn.rollback();
- conn.close();
+ return null;
}
- catch (SQLException e)
- {
- throw new AMQStoreException("Error aborting transaction: " + e.getMessage(), e);
- }
-
+ byte[] bytes = blob.getBytes(1, (int)blob.length());
+ return new String(bytes, UTF8_CHARSET);
}
- public Long getNewMessageId()
+ protected byte[] getBlobAsBytes(ResultSet rs, int col) throws SQLException
{
- return _messageId.incrementAndGet();
+ Blob dataAsBlob = rs.getBlob(col);
+ return dataAsBlob.getBytes(1,(int) dataAsBlob.length());
}
- private void storeMetaData(Connection conn, long messageId, StorableMessageMetaData metaData)
- throws SQLException
+ protected boolean tableExists(final String tableName, final Connection conn) throws SQLException
{
- if(_logger.isDebugEnabled())
- {
- _logger.debug("Adding metadata for message " +messageId);
- }
-
- PreparedStatement stmt = conn.prepareStatement(INSERT_INTO_META_DATA);
+ PreparedStatement stmt = conn.prepareStatement(TABLE_EXISTANCE_QUERY);
try
{
- stmt.setLong(1,messageId);
-
- final int bodySize = 1 + metaData.getStorableSize();
- byte[] underlying = new byte[bodySize];
- underlying[0] = (byte) metaData.getType().ordinal();
- java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(underlying);
- buf.position(1);
- buf = buf.slice();
-
- metaData.writeToBuffer(0, buf);
- ByteArrayInputStream bis = new ByteArrayInputStream(underlying);
+ stmt.setString(1, tableName);
+ ResultSet rs = stmt.executeQuery();
try
{
- stmt.setBinaryStream(2,bis,underlying.length);
- int result = stmt.executeUpdate();
-
- if(result == 0)
- {
- throw new RuntimeException("Unable to add meta data for message " +messageId);
- }
+ return rs.next();
}
finally
{
- try
- {
- bis.close();
- }
- catch (IOException e)
- {
-
- throw new SQLException(e);
- }
+ rs.close();
}
-
}
finally
{
stmt.close();
}
-
- }
-
-
-
-
- private void recoverMessages(MessageStoreRecoveryHandler recoveryHandler) throws SQLException
- {
- Connection conn = newAutoCommitConnection();
- try
- {
- MessageStoreRecoveryHandler.StoredMessageRecoveryHandler messageHandler = recoveryHandler.begin();
-
- Statement stmt = conn.createStatement();
- try
- {
- ResultSet rs = stmt.executeQuery(SELECT_ALL_FROM_META_DATA);
- try
- {
-
- long maxId = 0;
-
- while(rs.next())
- {
-
- long messageId = rs.getLong(1);
- Blob dataAsBlob = rs.getBlob(2);
-
- if(messageId > maxId)
- {
- maxId = messageId;
- }
-
- byte[] dataAsBytes = dataAsBlob.getBytes(1,(int) dataAsBlob.length());
- java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(dataAsBytes);
- buf.position(1);
- buf = buf.slice();
- MessageMetaDataType type = MessageMetaDataTypeRegistry.fromOrdinal(dataAsBytes[0]);
- StorableMessageMetaData metaData = type.createMetaData(buf);
- StoredDerbyMessage message = new StoredDerbyMessage(messageId, metaData, true);
- messageHandler.message(message);
- }
-
- _messageId.set(maxId);
-
- messageHandler.completeMessageRecovery();
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
- }
- finally
- {
- conn.close();
- }
- }
-
-
-
- private TransactionLogRecoveryHandler.DtxRecordRecoveryHandler recoverQueueEntries(TransactionLogRecoveryHandler recoveryHandler) throws SQLException
- {
- Connection conn = newAutoCommitConnection();
- try
- {
- TransactionLogRecoveryHandler.QueueEntryRecoveryHandler queueEntryHandler = recoveryHandler.begin(this);
-
- Statement stmt = conn.createStatement();
- try
- {
- ResultSet rs = stmt.executeQuery(SELECT_FROM_QUEUE_ENTRY);
- try
- {
- while(rs.next())
- {
-
- String id = rs.getString(1);
- long messageId = rs.getLong(2);
- queueEntryHandler.queueEntry(UUID.fromString(id), messageId);
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
-
- return queueEntryHandler.completeQueueEntryRecovery();
- }
- finally
- {
- conn.close();
- }
- }
-
- private static final class Xid
- {
-
- private final long _format;
- private final byte[] _globalId;
- private final byte[] _branchId;
-
- public Xid(long format, byte[] globalId, byte[] branchId)
- {
- _format = format;
- _globalId = globalId;
- _branchId = branchId;
- }
-
- public long getFormat()
- {
- return _format;
- }
-
- public byte[] getGlobalId()
- {
- return _globalId;
- }
-
- public byte[] getBranchId()
- {
- return _branchId;
- }
- }
-
- private static class RecordImpl implements Transaction.Record, TransactionLogResource, EnqueableMessage
- {
-
- private long _messageNumber;
- private UUID _queueId;
-
- public RecordImpl(UUID queueId, long messageNumber)
- {
- _messageNumber = messageNumber;
- _queueId = queueId;
- }
-
- @Override
- public TransactionLogResource getQueue()
- {
- return this;
- }
-
- @Override
- public EnqueableMessage getMessage()
- {
- return this;
- }
-
- @Override
- public long getMessageNumber()
- {
- return _messageNumber;
- }
-
- @Override
- public boolean isPersistent()
- {
- return true;
- }
-
- @Override
- public StoredMessage getStoredMessage()
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public UUID getId()
- {
- return _queueId;
- }
- }
-
- private void recoverXids(TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh) throws SQLException
- {
- Connection conn = newAutoCommitConnection();
- try
- {
- List<Xid> xids = new ArrayList<Xid>();
-
- Statement stmt = conn.createStatement();
- try
- {
- ResultSet rs = stmt.executeQuery(SELECT_ALL_FROM_XIDS);
- try
- {
- while(rs.next())
- {
-
- long format = rs.getLong(1);
- byte[] globalId = rs.getBytes(2);
- byte[] branchId = rs.getBytes(3);
- xids.add(new Xid(format, globalId, branchId));
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
-
-
-
- for(Xid xid : xids)
- {
- List<RecordImpl> enqueues = new ArrayList<RecordImpl>();
- List<RecordImpl> dequeues = new ArrayList<RecordImpl>();
-
- PreparedStatement pstmt = conn.prepareStatement(SELECT_ALL_FROM_XID_ACTIONS);
-
- try
- {
- pstmt.setLong(1, xid.getFormat());
- pstmt.setBytes(2, xid.getGlobalId());
- pstmt.setBytes(3, xid.getBranchId());
-
- ResultSet rs = pstmt.executeQuery();
- try
- {
- while(rs.next())
- {
-
- String actionType = rs.getString(1);
- UUID queueId = UUID.fromString(rs.getString(2));
- long messageId = rs.getLong(3);
-
- RecordImpl record = new RecordImpl(queueId, messageId);
- List<RecordImpl> records = "E".equals(actionType) ? enqueues : dequeues;
- records.add(record);
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- pstmt.close();
- }
-
- dtxrh.dtxRecord(xid.getFormat(), xid.getGlobalId(), xid.getBranchId(),
- enqueues.toArray(new RecordImpl[enqueues.size()]),
- dequeues.toArray(new RecordImpl[dequeues.size()]));
- }
-
-
- dtxrh.completeDtxRecordRecovery();
- }
- finally
- {
- conn.close();
- }
-
- }
-
- StorableMessageMetaData getMetaData(long messageId) throws SQLException
- {
-
- Connection conn = newAutoCommitConnection();
- try
- {
- PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_META_DATA);
- try
- {
- stmt.setLong(1,messageId);
- ResultSet rs = stmt.executeQuery();
- try
- {
-
- if(rs.next())
- {
- Blob dataAsBlob = rs.getBlob(1);
-
- byte[] dataAsBytes = dataAsBlob.getBytes(1,(int) dataAsBlob.length());
- java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(dataAsBytes);
- buf.position(1);
- buf = buf.slice();
- MessageMetaDataType type = MessageMetaDataTypeRegistry.fromOrdinal(dataAsBytes[0]);
- StorableMessageMetaData metaData = type.createMetaData(buf);
-
- return metaData;
- }
- else
- {
- throw new RuntimeException("Meta data not found for message with id " + messageId);
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
- }
- finally
- {
- conn.close();
- }
- }
-
-
- private void addContent(Connection conn, long messageId, ByteBuffer src)
- {
- if(_logger.isDebugEnabled())
- {
- _logger.debug("Adding content for message " +messageId);
- }
- PreparedStatement stmt = null;
-
- try
- {
- src = src.slice();
-
- byte[] chunkData = new byte[src.limit()];
- src.duplicate().get(chunkData);
-
- stmt = conn.prepareStatement(INSERT_INTO_MESSAGE_CONTENT);
- stmt.setLong(1,messageId);
-
- ByteArrayInputStream bis = new ByteArrayInputStream(chunkData);
- stmt.setBinaryStream(2, bis, chunkData.length);
- stmt.executeUpdate();
- }
- catch (SQLException e)
- {
- closeConnection(conn);
- throw new RuntimeException("Error adding content for message " + messageId + ": " + e.getMessage(), e);
- }
- finally
- {
- closePreparedStatement(stmt);
- }
-
- }
-
-
- public int getContent(long messageId, int offset, ByteBuffer dst)
- {
- Connection conn = null;
- PreparedStatement stmt = null;
-
- try
- {
- conn = newAutoCommitConnection();
-
- stmt = conn.prepareStatement(SELECT_FROM_MESSAGE_CONTENT);
- stmt.setLong(1,messageId);
- ResultSet rs = stmt.executeQuery();
-
- int written = 0;
-
- if (rs.next())
- {
-
- Blob dataAsBlob = rs.getBlob(1);
-
- final int size = (int) dataAsBlob.length();
- byte[] dataAsBytes = dataAsBlob.getBytes(1, size);
-
- if (offset > size)
- {
- throw new RuntimeException("Offset " + offset + " is greater than message size " + size
- + " for message id " + messageId + "!");
-
- }
-
- written = size - offset;
- if(written > dst.remaining())
- {
- written = dst.remaining();
- }
-
- dst.put(dataAsBytes, offset, written);
- }
-
- return written;
-
- }
- catch (SQLException e)
- {
- throw new RuntimeException("Error retrieving content from offset " + offset + " for message " + messageId + ": " + e.getMessage(), e);
- }
- finally
- {
- closePreparedStatement(stmt);
- closeConnection(conn);
- }
-
-
- }
-
- @Override
- public boolean isPersistent()
- {
- return true;
- }
-
-
- private class DerbyTransaction implements Transaction
- {
- private final ConnectionWrapper _connWrapper;
- private int _storeSizeIncrease;
-
-
- private DerbyTransaction()
- {
- try
- {
- _connWrapper = new ConnectionWrapper(newConnection());
- }
- catch (SQLException e)
- {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
- {
- final StoredMessage storedMessage = message.getStoredMessage();
- if(storedMessage instanceof StoredDerbyMessage)
- {
- try
- {
- ((StoredDerbyMessage) storedMessage).store(_connWrapper.getConnection());
- }
- catch (SQLException e)
- {
- throw new AMQStoreException("Exception on enqueuing message " + _messageId, e);
- }
- }
- _storeSizeIncrease += storedMessage.getMetaData().getContentSize();
- DerbyMessageStore.this.enqueueMessage(_connWrapper, queue, message.getMessageNumber());
- }
-
- @Override
- public void dequeueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException
- {
- DerbyMessageStore.this.dequeueMessage(_connWrapper, queue, message.getMessageNumber());
-
- }
-
- @Override
- public void commitTran() throws AMQStoreException
- {
- DerbyMessageStore.this.commitTran(_connWrapper);
- storedSizeChange(_storeSizeIncrease);
- }
-
- @Override
- public StoreFuture commitTranAsync() throws AMQStoreException
- {
- final StoreFuture storeFuture = DerbyMessageStore.this.commitTranAsync(_connWrapper);
- storedSizeChange(_storeSizeIncrease);
- return storeFuture;
- }
-
- @Override
- public void abortTran() throws AMQStoreException
- {
- DerbyMessageStore.this.abortTran(_connWrapper);
- }
-
- @Override
- public void removeXid(long format, byte[] globalId, byte[] branchId) throws AMQStoreException
- {
- DerbyMessageStore.this.removeXid(_connWrapper, format, globalId, branchId);
- }
-
- @Override
- public void recordXid(long format, byte[] globalId, byte[] branchId, Record[] enqueues, Record[] dequeues)
- throws AMQStoreException
- {
- DerbyMessageStore.this.recordXid(_connWrapper, format, globalId, branchId, enqueues, dequeues);
- }
- }
-
-
-
- private class StoredDerbyMessage implements StoredMessage
- {
-
- private final long _messageId;
- private final boolean _isRecovered;
-
- private StorableMessageMetaData _metaData;
- private volatile SoftReference<StorableMessageMetaData> _metaDataRef;
- private byte[] _data;
- private volatile SoftReference<byte[]> _dataRef;
-
-
- StoredDerbyMessage(long messageId, StorableMessageMetaData metaData)
- {
- this(messageId, metaData, false);
- }
-
-
- StoredDerbyMessage(long messageId,
- StorableMessageMetaData metaData, boolean isRecovered)
- {
- _messageId = messageId;
- _isRecovered = isRecovered;
-
- if(!_isRecovered)
- {
- _metaData = metaData;
- }
- _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData);
- }
-
- @Override
- public StorableMessageMetaData getMetaData()
- {
- StorableMessageMetaData metaData = _metaData == null ? _metaDataRef.get() : _metaData;
- if(metaData == null)
- {
- try
- {
- metaData = DerbyMessageStore.this.getMetaData(_messageId);
- }
- catch (SQLException e)
- {
- throw new RuntimeException(e);
- }
- _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData);
- }
-
- return metaData;
- }
-
- @Override
- public long getMessageNumber()
- {
- return _messageId;
- }
-
- @Override
- public void addContent(int offsetInMessage, java.nio.ByteBuffer src)
- {
- src = src.slice();
-
- if(_data == null)
- {
- _data = new byte[src.remaining()];
- _dataRef = new SoftReference<byte[]>(_data);
- src.duplicate().get(_data);
- }
- else
- {
- byte[] oldData = _data;
- _data = new byte[oldData.length + src.remaining()];
- _dataRef = new SoftReference<byte[]>(_data);
-
- System.arraycopy(oldData,0,_data,0,oldData.length);
- src.duplicate().get(_data, oldData.length, src.remaining());
- }
-
- }
-
- @Override
- public int getContent(int offsetInMessage, java.nio.ByteBuffer dst)
- {
- byte[] data = _dataRef == null ? null : _dataRef.get();
- if(data != null)
- {
- int length = Math.min(dst.remaining(), data.length - offsetInMessage);
- dst.put(data, offsetInMessage, length);
- return length;
- }
- else
- {
- return DerbyMessageStore.this.getContent(_messageId, offsetInMessage, dst);
- }
- }
-
-
- @Override
- public ByteBuffer getContent(int offsetInMessage, int size)
- {
- ByteBuffer buf = ByteBuffer.allocate(size);
- int length = getContent(offsetInMessage, buf);
- buf.position(0);
- buf.limit(length);
- return buf;
- }
-
- @Override
- public synchronized StoreFuture flushToStore()
- {
- Connection conn = null;
- try
- {
- if(!stored())
- {
- conn = newConnection();
-
- store(conn);
-
- conn.commit();
- storedSizeChange(getMetaData().getContentSize());
- }
- }
- catch (SQLException e)
- {
- if(_logger.isDebugEnabled())
- {
- _logger.debug("Error when trying to flush message " + _messageId + " to store: " + e);
- }
- throw new RuntimeException(e);
- }
- finally
- {
- closeConnection(conn);
- }
- return StoreFuture.IMMEDIATE_FUTURE;
- }
-
- @Override
- public void remove()
- {
- int delta = getMetaData().getContentSize();
- DerbyMessageStore.this.removeMessage(_messageId);
- storedSizeChange(-delta);
- }
-
- private synchronized void store(final Connection conn) throws SQLException
- {
- if (!stored())
- {
- try
- {
- storeMetaData(conn, _messageId, _metaData);
- DerbyMessageStore.this.addContent(conn, _messageId,
- _data == null ? ByteBuffer.allocate(0) : ByteBuffer.wrap(_data));
- }
- finally
- {
- _metaData = null;
- _data = null;
- }
-
- if(_logger.isDebugEnabled())
- {
- _logger.debug("Storing message " + _messageId + " to store");
- }
- }
- }
-
- private boolean stored()
- {
- return _metaData == null || _isRecovered;
- }
- }
-
- private void closeConnection(final Connection conn)
- {
- if(conn != null)
- {
- try
- {
- conn.close();
- }
- catch (SQLException e)
- {
- _logger.error("Problem closing connection", e);
- }
- }
- }
-
- private void closePreparedStatement(final PreparedStatement stmt)
- {
- if (stmt != null)
- {
- try
- {
- stmt.close();
- }
- catch(SQLException e)
- {
- _logger.error("Problem closing prepared statement", e);
- }
- }
- }
-
- @Override
- public void addEventListener(EventListener eventListener, Event... events)
- {
- _eventManager.addEventListener(eventListener, events);
}
@Override
@@ -1892,258 +241,7 @@ public class DerbyMessageStore implements MessageStore
return _storeLocation;
}
- private void insertConfiguredObject(ConfiguredObjectRecord configuredObject) throws AMQStoreException
- {
- if (_stateManager.isInState(State.ACTIVE))
- {
- try
- {
- Connection conn = newAutoCommitConnection();
- try
- {
- PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT);
- try
- {
- stmt.setString(1, configuredObject.getId().toString());
- ResultSet rs = stmt.executeQuery();
- try
- {
- // If we don't have any data in the result set then we can add this configured object
- if (!rs.next())
- {
- PreparedStatement insertStmt = conn.prepareStatement(INSERT_INTO_CONFIGURED_OBJECTS);
- try
- {
- insertStmt.setString(1, configuredObject.getId().toString());
- insertStmt.setString(2, configuredObject.getType());
- if(configuredObject.getAttributes() == null)
- {
- insertStmt.setNull(3, Types.BLOB);
- }
- else
- {
- byte[] attributesAsBytes = configuredObject.getAttributes().getBytes(UTF8_CHARSET);
- ByteArrayInputStream bis = new ByteArrayInputStream(attributesAsBytes);
- insertStmt.setBinaryStream(3, bis, attributesAsBytes.length);
- }
- insertStmt.execute();
- }
- finally
- {
- insertStmt.close();
- }
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
- }
- finally
- {
- conn.close();
- }
- }
- catch (SQLException e)
- {
- throw new AMQStoreException("Error inserting of configured object " + configuredObject + " into database: " + e.getMessage(), e);
- }
- }
- }
-
- private int removeConfiguredObject(UUID id) throws AMQStoreException
- {
- int results = 0;
- try
- {
- Connection conn = newAutoCommitConnection();
- try
- {
- PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_CONFIGURED_OBJECTS);
- try
- {
- stmt.setString(1, id.toString());
- results = stmt.executeUpdate();
- }
- finally
- {
- stmt.close();
- }
- }
- finally
- {
- conn.close();
- }
- }
- catch (SQLException e)
- {
- throw new AMQStoreException("Error deleting of configured object with id " + id + " from database: " + e.getMessage(), e);
- }
- return results;
- }
-
- private void updateConfiguredObject(final ConfiguredObjectRecord configuredObject) throws AMQStoreException
- {
- if (_stateManager.isInState(State.ACTIVE))
- {
- try
- {
- Connection conn = newAutoCommitConnection();
- try
- {
- PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT);
- try
- {
- stmt.setString(1, configuredObject.getId().toString());
- ResultSet rs = stmt.executeQuery();
- try
- {
- if (rs.next())
- {
- PreparedStatement stmt2 = conn.prepareStatement(UPDATE_CONFIGURED_OBJECTS);
- try
- {
- stmt2.setString(1, configuredObject.getType());
- if (configuredObject.getAttributes() != null)
- {
- byte[] attributesAsBytes = configuredObject.getAttributes().getBytes(UTF8_CHARSET);
- ByteArrayInputStream bis = new ByteArrayInputStream(attributesAsBytes);
- stmt2.setBinaryStream(2, bis, attributesAsBytes.length);
- }
- else
- {
- stmt2.setNull(2, Types.BLOB);
- }
- stmt2.setString(3, configuredObject.getId().toString());
- stmt2.execute();
- }
- finally
- {
- stmt2.close();
- }
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
- }
- finally
- {
- conn.close();
- }
- }
- catch (SQLException e)
- {
- throw new AMQStoreException("Error updating configured object " + configuredObject + " in database: " + e.getMessage(), e);
- }
- }
- }
-
- private ConfiguredObjectRecord loadConfiguredObject(final UUID id) throws AMQStoreException
- {
- ConfiguredObjectRecord result = null;
- try
- {
- Connection conn = newAutoCommitConnection();
- try
- {
- PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT);
- try
- {
- stmt.setString(1, id.toString());
- ResultSet rs = stmt.executeQuery();
- try
- {
- if (rs.next())
- {
- String type = rs.getString(1);
- Blob blob = rs.getBlob(2);
- String attributes = null;
- if (blob != null)
- {
- attributes = blobToString(blob);
- }
- result = new ConfiguredObjectRecord(id, type, attributes);
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
- }
- finally
- {
- conn.close();
- }
- }
- catch (SQLException e)
- {
- throw new AMQStoreException("Error loading of configured object with id " + id + " from database: "
- + e.getMessage(), e);
- }
- return result;
- }
-
- private String blobToString(Blob blob) throws SQLException
- {
- byte[] bytes = blob.getBytes(1, (int)blob.length());
- return new String(bytes, UTF8_CHARSET);
- }
-
- private List<ConfiguredObjectRecord> loadConfiguredObjects() throws SQLException
- {
- ArrayList<ConfiguredObjectRecord> results = new ArrayList<ConfiguredObjectRecord>();
- Connection conn = newAutoCommitConnection();
- try
- {
- PreparedStatement stmt = conn.prepareStatement(SELECT_FROM_CONFIGURED_OBJECTS);
- try
- {
- ResultSet rs = stmt.executeQuery();
- try
- {
- while (rs.next())
- {
- String id = rs.getString(1);
- String objectType = rs.getString(2);
- String attributes = blobToString(rs.getBlob(3));
- results.add(new ConfiguredObjectRecord(UUID.fromString(id), objectType, attributes));
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
- }
- finally
- {
- conn.close();
- }
- return results;
- }
-
- private synchronized void storedSizeChange(final int delta)
+ protected synchronized void storedSizeChange(final int delta)
{
if(getPersistentSizeHighThreshold() > 0)
{
@@ -2193,7 +291,7 @@ public class DerbyMessageStore implements MessageStore
catch (SQLException e)
{
closeConnection(conn);
- throw new RuntimeException("Exception will processing store size change", e);
+ throw new RuntimeException("Exception while processing store size change", e);
}
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java
new file mode 100644
index 0000000000..2c4b0e8119
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java
@@ -0,0 +1,396 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.store.jdbc;
+
+
+import java.sql.Blob;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+import org.apache.commons.configuration.Configuration;
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQStoreException;
+import org.apache.qpid.server.store.AbstractJDBCMessageStore;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.MessageStoreConstants;
+import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.store.Transaction;
+
+/**
+ * An implementation of a {@link org.apache.qpid.server.store.MessageStore} that uses a JDBC database as the persistence
+ * mechanism.
+ *
+ */
+public class JDBCMessageStore extends AbstractJDBCMessageStore implements MessageStore
+{
+
+ private static final Logger _logger = Logger.getLogger(JDBCMessageStore.class);
+
+
+ public static final String TYPE = "JDBC";
+
+
+ private static class JDBCDetails
+ {
+ private final String _vendor;
+ private String _blobType;
+ private String _varBinaryType;
+ private String _bigintType;
+ private boolean _useBytesMethodsForBlob;
+
+ private JDBCDetails(String vendor,
+ String blobType,
+ String varBinaryType,
+ String bigIntType,
+ boolean useBytesMethodsForBlob)
+ {
+ _vendor = vendor;
+ setBlobType(blobType);
+ setVarBinaryType(varBinaryType);
+ setBigintType(bigIntType);
+ setUseBytesMethodsForBlob(useBytesMethodsForBlob);
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+
+ JDBCDetails that = (JDBCDetails) o;
+
+ if (!getVendor().equals(that.getVendor()))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return getVendor().hashCode();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "JDBCDetails{" +
+ "vendor='" + getVendor() + '\'' +
+ ", blobType='" + getBlobType() + '\'' +
+ ", varBinaryType='" + getVarBinaryType() + '\'' +
+ ", bigIntType='" + getBigintType() + '\'' +
+ ", useBytesMethodsForBlob=" + isUseBytesMethodsForBlob() +
+ '}';
+ }
+
+ public String getVendor()
+ {
+ return _vendor;
+ }
+
+ public String getBlobType()
+ {
+ return _blobType;
+ }
+
+ public void setBlobType(String blobType)
+ {
+ _blobType = blobType;
+ }
+
+ public String getVarBinaryType()
+ {
+ return _varBinaryType;
+ }
+
+ public void setVarBinaryType(String varBinaryType)
+ {
+ _varBinaryType = varBinaryType;
+ }
+
+ public boolean isUseBytesMethodsForBlob()
+ {
+ return _useBytesMethodsForBlob;
+ }
+
+ public void setUseBytesMethodsForBlob(boolean useBytesMethodsForBlob)
+ {
+ _useBytesMethodsForBlob = useBytesMethodsForBlob;
+ }
+
+ public String getBigintType()
+ {
+ return _bigintType;
+ }
+
+ public void setBigintType(String bigintType)
+ {
+ _bigintType = bigintType;
+ }
+ }
+
+ private static JDBCDetails DERBY_DETAILS =
+ new JDBCDetails("derby",
+ "blob",
+ "varchar(%d) for bit data",
+ "bigint",
+ false);
+
+ private static JDBCDetails POSTGRESQL_DETAILS =
+ new JDBCDetails("postgresql",
+ "bytea",
+ "bytea",
+ "bigint",
+ true);
+
+ private static JDBCDetails MYSQL_DETAILS =
+ new JDBCDetails("mysql",
+ "blob",
+ "varbinary(%d)",
+ "bigint",
+ false);
+
+
+ private static JDBCDetails SYBASE_DETAILS =
+ new JDBCDetails("sybase",
+ "image",
+ "varbinary(%d)",
+ "bigint",
+ false);
+
+
+ private static JDBCDetails ORACLE_DETAILS =
+ new JDBCDetails("oracle",
+ "blob",
+ "raw(%d)",
+ "number",
+ false);
+
+
+ private static Map<String, JDBCDetails> VENDOR_DETAILS = new HashMap<String,JDBCDetails>();
+
+ static
+ {
+
+ addDetails(DERBY_DETAILS);
+ addDetails(POSTGRESQL_DETAILS);
+ addDetails(MYSQL_DETAILS);
+ addDetails(SYBASE_DETAILS);
+ addDetails(ORACLE_DETAILS);
+ }
+
+ private static void addDetails(JDBCDetails details)
+ {
+ VENDOR_DETAILS.put(details.getVendor(), details);
+ }
+
+ private String _blobType;
+ private String _varBinaryType;
+ private String _bigIntType;
+ private boolean _useBytesMethodsForBlob;
+
+ private List<RecordedJDBCTransaction> _transactions = new CopyOnWriteArrayList<RecordedJDBCTransaction>();
+
+
+ public JDBCMessageStore()
+ {
+ }
+
+ protected Logger getLogger()
+ {
+ return _logger;
+ }
+
+ protected String getSqlBlobType()
+ {
+ return _blobType;
+ }
+
+ protected String getSqlVarBinaryType(int size)
+ {
+ return String.format(_varBinaryType, size);
+ }
+
+ public String getSqlBigIntType()
+ {
+ return _bigIntType;
+ }
+
+ @Override
+ protected void doClose() throws AMQStoreException
+ {
+ while(!_transactions.isEmpty())
+ {
+ RecordedJDBCTransaction txn = _transactions.get(0);
+ txn.abortTran();
+ }
+ }
+
+ protected void implementationSpecificConfiguration(String name, Configuration storeConfiguration)
+ throws ClassNotFoundException
+ {
+
+ _connectionURL = storeConfiguration.getString("connectionUrl",
+ storeConfiguration.getString(MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY));
+
+ JDBCDetails details = null;
+
+ String[] components = _connectionURL.split(":",3);
+ if(components.length >= 2)
+ {
+ String vendor = components[1];
+ details = VENDOR_DETAILS.get(vendor);
+ }
+
+ if(details == null)
+ {
+ getLogger().info("Do not recognize vendor from connection URL: " + _connectionURL);
+
+ // TODO - is there a better default than derby
+ details = DERBY_DETAILS;
+ }
+
+ _blobType = storeConfiguration.getString("sqlBlobType",details.getBlobType());
+ _varBinaryType = storeConfiguration.getString("sqlVarbinaryType",details.getVarBinaryType());
+ _useBytesMethodsForBlob = storeConfiguration.getBoolean("useBytesForBlob",details.isUseBytesMethodsForBlob());
+ _bigIntType = storeConfiguration.getString("sqlBigIntType", details.getBigintType());
+ }
+
+ protected void storedSizeChange(int contentSize)
+ {
+ }
+
+ @Override
+ public String getStoreLocation()
+ {
+ return "";
+ }
+
+ @Override
+ public String getStoreType()
+ {
+ return TYPE;
+ }
+
+ @Override
+ protected byte[] getBlobAsBytes(ResultSet rs, int col) throws SQLException
+ {
+ if(_useBytesMethodsForBlob)
+ {
+ return rs.getBytes(col);
+ }
+ else
+ {
+ Blob dataAsBlob = rs.getBlob(col);
+ return dataAsBlob.getBytes(1,(int) dataAsBlob.length());
+
+ }
+ }
+
+ @Override
+ protected String getBlobAsString(ResultSet rs, int col) throws SQLException
+ {
+ byte[] bytes;
+ if(_useBytesMethodsForBlob)
+ {
+ bytes = rs.getBytes(col);
+ return new String(bytes,UTF8_CHARSET);
+ }
+ else
+ {
+ Blob blob = rs.getBlob(col);
+ if(blob == null)
+ {
+ return null;
+ }
+ bytes = blob.getBytes(1, (int)blob.length());
+ }
+ return new String(bytes, UTF8_CHARSET);
+
+ }
+
+ @Override
+ public Transaction newTransaction()
+ {
+ return new RecordedJDBCTransaction();
+ }
+
+ private class RecordedJDBCTransaction extends JDBCTransaction
+ {
+ private RecordedJDBCTransaction()
+ {
+ super();
+ JDBCMessageStore.this._transactions.add(this);
+ }
+
+ @Override
+ public void commitTran() throws AMQStoreException
+ {
+ try
+ {
+ super.commitTran();
+ }
+ finally
+ {
+ JDBCMessageStore.this._transactions.remove(this);
+ }
+ }
+
+ @Override
+ public StoreFuture commitTranAsync() throws AMQStoreException
+ {
+ try
+ {
+ return super.commitTranAsync();
+ }
+ finally
+ {
+ JDBCMessageStore.this._transactions.remove(this);
+ }
+ }
+
+ @Override
+ public void abortTran() throws AMQStoreException
+ {
+ try
+ {
+ super.abortTran();
+ }
+ finally
+ {
+ JDBCMessageStore.this._transactions.remove(this);
+ }
+ }
+ }
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java
new file mode 100644
index 0000000000..1446ad34e9
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store.jdbc;
+
+import org.apache.qpid.server.plugin.MessageStoreFactory;
+import org.apache.qpid.server.store.MessageStore;
+
+public class JDBCMessageStoreFactory implements MessageStoreFactory
+{
+
+ @Override
+ public String getType()
+ {
+ return JDBCMessageStore.TYPE;
+ }
+
+ @Override
+ public MessageStore createMessageStore()
+ {
+ return new JDBCMessageStore();
+ }
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java
index 8c57d04348..16e717a9c7 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java
@@ -62,7 +62,7 @@ public class MapValueConverter
return getStringAttribute(name, attributes, null);
}
- private static void assertMandatoryAttribute(String name, Map<String, Object> attributes)
+ public static void assertMandatoryAttribute(String name, Map<String, Object> attributes)
{
if (!attributes.containsKey(name))
{
@@ -326,6 +326,10 @@ public class MapValueConverter
public static <T> Set<T> toSet(Object rawValue, Class<T> setItemClass, String attributeName)
{
+ if (rawValue == null)
+ {
+ return null;
+ }
HashSet<T> set = new HashSet<T>();
if (rawValue instanceof Iterable)
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/util/StringUtil.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/util/StringUtil.java
new file mode 100644
index 0000000000..aa17a9493b
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/util/StringUtil.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.util;
+
+import java.util.Random;
+
+public class StringUtil
+{
+ private static final String NUMBERS = "0123456789";
+ private static final String LETTERS = "abcdefghijklmnopqrstuvwxwy";
+ private static final String OTHERS = "_-";
+ private static final char[] CHARACTERS = (NUMBERS + LETTERS + LETTERS.toUpperCase() + OTHERS).toCharArray();
+
+ private Random _random = new Random();
+
+ public String randomAlphaNumericString(int maxLength)
+ {
+ char[] result = new char[maxLength];
+ for (int i = 0; i < maxLength; i++)
+ {
+ result[i] = (char) CHARACTERS[_random.nextInt(CHARACTERS.length)];
+ }
+ return new String(result);
+ }
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
index 657cf4b762..af5b8b1270 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
@@ -131,7 +131,7 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr
CurrentActor.get().message(VirtualHostMessages.CREATED(_name));
- _securityManager = new SecurityManager(parentSecurityManager, _vhostConfig.getConfig().getString("security.acl"));
+ _securityManager = new SecurityManager(parentSecurityManager, _vhostConfig.getConfig().getString("security.acl"), _name);
_connectionRegistry = new ConnectionRegistry();
_connectionRegistry.addRegistryChangeListener(this);
diff --git a/qpid/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory b/qpid/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory
index 1357f816b7..0edd44f5a5 100644
--- a/qpid/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory
+++ b/qpid/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory
@@ -17,4 +17,5 @@
# under the License.
#
org.apache.qpid.server.store.derby.DerbyMessageStoreFactory
-org.apache.qpid.server.store.MemoryMessageStoreFactory \ No newline at end of file
+org.apache.qpid.server.store.MemoryMessageStoreFactory
+org.apache.qpid.server.store.jdbc.JDBCMessageStoreFactory
diff --git a/qpid/java/broker/src/main/resources/initial-store.json b/qpid/java/broker/src/main/resources/initial-config.json
index 7e73772d6d..f8b724d351 100644
--- a/qpid/java/broker/src/main/resources/initial-store.json
+++ b/qpid/java/broker/src/main/resources/initial-config.json
@@ -19,9 +19,8 @@
*
*/
{
- "name": "QpidBroker",
+ "name": "Broker",
"storeVersion": 1,
- "defaultAuthenticationProvider" : "passwordFile",
"defaultVirtualHost" : "default",
"authenticationproviders" : [ {
"name" : "passwordFile",
@@ -29,25 +28,28 @@
"path" : "${QPID_HOME}/etc/passwd"
} ],
"ports" : [ {
- "name" : "5672-AMQP",
- "port" : 5672
+ "name" : "AMQP",
+ "port" : 5672,
+ "authenticationProvider" : "passwordFile"
}, {
- "name" : "8080-HTTP",
+ "name" : "HTTP",
"port" : 8080,
+ "authenticationProvider" : "passwordFile",
"protocols" : [ "HTTP" ]
}, {
- "name" : "8999-RMI",
+ "name" : "RMI_REGISTRY",
"port" : 8999,
"protocols" : [ "RMI" ]
}, {
- "name" : "9099-JMX_RMI",
+ "name" : "JMX_CONNECTOR",
"port" : 9099,
+ "authenticationProvider" : "passwordFile",
"protocols" : [ "JMX_RMI" ]
}],
"virtualhosts" : [ {
"name" : "default",
"storeType" : "DERBY",
- "storePath" : "${QPID_WORK}/store"
+ "storePath" : "${QPID_WORK}/derbystore/default"
} ],
"plugins" : [ {
"pluginType" : "MANAGEMENT-HTTP",
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java
index 51fe2d88d3..08031c36a4 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java
@@ -28,8 +28,9 @@ public class BrokerOptionsTest extends QpidTestCase
{
private BrokerOptions _options;
- protected void setUp()
+ protected void setUp() throws Exception
{
+ super.setUp();
_options = new BrokerOptions();
}
@@ -129,6 +130,17 @@ public class BrokerOptionsTest extends QpidTestCase
assertEquals(true, _options.isManagementMode());
}
+ public void testDefaultManagementModeQuiesceVirtualHosts()
+ {
+ assertEquals(false, _options.isManagementModeQuiesceVirtualHosts());
+ }
+
+ public void testOverriddenDefaultManagementModeQuiesceVirtualHosts()
+ {
+ _options.setManagementModeQuiesceVirtualHosts(true);
+ assertEquals(true, _options.isManagementModeQuiesceVirtualHosts());
+ }
+
public void testDefaultManagementModeRmiPort()
{
assertEquals(0, _options.getManagementModeRmiPort());
@@ -197,4 +209,21 @@ public class BrokerOptionsTest extends QpidTestCase
_options.setSkipLoggingConfiguration(true);
assertTrue(_options.isSkipLoggingConfiguration());
}
+
+ public void testDefaultOverwriteConfigurationStore()
+ {
+ assertFalse(_options.isOverwriteConfigurationStore());
+ }
+
+ public void testOverriddenOverwriteConfigurationStore()
+ {
+ _options.setOverwriteConfigurationStore(true);
+ assertTrue(_options.isOverwriteConfigurationStore());
+ }
+
+ public void testManagementModePassword()
+ {
+ _options.setManagementModePassword("test");
+ assertEquals("Unexpected management mode password", "test", _options.getManagementModePassword());
+ }
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/MainTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/MainTest.java
index 46c63c9e34..d7579e2b2a 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/MainTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/MainTest.java
@@ -47,7 +47,7 @@ public class MainTest extends QpidTestCase
assertEquals(null, options.getLogConfigFile());
assertEquals(0, options.getLogWatchFrequency());
assertEquals(BrokerOptions.DEFAULT_INITIAL_CONFIG_LOCATION, options.getInitialConfigurationLocation());
-
+ assertFalse(options.isOverwriteConfigurationStore());
assertFalse(options.isManagementMode());
assertEquals(0, options.getManagementModeConnectorPort());
assertEquals(0, options.getManagementModeRmiPort());
@@ -72,6 +72,15 @@ public class MainTest extends QpidTestCase
assertEquals("bdb", options.getConfigurationStoreType());
}
+ public void testOverwriteConfigurationStore()
+ {
+ BrokerOptions options = startDummyMain("-os");
+ assertTrue(options.isOverwriteConfigurationStore());
+
+ options = startDummyMain("-overwrite-store");
+ assertTrue(options.isOverwriteConfigurationStore());
+ }
+
public void testLogConfig()
{
BrokerOptions options = startDummyMain("-l wxyz/log4j.xml");
@@ -122,46 +131,68 @@ public class MainTest extends QpidTestCase
public void testManagementModeRmiPort()
{
- BrokerOptions options = startDummyMain("-mm -rmi 7777");
+ BrokerOptions options = startDummyMain("-mm -mmrmi 7777");
assertTrue(options.isManagementMode());
assertEquals(7777, options.getManagementModeRmiPort());
- options = startDummyMain("-mm --jmxregistryport 7777");
+ options = startDummyMain("-mm --management-mode-rmi-registry-port 7777");
assertTrue(options.isManagementMode());
assertEquals(7777, options.getManagementModeRmiPort());
- options = startDummyMain("-rmi 7777");
+ options = startDummyMain("-mmrmi 7777");
assertEquals(0, options.getManagementModeRmiPort());
}
public void testManagementModeConnectorPort()
{
- BrokerOptions options = startDummyMain("-mm -jmxrmi 8888");
+ BrokerOptions options = startDummyMain("-mm -mmjmx 8888");
assertTrue(options.isManagementMode());
assertEquals(8888, options.getManagementModeConnectorPort());
- options = startDummyMain("-mm --jmxconnectorport 8888");
+ options = startDummyMain("-mm --management-mode-jmx-connector-port 8888");
assertTrue(options.isManagementMode());
assertEquals(8888, options.getManagementModeConnectorPort());
- options = startDummyMain("-jmxrmi 8888");
+ options = startDummyMain("-mmjmx 8888");
assertEquals(0, options.getManagementModeConnectorPort());
}
public void testManagementModeHttpPort()
{
- BrokerOptions options = startDummyMain("-mm -http 9999");
+ BrokerOptions options = startDummyMain("-mm -mmhttp 9999");
assertTrue(options.isManagementMode());
assertEquals(9999, options.getManagementModeHttpPort());
- options = startDummyMain("-mm --httpport 9999");
+ options = startDummyMain("-mm --management-mode-http-port 9999");
assertTrue(options.isManagementMode());
assertEquals(9999, options.getManagementModeHttpPort());
- options = startDummyMain("-http 9999");
+ options = startDummyMain("-mmhttp 9999");
assertEquals(0, options.getManagementModeHttpPort());
}
+ public void testManagementModePassword()
+ {
+ String password = getTestName();
+ BrokerOptions options = startDummyMain("-mm -mmpass " + password);
+ assertTrue(options.isManagementMode());
+ assertEquals(password, options.getManagementModePassword());
+
+ options = startDummyMain("-mm --management-mode-password " + password);
+ assertTrue(options.isManagementMode());
+ assertEquals(password, options.getManagementModePassword());
+
+ options = startDummyMain("-mmpass " + password);
+ assertNotNull(options.getManagementModePassword());
+ }
+
+ public void testDefaultManagementModePassword()
+ {
+ BrokerOptions options = startDummyMain("-mm");
+ assertTrue(options.isManagementMode());
+ assertNotNull(options.getManagementModePassword());
+ }
+
private BrokerOptions startDummyMain(String commandLine)
{
return (new TestMain(commandLine.split("\\s"))).getOptions();
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreatorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreatorTest.java
index d61117868f..7555a5632c 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreatorTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreatorTest.java
@@ -73,7 +73,7 @@ public class BrokerConfigurationStoreCreatorTest extends QpidTestCase
public void testCreateJsonStore()
{
- ConfigurationEntryStore store = _storeCreator.createStore(_userStoreLocation.getAbsolutePath(), "json", BrokerOptions.DEFAULT_INITIAL_CONFIG_LOCATION);
+ ConfigurationEntryStore store = _storeCreator.createStore(_userStoreLocation.getAbsolutePath(), "json", BrokerOptions.DEFAULT_INITIAL_CONFIG_LOCATION, false);
assertNotNull("Store was not created", store);
assertTrue("File should exists", _userStoreLocation.exists());
assertTrue("File size should be greater than 0", _userStoreLocation.length() > 0);
@@ -84,41 +84,73 @@ public class BrokerConfigurationStoreCreatorTest extends QpidTestCase
public void testCreateJsonStoreFromInitialStore() throws Exception
{
+ createJsonStoreFromInitialStoreTestImpl(false);
+ }
+
+ public void testOverwriteExistingJsonStoreWithInitialConfig() throws Exception
+ {
+ createJsonStoreFromInitialStoreTestImpl(true);
+ }
+
+ public void createJsonStoreFromInitialStoreTestImpl(boolean overwrite) throws Exception
+ {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ String defaultBrokerName = "Broker";
+ String testBrokerName = getTestName();
+
Map<String, Object> brokerObjectMap = new HashMap<String, Object>();
- UUID brokerId = UUID.randomUUID();
- brokerObjectMap.put(Broker.ID, brokerId);
- brokerObjectMap.put("name", "Test");
+ UUID testBrokerId = UUID.randomUUID();
+ brokerObjectMap.put(Broker.ID, testBrokerId);
+ brokerObjectMap.put("name", testBrokerName);
StringWriter sw = new StringWriter();
objectMapper.writeValue(sw, brokerObjectMap);
String brokerJson = sw.toString();
- File _storeFile = TestFileUtils.createTempFile(this, ".json", brokerJson);
+ File _initialStoreFile = TestFileUtils.createTempFile(this, ".json", brokerJson);
- ConfigurationEntryStore store = _storeCreator.createStore(_userStoreLocation.getAbsolutePath(), "json", _storeFile.getAbsolutePath());
+ ConfigurationEntryStore store = _storeCreator.createStore(_userStoreLocation.getAbsolutePath(), "json", _initialStoreFile.getAbsolutePath(), false);
assertNotNull("Store was not created", store);
assertTrue("File should exists", _userStoreLocation.exists());
assertTrue("File size should be greater than 0", _userStoreLocation.length() > 0);
JsonConfigurationEntryStore jsonStore = new JsonConfigurationEntryStore(_userStoreLocation.getAbsolutePath(), null);
ConfigurationEntry entry = jsonStore.getRootEntry();
- assertEquals("Unexpected root id", brokerId, entry.getId());
+ assertEquals("Unexpected root id", testBrokerId, entry.getId());
Map<String, Object> attributes = entry.getAttributes();
assertNotNull("Unexpected attributes: " + attributes, attributes);
assertEquals("Unexpected attributes size: " + attributes.size(), 1, attributes.size());
- assertEquals("Unexpected attribute name: " + attributes.get("name"), "Test", attributes.get("name"));
+ assertEquals("Unexpected attribute name: " + attributes.get("name"), testBrokerName, attributes.get(Broker.NAME));
Set<UUID> childrenIds = entry.getChildrenIds();
assertTrue("Unexpected children: " + childrenIds, childrenIds.isEmpty());
+
+ if(overwrite)
+ {
+ ConfigurationEntryStore overwrittenStore = _storeCreator.createStore(_userStoreLocation.getAbsolutePath(), "json", BrokerOptions.DEFAULT_INITIAL_CONFIG_LOCATION, true);
+ assertNotNull("Store was not created", overwrittenStore);
+ assertTrue("File should exists", _userStoreLocation.exists());
+ assertTrue("File size should be greater than 0", _userStoreLocation.length() > 0);
+
+ //check the contents reflect the test store content having been overwritten with the default store
+ JsonConfigurationEntryStore reopenedOverwrittenStore = new JsonConfigurationEntryStore(_userStoreLocation.getAbsolutePath(), null, false);
+ entry = reopenedOverwrittenStore.getRootEntry();
+ assertFalse("Root id did not change, store content was not overwritten", testBrokerId.equals(entry.getId()));
+ attributes = entry.getAttributes();
+ assertNotNull("No attributes found", attributes);
+ assertFalse("Test name should not equal default broker name", testBrokerName.equals(defaultBrokerName));
+ assertEquals("Unexpected broker name value" , defaultBrokerName, attributes.get(Broker.NAME));
+ childrenIds = entry.getChildrenIds();
+ assertFalse("Expected children were not found" + childrenIds, childrenIds.isEmpty());
+ }
}
public void testCreateStoreWithUnknownType()
{
try
{
- _storeCreator.createStore(_userStoreLocation.getAbsolutePath(), "derby", null);
+ _storeCreator.createStore(_userStoreLocation.getAbsolutePath(), "derby", null, false);
fail("Store is not yet supported");
}
catch(IllegalConfigurationException e)
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java
index 3a41b61961..64b432f471 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java
@@ -20,10 +20,8 @@
*/
package org.apache.qpid.server.configuration.startup;
-import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
import java.util.Arrays;
import java.util.Collection;
@@ -35,9 +33,9 @@ import java.util.UUID;
import junit.framework.TestCase;
+import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.configuration.ConfigurationEntry;
import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer;
-import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.RecovererProvider;
import org.apache.qpid.server.logging.LogRecorder;
import org.apache.qpid.server.logging.RootMessageLogger;
@@ -50,7 +48,9 @@ import org.apache.qpid.server.model.Plugin;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.adapter.AccessControlProviderFactory;
import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory;
+import org.apache.qpid.server.model.adapter.GroupProviderFactory;
import org.apache.qpid.server.model.adapter.PortFactory;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.stats.StatisticsGatherer;
@@ -72,8 +72,8 @@ public class BrokerRecovererTest extends TestCase
{
super.setUp();
- _brokerRecoverer = new BrokerRecoverer(mock(AuthenticationProviderFactory.class), mock(PortFactory.class), mock(StatisticsGatherer.class),
- mock(VirtualHostRegistry.class), mock(LogRecorder.class), mock(RootMessageLogger.class), mock(TaskExecutor.class));
+ _brokerRecoverer = new BrokerRecoverer(mock(AuthenticationProviderFactory.class), mock(GroupProviderFactory.class), mock(AccessControlProviderFactory.class), mock(PortFactory.class),
+ mock(StatisticsGatherer.class), mock(VirtualHostRegistry.class), mock(LogRecorder.class), mock(RootMessageLogger.class), mock(TaskExecutor.class), mock(BrokerOptions.class));
when(_brokerEntry.getId()).thenReturn(_brokerId);
when(_brokerEntry.getChildren()).thenReturn(_brokerEntryChildren);
@@ -89,7 +89,6 @@ public class BrokerRecovererTest extends TestCase
{
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(Broker.DEFAULT_VIRTUAL_HOST, "test");
- attributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider1");
attributes.put(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, 9l);
attributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 8l);
attributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, 7l);
@@ -100,7 +99,6 @@ public class BrokerRecovererTest extends TestCase
attributes.put(Broker.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS, 2);
attributes.put(Broker.QUEUE_DEAD_LETTER_QUEUE_ENABLED, true);
attributes.put(Broker.VIRTUALHOST_HOUSEKEEPING_CHECK_PERIOD, 1l);
- attributes.put(Broker.ACL_FILE, "/path/to/acl");
attributes.put(Broker.CONNECTION_SESSION_COUNT_LIMIT, 1000);
attributes.put(Broker.CONNECTION_HEART_BEAT_DELAY, 2000);
attributes.put(Broker.STATISTICS_REPORTING_PERIOD, 4000);
@@ -172,24 +170,6 @@ public class BrokerRecovererTest extends TestCase
assertEquals(Collections.singletonList(port), broker.getPorts());
}
- public void testCreateBrokerWithoutAuthenticationProviderThrowsException()
- {
- assertNotNull("expected to remove the base entry", _brokerEntryChildren.remove(AuthenticationProvider.class.getSimpleName()));
- assertTrue("should be empty", _brokerEntryChildren.isEmpty());
-
- RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[0], new ConfiguredObject[0]);
-
- try
- {
- _brokerRecoverer.create(recovererProvider, _brokerEntry);
- fail("should have thrown an exception due to missing authentication provider configuration");
- }
- catch(IllegalConfigurationException e)
- {
- //expected
- }
- }
-
public void testCreateBrokerWithOneAuthenticationProvider()
{
RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{_authenticationProviderEntry1},
@@ -202,29 +182,6 @@ public class BrokerRecovererTest extends TestCase
assertEquals(Collections.singletonList(_authenticationProvider1), broker.getAuthenticationProviders());
}
- public void testCreateBrokerWithMultipleAuthenticationProvidersAndNoDefaultThrowsException()
- {
- AuthenticationProvider authenticationProvider2 = mock(AuthenticationProvider.class);
- when(authenticationProvider2.getName()).thenReturn("authenticationProvider2");
- ConfigurationEntry authenticationProviderEntry2 = mock(ConfigurationEntry.class);
- _brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1, authenticationProviderEntry2));
-
- Map<String,Object> emptyBrokerAttributes = new HashMap<String,Object>();
- when(_brokerEntry.getAttributes()).thenReturn(emptyBrokerAttributes);
-
- RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{authenticationProviderEntry2, _authenticationProviderEntry1},
- new ConfiguredObject[]{authenticationProvider2, _authenticationProvider1});
- try
- {
- _brokerRecoverer.create(recovererProvider, _brokerEntry);
- fail("should have thrown an exception due to missing authentication provider default");
- }
- catch(IllegalConfigurationException e)
- {
- //expected
- }
- }
-
public void testCreateBrokerWithMultipleAuthenticationProvidersAndPorts()
{
//Create a second authentication provider
@@ -233,13 +190,10 @@ public class BrokerRecovererTest extends TestCase
ConfigurationEntry authenticationProviderEntry2 = mock(ConfigurationEntry.class);
_brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1, authenticationProviderEntry2));
- //Set the default authentication provider
Map<String,Object> brokerAtttributes = new HashMap<String,Object>();
when(_brokerEntry.getAttributes()).thenReturn(brokerAtttributes);
- brokerAtttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider2");
- //Add a couple ports, one with a defined authentication provider and
- //one without (which should then use the default)
+ //Add a couple ports
ConfigurationEntry portEntry1 = mock(ConfigurationEntry.class);
Port port1 = mock(Port.class);
when(port1.getName()).thenReturn("port1");
@@ -249,6 +203,7 @@ public class BrokerRecovererTest extends TestCase
Port port2 = mock(Port.class);
when(port2.getName()).thenReturn("port2");
when(port2.getPort()).thenReturn(5672);
+ when(port2.getAttribute(Port.AUTHENTICATION_PROVIDER)).thenReturn("authenticationProvider2");
_brokerEntryChildren.put(Port.class.getSimpleName(), Arrays.asList(portEntry1, portEntry2));
RecovererProvider recovererProvider = createRecoveryProvider(
@@ -258,47 +213,12 @@ public class BrokerRecovererTest extends TestCase
Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry);
assertNotNull(broker);
- assertEquals("Unexpected number of authentication providers", 2,broker.getAuthenticationProviders().size());
+ assertEquals("Unexpected number of authentication providers", 2, broker.getAuthenticationProviders().size());
Collection<Port> ports = broker.getPorts();
assertEquals("Unexpected number of ports", 2, ports.size());
assertTrue(ports.contains(port1));
assertTrue(ports.contains(port2));
-
- verify(port1).setAuthenticationProvider(any(AuthenticationProvider.class));
- verify(port1).setAuthenticationProvider(_authenticationProvider1);
-
- verify(port2).setAuthenticationProvider(any(AuthenticationProvider.class));
- verify(port2).setAuthenticationProvider(authenticationProvider2);
- }
-
- public void testCreateBrokerAssignsGroupAccessorToAuthenticationProviders()
- {
- //Create a second authentication provider
- AuthenticationProvider authenticationProvider2 = mock(AuthenticationProvider.class);
- when(authenticationProvider2.getName()).thenReturn("authenticationProvider2");
- ConfigurationEntry authenticationProviderEntry2 = mock(ConfigurationEntry.class);
- _brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1, authenticationProviderEntry2));
-
- //Set the default authentication provider
- Map<String,Object> brokerAtttributes = new HashMap<String,Object>();
- when(_brokerEntry.getAttributes()).thenReturn(brokerAtttributes);
- brokerAtttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider2");
-
- //Create a group provider
- ConfigurationEntry groupProviderEntry = mock(ConfigurationEntry.class);
- GroupProvider groupProvider = mock(GroupProvider.class);
- _brokerEntryChildren.put(GroupProvider.class.getSimpleName(), Arrays.asList(groupProviderEntry));
-
- RecovererProvider recovererProvider = createRecoveryProvider(
- new ConfigurationEntry[]{groupProviderEntry, authenticationProviderEntry2, _authenticationProviderEntry1},
- new ConfiguredObject[]{groupProvider, authenticationProvider2, _authenticationProvider1});
-
- Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry);
-
- assertNotNull(broker);
- assertEquals("Unexpected number of authentication providers", 2, broker.getAuthenticationProviders().size());
-
}
public void testCreateBrokerWithGroupProvider()
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java
index c95f67beb9..b958ba1f56 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java
@@ -23,14 +23,17 @@ package org.apache.qpid.server.configuration.startup;
import static org.mockito.Mockito.mock;
import junit.framework.TestCase;
+import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer;
import org.apache.qpid.server.logging.LogRecorder;
import org.apache.qpid.server.logging.RootMessageLogger;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.GroupProvider;
+import org.apache.qpid.server.model.KeyStore;
import org.apache.qpid.server.model.Plugin;
import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.stats.StatisticsGatherer;
@@ -42,7 +45,8 @@ public class DefaultRecovererProviderTest extends TestCase
{
String[] supportedTypes = {Broker.class.getSimpleName(),
VirtualHost.class.getSimpleName(), AuthenticationProvider.class.getSimpleName(),
- GroupProvider.class.getSimpleName(), Plugin.class.getSimpleName(), Port.class.getSimpleName()};
+ GroupProvider.class.getSimpleName(), Plugin.class.getSimpleName(), Port.class.getSimpleName(),
+ KeyStore.class.getSimpleName(), TrustStore.class.getSimpleName()};
// mocking the required object
StatisticsGatherer statisticsGatherer = mock(StatisticsGatherer.class);
@@ -51,7 +55,7 @@ public class DefaultRecovererProviderTest extends TestCase
RootMessageLogger rootMessageLogger = mock(RootMessageLogger.class);
TaskExecutor taskExecutor = mock(TaskExecutor.class);
- DefaultRecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, taskExecutor);
+ DefaultRecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, taskExecutor, mock(BrokerOptions.class));
for (String configuredObjectType : supportedTypes)
{
ConfiguredObjectRecoverer<?> recovever = provider.getRecoverer(configuredObjectType);
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java
index 6713574e4b..d6f03a9758 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java
@@ -30,6 +30,7 @@ import org.apache.qpid.server.configuration.ConfigurationEntry;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.GroupProvider;
+import org.apache.qpid.server.model.adapter.GroupProviderFactory;
import org.apache.qpid.server.plugin.GroupManagerFactory;
import org.apache.qpid.server.plugin.QpidServiceLoader;
import org.apache.qpid.server.security.group.GroupManager;
@@ -46,6 +47,7 @@ public class GroupProviderRecovererTest extends TestCase
private QpidServiceLoader<GroupManagerFactory> _groupManagerServiceLoader;
private Broker _broker;
private ConfigurationEntry _configurationEntry;
+ private GroupProviderFactory _groupProviderFactory;
@SuppressWarnings("unchecked")
protected void setUp() throws Exception
@@ -58,6 +60,7 @@ public class GroupProviderRecovererTest extends TestCase
_groupManagerServiceLoader = mock(QpidServiceLoader.class);
when(_groupManagerServiceLoader.instancesOf(GroupManagerFactory.class)).thenReturn(Collections.singletonList(_factory ));
+ _groupProviderFactory = new GroupProviderFactory(_groupManagerServiceLoader);
_broker = mock(Broker.class);
@@ -70,8 +73,9 @@ public class GroupProviderRecovererTest extends TestCase
{
GroupManager groupManager = mock(GroupManager.class);
String name = groupManager.getClass().getSimpleName();
+ _attributes.put(GroupProvider.NAME, name);
when(_factory.createInstance(_attributes)).thenReturn(groupManager);
- GroupProviderRecoverer groupProviderRecoverer = new GroupProviderRecoverer(_groupManagerServiceLoader);
+ GroupProviderRecoverer groupProviderRecoverer = new GroupProviderRecoverer(_groupProviderFactory);
GroupProvider groupProvider = groupProviderRecoverer.create(null, _configurationEntry, _broker);
assertNotNull("Null group provider", groupProvider);
assertEquals("Unexpected name", name, groupProvider.getName());
@@ -82,7 +86,7 @@ public class GroupProviderRecovererTest extends TestCase
{
when(_factory.createInstance(_attributes)).thenReturn(null);
- GroupProviderRecoverer groupProviderRecoverer = new GroupProviderRecoverer(_groupManagerServiceLoader);
+ GroupProviderRecoverer groupProviderRecoverer = new GroupProviderRecoverer(_groupProviderFactory);
try
{
groupProviderRecoverer.create(null, _configurationEntry, _broker);
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/KeyStoreRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/KeyStoreRecovererTest.java
index 0d7dc1bb06..e0a736df89 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/KeyStoreRecovererTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/KeyStoreRecovererTest.java
@@ -27,12 +27,15 @@ import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
+import javax.net.ssl.KeyManagerFactory;
+
+import junit.framework.TestCase;
+
import org.apache.qpid.server.configuration.ConfigurationEntry;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.KeyStore;
-import org.apache.qpid.server.model.TrustStore;
-
-import junit.framework.TestCase;
+import org.apache.qpid.server.model.adapter.AbstractKeyStoreAdapter;
+import org.apache.qpid.test.utils.TestSSLConstants;
public class KeyStoreRecovererTest extends TestCase
{
@@ -40,6 +43,7 @@ public class KeyStoreRecovererTest extends TestCase
public void testCreateWithAllAttributesProvided()
{
Map<String, Object> attributes = getKeyStoreAttributes();
+ Map<String, Object> attributesCopy = new HashMap<String, Object>(attributes);
UUID id = UUID.randomUUID();
Broker broker = mock(Broker.class);
@@ -49,36 +53,27 @@ public class KeyStoreRecovererTest extends TestCase
KeyStoreRecoverer recovever = new KeyStoreRecoverer();
- KeyStore KeyStore = recovever.create(null, entry, broker);
- assertNotNull("Key store configured object is not created", KeyStore);
- assertEquals(id, KeyStore.getId());
- assertEquals("my-secret-password", KeyStore.getPassword());
+ KeyStore keyStore = recovever.create(null, entry, broker);
+ assertNotNull("Key store configured object is not created", keyStore);
+ assertEquals(id, keyStore.getId());
- assertNull("Password was unexpectedly returned from configured object", KeyStore.getAttribute(TrustStore.PASSWORD));
+ //verify we can retrieve the actual password using the method
+ assertEquals(TestSSLConstants.BROKER_TRUSTSTORE_PASSWORD, keyStore.getPassword());
+ assertNotNull(keyStore.getPassword());
- // password attribute should not be exposed by a key store configured object
- // so, we should set password value to null in the map being used to create the key store configured object
- attributes.put(KeyStore.PASSWORD, null);
- for (Map.Entry<String, Object> attribute : attributes.entrySet())
+ //verify that we havent configured the key store with the actual dummy password value
+ assertFalse(AbstractKeyStoreAdapter.DUMMY_PASSWORD_MASK.equals(keyStore.getPassword()));
+
+ // Verify the remaining attributes, including that the password value returned
+ // via getAttribute is actually the dummy value and not the real password
+ attributesCopy.put(KeyStore.PASSWORD, AbstractKeyStoreAdapter.DUMMY_PASSWORD_MASK);
+ for (Map.Entry<String, Object> attribute : attributesCopy.entrySet())
{
- Object attributeValue = KeyStore.getAttribute(attribute.getKey());
+ Object attributeValue = keyStore.getAttribute(attribute.getKey());
assertEquals("Unexpected value of attribute '" + attribute.getKey() + "'", attribute.getValue(), attributeValue);
}
}
- private Map<String, Object> getKeyStoreAttributes()
- {
- Map<String, Object> attributes = new HashMap<String, Object>();
- attributes.put(KeyStore.NAME, getName());
- attributes.put(KeyStore.PATH, "/path/to/KeyStore");
- attributes.put(KeyStore.PASSWORD, "my-secret-password");
- attributes.put(KeyStore.TYPE, "NON-JKS");
- attributes.put(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM, "NON-STANDARD");
- attributes.put(KeyStore.CERTIFICATE_ALIAS, "my-cert-alias");
- attributes.put(KeyStore.DESCRIPTION, "description");
- return attributes;
- }
-
public void testCreateWithMissedRequiredAttributes()
{
Map<String, Object> attributes = getKeyStoreAttributes();
@@ -108,4 +103,16 @@ public class KeyStoreRecovererTest extends TestCase
}
}
+ private Map<String, Object> getKeyStoreAttributes()
+ {
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(KeyStore.NAME, getName());
+ attributes.put(KeyStore.PATH, TestSSLConstants.BROKER_KEYSTORE);
+ attributes.put(KeyStore.PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
+ attributes.put(KeyStore.TYPE, "jks");
+ attributes.put(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM, KeyManagerFactory.getDefaultAlgorithm());
+ attributes.put(KeyStore.CERTIFICATE_ALIAS, "java-broker");
+ return attributes;
+ }
+
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/TrustStoreRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/TrustStoreRecovererTest.java
index 5e7784bc06..4d92f99306 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/TrustStoreRecovererTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/TrustStoreRecovererTest.java
@@ -27,16 +27,21 @@ import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
+import javax.net.ssl.TrustManagerFactory;
+
import org.apache.qpid.server.configuration.ConfigurationEntry;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.TrustStore;
+import org.apache.qpid.server.model.adapter.AbstractKeyStoreAdapter;
import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestSSLConstants;
public class TrustStoreRecovererTest extends QpidTestCase
{
public void testCreateWithAllAttributesProvided()
{
Map<String, Object> attributes = getTrustStoreAttributes();
+ Map<String, Object> attributesCopy = new HashMap<String, Object>(attributes);
UUID id = UUID.randomUUID();
Broker broker = mock(Broker.class);
@@ -44,38 +49,29 @@ public class TrustStoreRecovererTest extends QpidTestCase
when(entry.getAttributes()).thenReturn(attributes);
when(entry.getId()).thenReturn(id);
- TrustStoreRecoverer recovever = new TrustStoreRecoverer();
+ TrustStoreRecoverer recoverer = new TrustStoreRecoverer();
- TrustStore trustStore = recovever.create(null, entry, broker);
+ TrustStore trustStore = recoverer.create(null, entry, broker);
assertNotNull("Trust store configured object is not created", trustStore);
assertEquals(id, trustStore.getId());
- assertEquals("my-secret-password", trustStore.getPassword());
- assertNull("Password was unexpectedly returned from configured object", trustStore.getAttribute(TrustStore.PASSWORD));
+ //verify we can retrieve the actual password using the method
+ assertEquals(TestSSLConstants.BROKER_TRUSTSTORE_PASSWORD, trustStore.getPassword());
+ assertNotNull(trustStore.getPassword());
+
+ //verify that we havent configured the trust store with the actual dummy password value
+ assertFalse(AbstractKeyStoreAdapter.DUMMY_PASSWORD_MASK.equals(trustStore.getPassword()));
- // password attribute should not be exposed by a trust store configured object
- // so, we should set password value to null in the map being used to create the trust store configured object
- attributes.put(TrustStore.PASSWORD, null);
- for (Map.Entry<String, Object> attribute : attributes.entrySet())
+ // Verify the remaining attributes, including that the password value returned
+ // via getAttribute is actually the dummy value and not the real password
+ attributesCopy.put(TrustStore.PASSWORD, AbstractKeyStoreAdapter.DUMMY_PASSWORD_MASK);
+ for (Map.Entry<String, Object> attribute : attributesCopy.entrySet())
{
Object attributeValue = trustStore.getAttribute(attribute.getKey());
assertEquals("Unexpected value of attribute '" + attribute.getKey() + "'", attribute.getValue(), attributeValue);
}
}
- private Map<String, Object> getTrustStoreAttributes()
- {
- Map<String, Object> attributes = new HashMap<String, Object>();
- attributes.put(TrustStore.NAME, getName());
- attributes.put(TrustStore.PATH, "/path/to/truststore");
- attributes.put(TrustStore.PASSWORD, "my-secret-password");
- attributes.put(TrustStore.TYPE, "NON-JKS");
- attributes.put(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM, "NON-STANDARD");
- attributes.put(TrustStore.PEERS_ONLY, Boolean.TRUE);
- attributes.put(TrustStore.DESCRIPTION, "Description");
- return attributes;
- }
-
public void testCreateWithMissedRequiredAttributes()
{
Map<String, Object> attributes = getTrustStoreAttributes();
@@ -106,4 +102,16 @@ public class TrustStoreRecovererTest extends QpidTestCase
}
}
+ private Map<String, Object> getTrustStoreAttributes()
+ {
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(TrustStore.NAME, getName());
+ attributes.put(TrustStore.PATH, TestSSLConstants.BROKER_TRUSTSTORE);
+ attributes.put(TrustStore.PASSWORD, TestSSLConstants.BROKER_TRUSTSTORE_PASSWORD);
+ attributes.put(TrustStore.TYPE, "jks");
+ attributes.put(TrustStore.TRUST_MANAGER_FACTORY_ALGORITHM, TrustManagerFactory.getDefaultAlgorithm());
+ attributes.put(TrustStore.PEERS_ONLY, Boolean.TRUE);
+ return attributes;
+ }
+
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java
index adb4472694..d56481340b 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java
@@ -60,7 +60,6 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase
_brokerId = UUID.randomUUID();
_brokerAttributes = new HashMap<String, Object>();
_brokerAttributes.put(Broker.DEFAULT_VIRTUAL_HOST, "test");
- _brokerAttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider1");
_brokerAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, 9);
_brokerAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 8);
_brokerAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, 7);
@@ -71,7 +70,6 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase
_brokerAttributes.put(Broker.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS, 2);
_brokerAttributes.put(Broker.QUEUE_DEAD_LETTER_QUEUE_ENABLED, true);
_brokerAttributes.put(Broker.VIRTUALHOST_HOUSEKEEPING_CHECK_PERIOD, 1);
- _brokerAttributes.put(Broker.ACL_FILE, "/path/to/acl");
_brokerAttributes.put(Broker.CONNECTION_SESSION_COUNT_LIMIT, 1000);
_brokerAttributes.put(Broker.CONNECTION_HEART_BEAT_DELAY, 2000);
_brokerAttributes.put(Broker.STATISTICS_REPORTING_PERIOD, 4000);
@@ -171,7 +169,6 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase
ConfigurationEntry brokerConfigEntry = _store.getRootEntry();
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(Broker.DEFAULT_VIRTUAL_HOST, "test");
- attributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider1");
attributes.put(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, 19);
attributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 18);
attributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, 17);
@@ -182,7 +179,6 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase
attributes.put(Broker.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS, 12);
attributes.put(Broker.QUEUE_DEAD_LETTER_QUEUE_ENABLED, false);
attributes.put(Broker.VIRTUALHOST_HOUSEKEEPING_CHECK_PERIOD, 11);
- attributes.put(Broker.ACL_FILE, "/path/to/acl1");
attributes.put(Broker.CONNECTION_SESSION_COUNT_LIMIT, 11000);
attributes.put(Broker.CONNECTION_HEART_BEAT_DELAY, 12000);
attributes.put(Broker.STATISTICS_REPORTING_PERIOD, 14000);
@@ -284,7 +280,7 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase
attributes.put(TrustStore.PATH, "/path/to/truststore");
attributes.put(TrustStore.PASSWORD, "my-secret-password");
attributes.put(TrustStore.TYPE, "NON-JKS");
- attributes.put(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM, "NON-STANDARD");
+ attributes.put(TrustStore.TRUST_MANAGER_FACTORY_ALGORITHM, "NON-STANDARD");
attributes.put(TrustStore.DESCRIPTION, "Description");
ConfigurationEntry trustStoreEntry = new ConfigurationEntry(trustStoreId, TrustStore.class.getSimpleName(), attributes,
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStoreTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStoreTest.java
index 1cb760f611..b30508ee0b 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStoreTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStoreTest.java
@@ -72,20 +72,20 @@ public class JsonConfigurationEntryStoreTest extends ConfigurationEntryStoreTest
public void testAttributeIsResolvedFromSystemProperties()
{
- String aclLocation = "path/to/acl/" + getTestName();
- setTestSystemProperty("my.test.property", aclLocation);
+ String defaultVhost = getTestName();
+ setTestSystemProperty("my.test.property", defaultVhost);
ConfigurationEntryStore store = getStore();
ConfigurationEntry brokerConfigEntry = store.getRootEntry();
Map<String, Object> attributes = new HashMap<String, Object>(brokerConfigEntry.getAttributes());
- attributes.put(Broker.ACL_FILE, "${my.test.property}");
+ attributes.put(Broker.DEFAULT_VIRTUAL_HOST, "${my.test.property}");
ConfigurationEntry updatedBrokerEntry = new ConfigurationEntry(brokerConfigEntry.getId(), Broker.class.getSimpleName(),
attributes, brokerConfigEntry.getChildrenIds(), store);
store.save(updatedBrokerEntry);
JsonConfigurationEntryStore store2 = new JsonConfigurationEntryStore(_storeFile.getAbsolutePath(), null);
- assertEquals("Unresolved ACL value", aclLocation, store2.getRootEntry().getAttributes().get(Broker.ACL_FILE));
+ assertEquals("Unresolved default virtualhost value", defaultVhost, store2.getRootEntry().getAttributes().get(Broker.DEFAULT_VIRTUAL_HOST));
}
public void testCreateEmptyStore()
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java
index 52e021240e..d9d3c9fe8f 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java
@@ -176,7 +176,17 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase
assertEquals("Unexpected state", State.QUIESCED, portEntry.getAttributes().get(Port.STATE));
}
- public void testVirtualHostEntryIsQuiesced()
+ public void testVirtualHostEntryIsNotQuiescedByDefault()
+ {
+ virtualHostEntryQuiescedStatusTestImpl(false);
+ }
+
+ public void testVirtualHostEntryIsQuiescedWhenRequested()
+ {
+ virtualHostEntryQuiescedStatusTestImpl(true);
+ }
+
+ private void virtualHostEntryQuiescedStatusTestImpl(boolean mmQuiesceVhosts)
{
UUID virtualHostId = UUID.randomUUID();
ConfigurationEntry virtualHost = mock(ConfigurationEntry.class);
@@ -188,11 +198,17 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase
when(_store.getEntry(virtualHostId)).thenReturn(virtualHost);
when(_root.getChildrenIds()).thenReturn(new HashSet<UUID>(Arrays.asList(_portEntryId, virtualHostId)));
+ State expectedState = mmQuiesceVhosts ? State.QUIESCED : null;
+ if(mmQuiesceVhosts)
+ {
+ _options.setManagementModeQuiesceVirtualHosts(mmQuiesceVhosts);
+ }
+
_handler = new ManagementModeStoreHandler(_store, _options);
ConfigurationEntry hostEntry = _handler.getEntry(virtualHostId);
Map<String, Object> hostAttributes = hostEntry.getAttributes();
- assertEquals("Unexpected state", State.QUIESCED, hostAttributes.get(VirtualHost.STATE));
+ assertEquals("Unexpected state", expectedState, hostAttributes.get(VirtualHost.STATE));
hostAttributes.remove(VirtualHost.STATE);
assertEquals("Unexpected attributes", attributes, hostAttributes);
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/filter/JMSSelectorFilterTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/filter/JMSSelectorFilterTest.java
new file mode 100644
index 0000000000..91002edfc6
--- /dev/null
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/filter/JMSSelectorFilterTest.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.filter;
+
+import junit.framework.TestCase;
+
+public class JMSSelectorFilterTest extends TestCase
+{
+ public void testEqualsAndHashCodeUsingSelectorString() throws Exception
+ {
+ final String selectorString = "1 = 1";
+
+ JMSSelectorFilter filter1 = new JMSSelectorFilter(new String(selectorString));
+ JMSSelectorFilter filter2 = new JMSSelectorFilter(new String(selectorString));
+
+ assertEquals(filter1 + " should equal itself", filter1, filter1);
+ assertFalse(filter1 + " should not equal null", filter1.equals(null));
+ assertEqualsAndHashcodeMatch(filter1, filter2);
+
+ JMSSelectorFilter differentFilter = new JMSSelectorFilter("2 = 2");
+ assertNotEqual(filter1, differentFilter);
+ }
+
+ private void assertEqualsAndHashcodeMatch(JMSSelectorFilter filter1, JMSSelectorFilter filter2)
+ {
+ String message = filter1 + " and " + filter2 + " should be equal";
+
+ assertEquals(message, filter1, filter2);
+ assertEquals(message, filter2, filter1);
+
+ assertEquals("Hashcodes of " + filter1 + " and " + filter2 + " should be equal",
+ filter1.hashCode(), filter2.hashCode());
+ }
+
+ private void assertNotEqual(JMSSelectorFilter filter, JMSSelectorFilter differentFilter)
+ {
+ assertFalse(filter.equals(differentFilter));
+ assertFalse(differentFilter.equals(filter));
+ }
+}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java
index 7c1db6348b..eb5c672eb8 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.model;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.configuration.ConfigurationEntry;
import org.apache.qpid.server.configuration.ConfigurationEntryStore;
import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer;
@@ -121,7 +122,7 @@ public class BrokerShutdownTest extends QpidTestCase
RootMessageLogger rootMessageLogger = mock(RootMessageLogger.class);
// recover the broker from the store
- RecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, _taskExecutor);
+ RecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, _taskExecutor, mock(BrokerOptions.class));
ConfiguredObjectRecoverer<? extends ConfiguredObject> brokerRecoverer = provider.getRecoverer(Broker.class.getSimpleName());
Broker broker = (Broker) brokerRecoverer.create(provider, store.getRootEntry());
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java
index a9303c264e..54826b8c88 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java
@@ -22,8 +22,8 @@ package org.apache.qpid.server.model.adapter;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.any;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -36,6 +36,7 @@ import java.util.UUID;
import org.apache.qpid.server.configuration.BrokerProperties;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.KeyStore;
import org.apache.qpid.server.model.Port;
@@ -47,8 +48,6 @@ import org.apache.qpid.test.utils.QpidTestCase;
public class PortFactoryTest extends QpidTestCase
{
private UUID _portId = UUID.randomUUID();
- private UUID _keyStoreId = UUID.randomUUID();
- private UUID _trustStoreId = UUID.randomUUID();
private int _portNumber = 123;
private Set<String> _tcpStringSet = Collections.singleton(Transport.TCP.name());
private Set<Transport> _tcpTransportSet = Collections.singleton(Transport.TCP);
@@ -60,19 +59,22 @@ public class PortFactoryTest extends QpidTestCase
private Broker _broker = mock(Broker.class);
private KeyStore _keyStore = mock(KeyStore.class);
private TrustStore _trustStore = mock(TrustStore.class);
-
+ private String _authProviderName = "authProvider";
+ private AuthenticationProvider _authProvider = mock(AuthenticationProvider.class);
private PortFactory _portFactory;
@Override
protected void setUp() throws Exception
{
+ when(_broker.findAuthenticationProviderByName(_authProviderName)).thenReturn(_authProvider);
+
setTestSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES, null);
setTestSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_INCLUDES, null);
_portFactory = new PortFactory();
_attributes.put(Port.PORT, _portNumber);
_attributes.put(Port.TRANSPORTS, _tcpStringSet);
-
+ _attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName);
_attributes.put(Port.TCP_NO_DELAY, "true");
_attributes.put(Port.RECEIVE_BUFFER_SIZE, "1");
_attributes.put(Port.SEND_BUFFER_SIZE, "2");
@@ -113,6 +115,7 @@ public class PortFactoryTest extends QpidTestCase
{
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(Port.PORT, 1);
+ attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName);
Port port = _portFactory.createPort(_portId, _broker, attributes);
assertNotNull(port);
@@ -134,15 +137,14 @@ public class PortFactoryTest extends QpidTestCase
public void testCreateAmqpPort()
{
- createAmqpPortTestImpl(false,false,false);
+ createAmqpPortTestImpl(false, false, false, null, null);
}
public void testCreateAmqpPortUsingSslFailsWithoutKeyStore()
{
- when(_broker.getKeyStores()).thenReturn(new ArrayList<KeyStore>());
try
{
- createAmqpPortTestImpl(true,false,false);
+ createAmqpPortTestImpl(true, false, false, null, null);
fail("expected exception due to lack of SSL keystore");
}
catch(IllegalConfigurationException e)
@@ -153,18 +155,22 @@ public class PortFactoryTest extends QpidTestCase
public void testCreateAmqpPortUsingSslSucceedsWithKeyStore()
{
- when(_broker.getKeyStores()).thenReturn(Collections.singleton(_keyStore));
+ String keyStoreName = "myKeyStore";
+ when(_broker.findKeyStoreByName(keyStoreName)).thenReturn(_keyStore);
- createAmqpPortTestImpl(true,false,false);
+ createAmqpPortTestImpl(true, false, false, keyStoreName, null);
}
public void testCreateAmqpPortNeedingClientAuthFailsWithoutTrustStore()
{
- when(_broker.getKeyStores()).thenReturn(Collections.singleton(_keyStore));
- when(_broker.getTrustStores()).thenReturn(new ArrayList<TrustStore>());
+ String keyStoreName = "myKeyStore";
+ when(_broker.findKeyStoreByName(keyStoreName)).thenReturn(_keyStore);
+
+ when(_broker.findTrustStoreByName(any(String.class))).thenReturn(null);
+
try
{
- createAmqpPortTestImpl(true,true,false);
+ createAmqpPortTestImpl(true, true, false, keyStoreName, null);
fail("expected exception due to lack of SSL truststore");
}
catch(IllegalConfigurationException e)
@@ -175,19 +181,23 @@ public class PortFactoryTest extends QpidTestCase
public void testCreateAmqpPortNeedingClientAuthSucceedsWithTrustStore()
{
- when(_broker.getKeyStores()).thenReturn(Collections.singleton(_keyStore));
- when(_broker.getTrustStores()).thenReturn(Collections.singleton(_trustStore));
+ String keyStoreName = "myKeyStore";
+ when(_broker.findKeyStoreByName(keyStoreName)).thenReturn(_keyStore);
+
+ String trustStoreName = "myTrustStore";
+ when(_broker.findTrustStoreByName(trustStoreName)).thenReturn(_trustStore);
- createAmqpPortTestImpl(true,true,false);
+ createAmqpPortTestImpl(true, true, false, keyStoreName, new String[]{trustStoreName});
}
public void testCreateAmqpPortWantingClientAuthFailsWithoutTrustStore()
{
- when(_broker.getKeyStores()).thenReturn(Collections.singleton(_keyStore));
- when(_broker.getTrustStores()).thenReturn(new ArrayList<TrustStore>());
+ String keyStoreName = "myKeyStore";
+ when(_broker.findKeyStoreByName(keyStoreName)).thenReturn(_keyStore);
+
try
{
- createAmqpPortTestImpl(true,false,true);
+ createAmqpPortTestImpl(true, false, true, keyStoreName, null);
fail("expected exception due to lack of SSL truststore");
}
catch(IllegalConfigurationException e)
@@ -198,13 +208,17 @@ public class PortFactoryTest extends QpidTestCase
public void testCreateAmqpPortWantingClientAuthSucceedsWithTrustStore()
{
- when(_broker.getKeyStores()).thenReturn(Collections.singleton(_keyStore));
- when(_broker.getTrustStores()).thenReturn(Collections.singleton(_trustStore));
+ String keyStoreName = "myKeyStore";
+ when(_broker.findKeyStoreByName(keyStoreName)).thenReturn(_keyStore);
+
+ String trustStoreName = "myTrustStore";
+ when(_broker.findTrustStoreByName(trustStoreName)).thenReturn(_trustStore);
- createAmqpPortTestImpl(true,false,true);
+ createAmqpPortTestImpl(true, false, true, keyStoreName, new String[]{trustStoreName});
}
- public void createAmqpPortTestImpl(boolean useSslTransport, boolean needClientAuth, boolean wantClientAuth)
+ public void createAmqpPortTestImpl(boolean useSslTransport, boolean needClientAuth, boolean wantClientAuth,
+ String keystoreName, String[] trustStoreNames)
{
Set<Protocol> amqp010ProtocolSet = Collections.singleton(Protocol.AMQP_0_10);
Set<String> amqp010StringSet = Collections.singleton(Protocol.AMQP_0_10.name());
@@ -225,6 +239,16 @@ public class PortFactoryTest extends QpidTestCase
_attributes.put(Port.WANT_CLIENT_AUTH, "true");
}
+ if(keystoreName != null)
+ {
+ _attributes.put(Port.KEY_STORE, keystoreName);
+ }
+
+ if(trustStoreNames != null)
+ {
+ _attributes.put(Port.TRUST_STORES, Arrays.asList(trustStoreNames));
+ }
+
Port port = _portFactory.createPort(_portId, _broker, _attributes);
assertNotNull(port);
@@ -254,6 +278,7 @@ public class PortFactoryTest extends QpidTestCase
Set<String> nonAmqpStringSet = Collections.singleton(Protocol.JMX_RMI.name());
_attributes = new HashMap<String, Object>();
_attributes.put(Port.PROTOCOLS, nonAmqpStringSet);
+ _attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName);
_attributes.put(Port.PORT, _portNumber);
_attributes.put(Port.TRANSPORTS, _tcpStringSet);
@@ -279,6 +304,7 @@ public class PortFactoryTest extends QpidTestCase
Set<String> nonAmqpStringSet = Collections.singleton(Protocol.JMX_RMI.name());
_attributes = new HashMap<String, Object>();
_attributes.put(Port.PROTOCOLS, nonAmqpStringSet);
+ _attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName);
_attributes.put(Port.PORT, _portNumber);
Port port = _portFactory.createPort(_portId, _broker, _attributes);
@@ -335,4 +361,29 @@ public class PortFactoryTest extends QpidTestCase
// pass
}
}
+
+ public void testCreateRMIPortRequestingSslFails()
+ {
+ String keyStoreName = "myKeyStore";
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(Port.PORT, 1);
+ attributes.put(Port.NAME, getTestName());
+ attributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
+ attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.RMI));
+ _attributes.put(Port.KEY_STORE, keyStoreName);
+
+ when(_broker.findKeyStoreByName(keyStoreName)).thenReturn(_keyStore);
+
+ try
+ {
+ _portFactory.createPort(_portId, _broker, attributes);
+ fail("RMI port creation should fail due to requesting SSL");
+ }
+ catch(IllegalConfigurationException e)
+ {
+ e.printStackTrace();
+ // pass
+ }
+ }
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java
deleted file mode 100644
index c41b9bf081..0000000000
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- *
- */
-package org.apache.qpid.server.security.auth.database;
-
-import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
-import org.apache.qpid.server.security.auth.UsernamePrincipal;
-import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5Initialiser;
-import org.apache.qpid.server.security.auth.sasl.plain.PlainInitialiser;
-
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.login.AccountNotFoundException;
-
-import java.io.File;
-import java.io.IOException;
-import java.security.Principal;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-public class PropertiesPrincipalDatabase implements PrincipalDatabase
-{
- private Properties _users;
-
- private Map<String, AuthenticationProviderInitialiser> _saslServers;
-
- public PropertiesPrincipalDatabase(Properties users)
- {
- _users = users;
-
- _saslServers = new HashMap<String, AuthenticationProviderInitialiser>();
-
- /**
- * Create Authenticators for Properties Principal Database.
- */
-
- // Accept MD5 incomming and use plain comparison with the file
- PlainInitialiser cram = new PlainInitialiser();
- cram.initialise(this);
- // Accept Plain incomming and hash it for comparison to the file.
- CRAMMD5Initialiser plain = new CRAMMD5Initialiser();
- plain.initialise(this, CRAMMD5Initialiser.HashDirection.INCOMMING);
-
- _saslServers.put(plain.getMechanismName(), cram);
- _saslServers.put(cram.getMechanismName(), plain);
- }
-
- public void setPassword(Principal principal, PasswordCallback callback) throws IOException, AccountNotFoundException
- {
- if (principal == null)
- {
- throw new IllegalArgumentException("principal must not be null");
- }
-
-
-
- final String pwd = _users.getProperty(principal.getName());
-
- if (pwd != null)
- {
- callback.setPassword(pwd.toCharArray());
- }
- else
- {
- throw new AccountNotFoundException("No account found for principal " + principal);
- }
- }
-
- public boolean verifyPassword(String principal, char[] password) throws AccountNotFoundException
- {
- //fixme this is not correct as toCharArray is not safe based on the type of string.
- char[] pwd = _users.getProperty(principal).toCharArray();
-
- return compareCharArray(pwd, password);
- }
-
- public boolean updatePassword(Principal principal, char[] password) throws AccountNotFoundException
- {
- return false; // updates denied
- }
-
- public boolean createPrincipal(Principal principal, char[] password)
- {
- return false; // updates denied
- }
-
- public boolean deletePrincipal(Principal principal) throws AccountNotFoundException
- {
- return false; // updates denied
- }
-
- private boolean compareCharArray(char[] a, char[] b)
- {
- boolean equal = false;
- if (a.length == b.length)
- {
- equal = true;
- int index = 0;
- while (equal && index < a.length)
- {
- equal = a[index] == b[index];
- index++;
- }
- }
- return equal;
- }
-
-
- public Map<String, AuthenticationProviderInitialiser> getMechanisms()
- {
- return _saslServers;
- }
-
- public List<Principal> getUsers()
- {
- return new LinkedList<Principal>(); //todo
- }
-
- public Principal getUser(String username)
- {
- if (_users.getProperty(username) != null)
- {
- return new UsernamePrincipal(username);
- }
- else
- {
- return null;
- }
- }
-
- public void reload() throws IOException
- {
- //No file to update from, so do nothing.
- }
-
- @Override
- public void open(File passwordFile)
- {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticatorTest.java
index 52b525dd80..a4dd97e6a1 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticatorTest.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpid.server.security.auth.rmi;
+package org.apache.qpid.server.security.auth.jmx;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.any;
@@ -38,14 +38,15 @@ import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.security.SubjectCreator;
import org.apache.qpid.server.security.auth.AuthenticationResult;
import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
+import org.apache.qpid.server.security.auth.jmx.JMXPasswordAuthenticator;
import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
import org.apache.qpid.server.security.SecurityManager;
/**
- * Tests the RMIPasswordAuthenticator and its collaboration with the AuthenticationManager.
+ * Tests the JMXPasswordAuthenticator and its collaboration with the AuthenticationManager.
*
*/
-public class RMIPasswordAuthenticatorTest extends TestCase
+public class JMXPasswordAuthenticatorTest extends TestCase
{
private static final String USERNAME = "guest";
private static final String PASSWORD = "password";
@@ -55,7 +56,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
private final Subject _loginSubject = new Subject();
private final String[] _credentials = new String[] {USERNAME, PASSWORD};
- private RMIPasswordAuthenticator _rmipa;
+ private JMXPasswordAuthenticator _rmipa;
private SubjectCreator _usernamePasswordOkaySuvjectCreator = createMockSubjectCreator(true, null);
private SubjectCreator _badPasswordSubjectCreator = createMockSubjectCreator(false, null);
@@ -63,7 +64,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
protected void setUp() throws Exception
{
when(_broker.getSecurityManager()).thenReturn(_securityManager);
- _rmipa = new RMIPasswordAuthenticator(_broker, new InetSocketAddress(8999));
+ _rmipa = new JMXPasswordAuthenticator(_broker, new InetSocketAddress(8999));
}
/**
@@ -93,7 +94,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
catch (SecurityException se)
{
assertEquals("Unexpected exception message",
- RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage());
+ JMXPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage());
}
}
@@ -110,7 +111,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
catch (SecurityException se)
{
assertEquals("Unexpected exception message",
- RMIPasswordAuthenticator.USER_NOT_AUTHORISED_FOR_MANAGEMENT, se.getMessage());
+ JMXPasswordAuthenticator.USER_NOT_AUTHORISED_FOR_MANAGEMENT, se.getMessage());
}
}
@@ -164,7 +165,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
catch (SecurityException se)
{
assertEquals("Unexpected exception message",
- RMIPasswordAuthenticator.SHOULD_BE_STRING_ARRAY, se.getMessage());
+ JMXPasswordAuthenticator.SHOULD_BE_STRING_ARRAY, se.getMessage());
}
}
@@ -185,7 +186,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
catch (SecurityException se)
{
assertEquals("Unexpected exception message",
- RMIPasswordAuthenticator.SHOULD_HAVE_2_ELEMENTS, se.getMessage());
+ JMXPasswordAuthenticator.SHOULD_HAVE_2_ELEMENTS, se.getMessage());
}
// Test handling of null credentials
@@ -199,7 +200,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
catch (SecurityException se)
{
assertEquals("Unexpected exception message",
- RMIPasswordAuthenticator.CREDENTIALS_REQUIRED, se.getMessage());
+ JMXPasswordAuthenticator.CREDENTIALS_REQUIRED, se.getMessage());
}
try
@@ -212,7 +213,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
catch (SecurityException se)
{
assertEquals("Unexpected exception message",
- RMIPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage());
+ JMXPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage());
}
try
@@ -225,7 +226,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase
catch (SecurityException se)
{
assertEquals("Unexpected exception message",
- RMIPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage());
+ JMXPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage());
}
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java
new file mode 100644
index 0000000000..5868f44b8f
--- /dev/null
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java
@@ -0,0 +1,140 @@
+package org.apache.qpid.server.security.auth.manager;
+
+import java.security.Principal;
+import java.util.Set;
+
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
+import org.apache.qpid.server.security.auth.sasl.SaslUtil;
+import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class SimpleAuthenticationManagerTest extends QpidTestCase
+{
+ private static final String TEST_USER = "testUser";
+ private static final String TEST_PASSWORD = "testPassword";
+ private AuthenticationManager _authenticationManager;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _authenticationManager = new SimpleAuthenticationManager(TEST_USER, TEST_PASSWORD);
+ }
+
+ public void testGetMechanisms()
+ {
+ assertEquals("Unexpected mechanisms", "PLAIN CRAM-MD5", _authenticationManager.getMechanisms());
+ }
+
+ public void testCreateSaslServerForUnsupportedMechanisms() throws Exception
+ {
+ String[] unsupported = new String[] { "EXTERNAL", "CRAM-MD5-HEX", "CRAM-MD5-HASHED", "ANONYMOUS", "GSSAPI"};
+ for (int i = 0; i < unsupported.length; i++)
+ {
+ String mechanism = unsupported[i];
+ try
+ {
+ _authenticationManager.createSaslServer(mechanism, "test", null);
+ fail("Mechanism " + mechanism + " should not be supported by SimpleAuthenticationManager");
+ }
+ catch (SaslException e)
+ {
+ // pass
+ }
+ }
+ }
+
+ public void testAuthenticateWithPlainSaslServer() throws Exception
+ {
+ AuthenticationResult result = authenticatePlain(TEST_USER, TEST_PASSWORD);
+ assertAuthenticated(result);
+ }
+
+ public void testAuthenticateWithPlainSaslServerInvalidPassword() throws Exception
+ {
+ AuthenticationResult result = authenticatePlain(TEST_USER, "wrong-password");
+ assertUnauthenticated(result);
+ }
+
+ public void testAuthenticateWithPlainSaslServerInvalidUsername() throws Exception
+ {
+ AuthenticationResult result = authenticatePlain("wrong-user", TEST_PASSWORD);
+ assertUnauthenticated(result);
+ }
+
+ public void testAuthenticateWithCramMd5SaslServer() throws Exception
+ {
+ AuthenticationResult result = authenticateCramMd5(TEST_USER, TEST_PASSWORD);
+ assertAuthenticated(result);
+ }
+
+ public void testAuthenticateWithCramMd5SaslServerInvalidPassword() throws Exception
+ {
+ AuthenticationResult result = authenticateCramMd5(TEST_USER, "wrong-password");
+ assertUnauthenticated(result);
+ }
+
+ public void testAuthenticateWithCramMd5SaslServerInvalidUsername() throws Exception
+ {
+ AuthenticationResult result = authenticateCramMd5("wrong-user", TEST_PASSWORD);
+ assertUnauthenticated(result);
+ }
+
+ public void testAuthenticateValidCredentials()
+ {
+ AuthenticationResult result = _authenticationManager.authenticate(TEST_USER, TEST_PASSWORD);
+ assertEquals("Unexpected authentication result", AuthenticationStatus.SUCCESS, result.getStatus());
+ assertAuthenticated(result);
+ }
+
+ public void testAuthenticateInvalidPassword()
+ {
+ AuthenticationResult result = _authenticationManager.authenticate(TEST_USER, "invalid");
+ assertUnauthenticated(result);
+ }
+
+ public void testAuthenticateInvalidUserName()
+ {
+ AuthenticationResult result = _authenticationManager.authenticate("invalid", TEST_PASSWORD);
+ assertUnauthenticated(result);
+ }
+
+ private void assertAuthenticated(AuthenticationResult result)
+ {
+ assertEquals("Unexpected authentication result", AuthenticationStatus.SUCCESS, result.getStatus());
+ Principal principal = result.getMainPrincipal();
+ assertEquals("Unexpected principal name", TEST_USER, principal.getName());
+ Set<Principal> principals = result.getPrincipals();
+ assertEquals("Unexpected principals size", 1, principals.size());
+ assertEquals("Unexpected principal name", TEST_USER, principals.iterator().next().getName());
+ }
+
+ private void assertUnauthenticated(AuthenticationResult result)
+ {
+ assertEquals("Unexpected authentication result", AuthenticationStatus.ERROR, result.getStatus());
+ assertNull("Unexpected principal", result.getMainPrincipal());
+ Set<Principal> principals = result.getPrincipals();
+ assertEquals("Unexpected principals size", 0, principals.size());
+ }
+
+ private AuthenticationResult authenticatePlain(String userName, String userPassword) throws SaslException, Exception
+ {
+ PlainSaslServer ss = (PlainSaslServer) _authenticationManager.createSaslServer("PLAIN", "test", null);
+ byte[] response = SaslUtil.generatePlainClientResponse(userName, userPassword);
+
+ return _authenticationManager.authenticate(ss, response);
+ }
+
+ private AuthenticationResult authenticateCramMd5(String userName, String userPassword) throws SaslException, Exception
+ {
+ SaslServer ss = _authenticationManager.createSaslServer("CRAM-MD5", "test", null);
+ byte[] challenge = ss.evaluateResponse(new byte[0]);
+ byte[] response = SaslUtil.generateCramMD5ClientResponse(userName, userPassword, challenge);
+
+ AuthenticationResult result = _authenticationManager.authenticate(ss, response);
+ return result;
+ }
+}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java
index e408fd73d5..3079222b1c 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java
@@ -20,88 +20,94 @@
*/
package org.apache.qpid.server.security.auth.sasl;
-import junit.framework.TestCase;
-
-import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabase;
-import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexInitialiser;
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import java.io.IOException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexInitialiser;
+import org.apache.qpid.test.utils.TestFileUtils;
+import org.apache.qpid.tools.security.Passwd;
/**
* These tests ensure that the Hex wrapping that the initialiser performs does actually operate when the handle method is called.
*/
public class CRAMMD5HexInitialiserTest extends TestCase
{
- public void testHex()
- {
- //Create User details for testing
- String user = "testUser";
- String password = "testPassword";
+ private static final String TEST_PASSWORD = "testPassword";
+ private static final String TEST_USER = "testUser";
+ private File _file;
- perform(user, password);
- }
-
- public void testHashedHex()
+ public void testHashedHex() throws Exception
{
- //Create User details for testing
- String user = "testUser";
- String password = "testPassword";
-
- //Create a hashed password that we then attempt to put through the call back mechanism.
- try
- {
- password = new String(MessageDigest.getInstance("MD5").digest(password.getBytes()));
- }
- catch (NoSuchAlgorithmException e)
- {
- fail(e.getMessage());
- }
-
- perform(user, password);
+ perform(TEST_USER, getHash(TEST_PASSWORD));
}
- public void perform(String user, String password)
+ public void perform(String user, char[] password) throws Exception
{
CRAMMD5HexInitialiser initialiser = new CRAMMD5HexInitialiser();
- //Use properties to create a PrincipalDatabase
- Properties users = new Properties();
- users.put(user, password);
-
- PropertiesPrincipalDatabase db = new PropertiesPrincipalDatabase(users);
-
+ PrincipalDatabase db = new Base64MD5PasswordFilePrincipalDatabase();
+ db.open(_file);
initialiser.initialise(db);
- //setup the callbacks
PasswordCallback passwordCallback = new PasswordCallback("password:", false);
NameCallback usernameCallback = new NameCallback("user:", user);
Callback[] callbacks = new Callback[]{usernameCallback, passwordCallback};
- //Check the
- try
+ assertNull("The password was not null before the handle call.", passwordCallback.getPassword());
+ initialiser.getCallbackHandler().handle(callbacks);
+
+ assertArrayEquals(toHex(password), passwordCallback.getPassword());
+ }
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _file = TestFileUtils.createTempFile(this, "password-file", new Passwd().getOutput(TEST_USER , TEST_PASSWORD));
+ }
+
+ public void tearDown() throws Exception
+ {
+ if (_file != null)
{
- assertNull("The password was not null before the handle call.", passwordCallback.getPassword());
- initialiser.getCallbackHandler().handle(callbacks);
+ _file.delete();
}
- catch (IOException e)
+ super.tearDown();
+ }
+
+ private char[] getHash(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException
+ {
+
+ byte[] data = text.getBytes("utf-8");
+
+ MessageDigest md = MessageDigest.getInstance("MD5");
+
+ for (byte b : data)
{
- fail(e.getMessage());
+ md.update(b);
}
- catch (UnsupportedCallbackException e)
+
+ byte[] digest = md.digest();
+
+ char[] hash = new char[digest.length];
+
+ int index = 0;
+ for (byte b : digest)
{
- fail(e.getMessage());
+ hash[index++] = (char) b;
}
- //Hex the password we initialised with and compare it with the passwordCallback
- assertArrayEquals(toHex(password.toCharArray()), passwordCallback.getPassword());
+ return hash;
}
private void assertArrayEquals(char[] expected, char[] actual)
@@ -135,4 +141,5 @@ public class CRAMMD5HexInitialiserTest extends TestCase
return hex;
}
+
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslUtil.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslUtil.java
new file mode 100644
index 0000000000..251ebc4c81
--- /dev/null
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslUtil.java
@@ -0,0 +1,85 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security.auth.sasl;
+
+import java.security.MessageDigest;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+public class SaslUtil
+{
+
+ private static byte SEPARATOR = 0;
+
+ public static byte[] generatePlainClientResponse(String userName, String userPassword) throws Exception
+ {
+ byte[] password = userPassword.getBytes("UTF8");
+ byte user[] = userName.getBytes("UTF8");
+ byte response[] = new byte[password.length + user.length + 2];
+ int size = 0;
+ response[size++] = SEPARATOR;
+ System.arraycopy(user, 0, response, size, user.length);
+ size += user.length;
+ response[size++] = SEPARATOR;
+ System.arraycopy(password, 0, response, size, password.length);
+ return response;
+ }
+
+ public static byte[] generateCramMD5HexClientResponse(String userName, String userPassword, byte[] challengeBytes)
+ throws Exception
+ {
+ String macAlgorithm = "HmacMD5";
+ byte[] digestedPasswordBytes = MessageDigest.getInstance("MD5").digest(userPassword.getBytes("UTF-8"));
+ byte[] hexEncodedDigestedPasswordBytes = toHex(digestedPasswordBytes).getBytes("UTF-8");
+ Mac mac = Mac.getInstance(macAlgorithm);
+ mac.init(new SecretKeySpec(hexEncodedDigestedPasswordBytes, macAlgorithm));
+ final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes);
+ String responseAsString = userName + " " + toHex(messageAuthenticationCode);
+ return responseAsString.getBytes();
+ }
+
+ public static byte[] generateCramMD5ClientResponse(String userName, String userPassword, byte[] challengeBytes)
+ throws Exception
+ {
+ String macAlgorithm = "HmacMD5";
+ Mac mac = Mac.getInstance(macAlgorithm);
+ mac.init(new SecretKeySpec(userPassword.getBytes("UTF-8"), macAlgorithm));
+ final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes);
+ String responseAsString = userName + " " + toHex(messageAuthenticationCode);
+ return responseAsString.getBytes();
+ }
+
+ public static String toHex(byte[] data)
+ {
+ StringBuffer hash = new StringBuffer();
+ for (int i = 0; i < data.length; i++)
+ {
+ String hex = Integer.toHexString(0xFF & data[i]);
+ if (hex.length() == 1)
+ {
+ hash.append('0');
+ }
+ hash.append(hex);
+ }
+ return hash.toString();
+ }
+}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java
index 934c0082ea..90308d316b 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java
@@ -35,8 +35,8 @@ public class FileGroupManagerFactoryTest extends TestCase
public void testInstanceCreated() throws Exception
{
- _configuration.put(GroupProvider.TYPE, FileGroupManagerFactory.FILE_GROUP_MANAGER_TYPE);
- _configuration.put(FileGroupManagerFactory.FILE, _emptyButValidGroupFile);
+ _configuration.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+ _configuration.put(FileGroupManagerFactory.PATH, _emptyButValidGroupFile);
GroupManager manager = _factory.createInstance(_configuration);
assertNotNull(manager);
@@ -60,8 +60,8 @@ public class FileGroupManagerFactoryTest extends TestCase
public void testRejectsConfigThatIsMissingAttributeValue() throws Exception
{
- _configuration.put(GroupProvider.TYPE, FileGroupManagerFactory.FILE_GROUP_MANAGER_TYPE);
- _configuration.put(FileGroupManagerFactory.FILE, null);
+ _configuration.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+ _configuration.put(FileGroupManagerFactory.PATH, null);
try
{
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerTest.java
index b83d25b206..152703d548 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerTest.java
@@ -20,13 +20,11 @@
package org.apache.qpid.server.security.group;
import java.io.File;
-import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.security.Principal;
import java.util.Properties;
import java.util.Set;
-import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.security.auth.UsernamePrincipal;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -62,17 +60,26 @@ public class FileGroupManagerTest extends QpidTestCase
public void testNonExistentGroupFile() throws Exception
{
- final String filePath = "/does.not.exist/";
-
+ final String filePath = TMP_FOLDER + File.separator + "non.existing";
+ File file = new File(filePath);
+ if (file.exists())
+ {
+ file.delete();
+ }
+ assertFalse("File should not exist", file.exists());
try
{
_manager = new FileGroupManager(filePath);
- fail("expected exception was not thrown");
+ assertFalse("File should be created", file.exists());
+ _manager.onCreate();
+ assertTrue("File should be created", file.exists());
+ _manager.open();
+ Set<Principal> groups = _manager.getGroupPrincipals();
+ assertTrue("No group should exist", groups.isEmpty());
}
- catch(IllegalConfigurationException ce)
+ finally
{
- assertNotNull(ce.getCause());
- assertTrue(ce.getCause() instanceof FileNotFoundException);
+ file.delete();
}
}
@@ -80,7 +87,7 @@ public class FileGroupManagerTest extends QpidTestCase
{
final String groupFileName = writeGroupFile();
_manager = new FileGroupManager(groupFileName);
-
+ _manager.open();
Set<Principal> principals = _manager.getGroupPrincipalsForUser("user1");
assertEquals(1, principals.size());
assertTrue(principals.contains(new GroupPrincipal("myGroup")));
@@ -90,7 +97,7 @@ public class FileGroupManagerTest extends QpidTestCase
{
final String groupFileName = writeGroupFile();
_manager = new FileGroupManager(groupFileName);
-
+ _manager.open();
Set<Principal> principals = _manager.getUserPrincipalsForGroup("myGroup");
assertEquals(1, principals.size());
assertTrue(principals.contains(new UsernamePrincipal("user1")));
@@ -100,7 +107,7 @@ public class FileGroupManagerTest extends QpidTestCase
{
final String groupFileName = writeGroupFile(MY_GROUP, MYGROUP_USERS, MY_GROUP2, MYGROUP_USERS);
_manager = new FileGroupManager(groupFileName);
-
+ _manager.open();
Set<Principal> principals = _manager.getGroupPrincipals();
assertEquals(2, principals.size());
assertTrue(principals.contains(new GroupPrincipal("myGroup")));
@@ -111,7 +118,7 @@ public class FileGroupManagerTest extends QpidTestCase
{
final String groupFileName = writeGroupFile();
_manager = new FileGroupManager(groupFileName);
-
+ _manager.open();
Set<Principal> principals = _manager.getGroupPrincipals();
assertEquals(1, principals.size());
@@ -126,7 +133,7 @@ public class FileGroupManagerTest extends QpidTestCase
{
final String groupFileName = writeGroupFile(MY_GROUP, MYGROUP_USERS);
_manager = new FileGroupManager(groupFileName);
-
+ _manager.open();
Set<Principal> principals = _manager.getGroupPrincipals();
assertEquals(1, principals.size());
@@ -140,7 +147,7 @@ public class FileGroupManagerTest extends QpidTestCase
{
final String groupFileName = writeGroupFile(MY_GROUP, MYGROUP_USERS);
_manager = new FileGroupManager(groupFileName);
-
+ _manager.open();
Set<Principal> principals = _manager.getUserPrincipalsForGroup("myGroup");
assertEquals(1, principals.size());
assertFalse(principals.contains(new UsernamePrincipal("user2")));
@@ -156,7 +163,7 @@ public class FileGroupManagerTest extends QpidTestCase
{
final String groupFileName = writeGroupFile(MY_GROUP, MYGROUP_USERS);
_manager = new FileGroupManager(groupFileName);
-
+ _manager.open();
Set<Principal> principals = _manager.getUserPrincipalsForGroup("myGroup");
assertEquals(1, principals.size());
assertTrue(principals.contains(new UsernamePrincipal("user1")));
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupProviderAttributeDescriptions.properties b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupProviderAttributeDescriptions.properties
new file mode 100644
index 0000000000..2c2d2ab9e3
--- /dev/null
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupProviderAttributeDescriptions.properties
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+path= File location*
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java
index 860928e380..ec3c006364 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java
@@ -77,7 +77,7 @@ public class BrokerTestHelper
RootMessageLogger rootMessageLogger = CurrentActor.get().getRootMessageLogger();
when(broker.getRootMessageLogger()).thenReturn(rootMessageLogger);
when(broker.getVirtualHostRegistry()).thenReturn(new VirtualHostRegistry());
- when(broker.getSecurityManager()).thenReturn(new SecurityManager(null));
+ when(broker.getSecurityManager()).thenReturn(new SecurityManager(mock(Broker.class), false));
GenericActor.setDefaultMessageLogger(rootMessageLogger);
return broker;
}
@@ -96,14 +96,14 @@ public class BrokerTestHelper
throws Exception
{
StatisticsGatherer statisticsGatherer = mock(StatisticsGatherer.class);
- VirtualHost host = new VirtualHostImpl(virtualHostRegistry, statisticsGatherer, new SecurityManager(null), virtualHostConfiguration);
+ VirtualHost host = new VirtualHostImpl(virtualHostRegistry, statisticsGatherer, new SecurityManager(mock(Broker.class), false), virtualHostConfiguration);
virtualHostRegistry.registerVirtualHost(host);
return host;
}
public static VirtualHost createVirtualHost(VirtualHostConfiguration virtualHostConfiguration) throws Exception
{
- return new VirtualHostImpl(null, mock(StatisticsGatherer.class), new SecurityManager(null), virtualHostConfiguration);
+ return new VirtualHostImpl(null, mock(StatisticsGatherer.class), new SecurityManager(mock(Broker.class), false), virtualHostConfiguration);
}
public static VirtualHost createVirtualHost(String name, VirtualHostRegistry virtualHostRegistry) throws Exception
@@ -156,7 +156,7 @@ public class BrokerTestHelper
public static Exchange createExchange(String hostName) throws Exception
{
- SecurityManager securityManager = new SecurityManager(null);
+ SecurityManager securityManager = new SecurityManager(mock(Broker.class), false);
VirtualHost virtualHost = mock(VirtualHost.class);
when(virtualHost.getName()).thenReturn(hostName);
when(virtualHost.getSecurityManager()).thenReturn(securityManager);
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/StringUtilTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/StringUtilTest.java
new file mode 100644
index 0000000000..93b4172792
--- /dev/null
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/StringUtilTest.java
@@ -0,0 +1,38 @@
+package org.apache.qpid.server.util;
+
+import org.apache.qpid.server.util.StringUtil;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class StringUtilTest extends QpidTestCase
+{
+ private StringUtil _util;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _util = new StringUtil();
+ }
+
+ public void testRandomAlphaNumericStringInt()
+ {
+ String password = _util.randomAlphaNumericString(10);
+ assertEquals("Unexpected password string length", 10, password.length());
+ assertCharacters(password);
+ }
+
+ private void assertCharacters(String password)
+ {
+ String numbers = "0123456789";
+ String letters = "abcdefghijklmnopqrstuvwxwy";
+ String others = "_-";
+ String expectedCharacters = (numbers + letters + letters.toUpperCase() + others);
+ char[] chars = password.toCharArray();
+ for (int i = 0; i < chars.length; i++)
+ {
+ char ch = chars[i];
+ assertTrue("Unexpected character " + ch, expectedCharacters.indexOf(ch) != -1);
+ }
+ }
+
+}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java
index 559a7f8aaf..4e58eae1d2 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java
@@ -211,7 +211,7 @@ public class VirtualHostImplTest extends QpidTestCase
_virtualHostRegistry = broker.getVirtualHostRegistry();
VirtualHostConfiguration configuration = new VirtualHostConfiguration(vhostName, config, broker);
- VirtualHost host = new VirtualHostImpl(_virtualHostRegistry, mock(StatisticsGatherer.class), new SecurityManager(null), configuration);
+ VirtualHost host = new VirtualHostImpl(_virtualHostRegistry, mock(StatisticsGatherer.class), new SecurityManager(mock(Broker.class), false), configuration);
_virtualHostRegistry.registerVirtualHost(host);
return host;
@@ -295,7 +295,7 @@ public class VirtualHostImplTest extends QpidTestCase
Configuration config = new PropertiesConfiguration();
config.setProperty("store.type", MemoryMessageStore.TYPE);
VirtualHostConfiguration configuration = new VirtualHostConfiguration(virtualHostName, config, broker);
- VirtualHost host = new VirtualHostImpl(_virtualHostRegistry, mock(StatisticsGatherer.class), new SecurityManager(null), configuration);
+ VirtualHost host = new VirtualHostImpl(_virtualHostRegistry, mock(StatisticsGatherer.class), new SecurityManager(mock(Broker.class), false), configuration);
_virtualHostRegistry.registerVirtualHost(host);
return host;
}
diff --git a/qpid/java/build.deps b/qpid/java/build.deps
index b53ac55b6d..c8a850bce9 100644
--- a/qpid/java/build.deps
+++ b/qpid/java/build.deps
@@ -47,17 +47,17 @@ slf4j-log4j=lib/required/slf4j-log4j12-1.6.4.jar
xalan=lib/required/xalan-2.7.0.jar
-jetty=lib/required/jetty-server-7.6.3.v20120416.jar
-jetty-continuation=lib/required/jetty-continuation-7.6.3.v20120416.jar
-jetty-security=lib/required/jetty-security-7.6.3.v20120416.jar
-jetty-util=lib/required/jetty-util-7.6.3.v20120416.jar
-jetty-io=lib/required/jetty-io-7.6.3.v20120416.jar
-jetty-http=lib/required/jetty-http-7.6.3.v20120416.jar
-jetty-servlet=lib/required/jetty-servlet-7.6.3.v20120416.jar
-jetty-websocket=lib/required/jetty-websocket-7.6.3.v20120416.jar
+jetty=lib/required/jetty-server-7.6.10.v20130312.jar
+jetty-continuation=lib/required/jetty-continuation-7.6.10.v20130312.jar
+jetty-security=lib/required/jetty-security-7.6.10.v20130312.jar
+jetty-util=lib/required/jetty-util-7.6.10.v20130312.jar
+jetty-io=lib/required/jetty-io-7.6.10.v20130312.jar
+jetty-http=lib/required/jetty-http-7.6.10.v20130312.jar
+jetty-servlet=lib/required/jetty-servlet-7.6.10.v20130312.jar
+jetty-websocket=lib/required/jetty-websocket-7.6.10.v20130312.jar
servlet-api=${geronimo-servlet}
-dojo=lib/required/dojo-war-1.7.2.war
+dojo=lib/required/dojo-war-1.8.3.war
jackson-core=lib/required/jackson-core-asl-1.9.0.jar
jackson-mapper=lib/required/jackson-mapper-asl-1.9.0.jar
diff --git a/qpid/java/client/example/src/main/java/org/apache/qpid/example/hello.properties b/qpid/java/client/example/src/main/java/org/apache/qpid/example/hello.properties
index 27ea66b318..fdfbd418f8 100644
--- a/qpid/java/client/example/src/main/java/org/apache/qpid/example/hello.properties
+++ b/qpid/java/client/example/src/main/java/org/apache/qpid/example/hello.properties
@@ -20,7 +20,7 @@ java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextF
# register some connection factories
# connectionfactory.[jndiname] = [ConnectionURL]
-connectionfactory.qpidConnectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672'
+connectionfactory.qpidConnectionfactory = amqp://guest:guest@clientid/?brokerlist='tcp://localhost:5672'
# Register an AMQP destination in JNDI
# destination.[jniName] = [Address Format]
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java b/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java
index 01381ad23f..158006f072 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java
@@ -31,7 +31,6 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
-import java.security.cert.X509Certificate;
import java.io.IOException;
import java.security.GeneralSecurityException;
@@ -39,7 +38,6 @@ import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.List;
/**
* Factory used to create SSLContexts. SSL needs to be configured
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestSSLConstants.java b/qpid/java/common/src/test/java/org/apache/qpid/test/utils/TestSSLConstants.java
index 5664e94bd9..c48f164d98 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestSSLConstants.java
+++ b/qpid/java/common/src/test/java/org/apache/qpid/test/utils/TestSSLConstants.java
@@ -28,4 +28,10 @@ public interface TestSSLConstants
String BROKER_KEYSTORE = "test-profiles/test_resources/ssl/java_broker_keystore.jks";
String BROKER_KEYSTORE_PASSWORD = "password";
+
+ String BROKER_PEERSTORE = "test-profiles/test_resources/ssl/java_broker_peerstore.jks";
+ String BROKER_PEERSTORE_PASSWORD = "password";
+
+ String BROKER_TRUSTSTORE = "test-profiles/test_resources/ssl/java_broker_truststore.jks";
+ String BROKER_TRUSTSTORE_PASSWORD = "password";
}
diff --git a/qpid/java/ivy.retrieve.xml b/qpid/java/ivy.retrieve.xml
index 4c8e935aca..78769da005 100644
--- a/qpid/java/ivy.retrieve.xml
+++ b/qpid/java/ivy.retrieve.xml
@@ -59,15 +59,15 @@
<dependency org="org.mockito" name="mockito-all" rev="1.9.0" transitive="false"/>
<dependency org="org.slf4j" name="slf4j-api" rev="1.6.4" transitive="false"/>
<dependency org="org.slf4j" name="slf4j-log4j12" rev="1.6.4" transitive="false"/>
- <dependency org="org.eclipse.jetty" name="jetty-server" rev="7.6.3.v20120416" transitive="false"/>
- <dependency org="org.eclipse.jetty" name="jetty-websocket" rev="7.6.3.v20120416" transitive="false"/>
- <dependency org="org.eclipse.jetty" name="jetty-continuation" rev="7.6.3.v20120416" transitive="false"/>
- <dependency org="org.eclipse.jetty" name="jetty-io" rev="7.6.3.v20120416" transitive="false"/>
- <dependency org="org.eclipse.jetty" name="jetty-http" rev="7.6.3.v20120416" transitive="false"/>
- <dependency org="org.eclipse.jetty" name="jetty-security" rev="7.6.3.v20120416" transitive="false"/>
- <dependency org="org.eclipse.jetty" name="jetty-servlet" rev="7.6.3.v20120416" transitive="false"/>
- <dependency org="org.eclipse.jetty" name="jetty-util" rev="7.6.3.v20120416" transitive="false"/>
- <dependency org="org.dojotoolkit" name="dojo-war" rev="1.7.2" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-server" rev="7.6.10.v20130312" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-websocket" rev="7.6.10.v20130312" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-continuation" rev="7.6.10.v20130312" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-io" rev="7.6.10.v20130312" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-http" rev="7.6.10.v20130312" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-security" rev="7.6.10.v20130312" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-servlet" rev="7.6.10.v20130312" transitive="false"/>
+ <dependency org="org.eclipse.jetty" name="jetty-util" rev="7.6.10.v20130312" transitive="false"/>
+ <dependency org="org.dojotoolkit" name="dojo-war" rev="1.8.3" transitive="false"/>
<dependency org="xalan" name="xalan" rev="2.7.0" transitive="false"/>
<dependency org="velocity" name="velocity" rev="1.4" transitive="false"/>
<dependency org="velocity" name="velocity-dep" rev="1.4" transitive="false"/>
diff --git a/qpid/java/lib/poms/jetty-continuation-7.6.3.v20120416.xml b/qpid/java/lib/poms/jetty-continuation-7.6.10.v20130312.xml
index 6ace17c18a..5beba95d17 100644
--- a/qpid/java/lib/poms/jetty-continuation-7.6.3.v20120416.xml
+++ b/qpid/java/lib/poms/jetty-continuation-7.6.10.v20130312.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-continuation</artifactId>
- <version>7.6.3.v20120416</version>
+ <version>7.6.10.v20130312</version>
</dep>
diff --git a/qpid/java/lib/poms/jetty-http-7.6.3.v20120416.xml b/qpid/java/lib/poms/jetty-http-7.6.10.v20130312.xml
index 02af020cfe..5c840bedd6 100644
--- a/qpid/java/lib/poms/jetty-http-7.6.3.v20120416.xml
+++ b/qpid/java/lib/poms/jetty-http-7.6.10.v20130312.xml
@@ -18,7 +18,7 @@
<dep>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
- <version>7.6.3.v20120416</version>
+ <version>7.6.10.v20130312</version>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
diff --git a/qpid/java/lib/poms/jetty-io-7.6.3.v20120416.xml b/qpid/java/lib/poms/jetty-io-7.6.10.v20130312.xml
index b6c865f0fb..9cec3998ea 100644
--- a/qpid/java/lib/poms/jetty-io-7.6.3.v20120416.xml
+++ b/qpid/java/lib/poms/jetty-io-7.6.10.v20130312.xml
@@ -18,7 +18,7 @@
<dep>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-io</artifactId>
- <version>7.6.3.v20120416</version>
+ <version>7.6.10.v20130312</version>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
diff --git a/qpid/java/lib/poms/jetty-security-7.6.3.v20120416.xml b/qpid/java/lib/poms/jetty-security-7.6.10.v20130312.xml
index ba643ccb97..9501750ba0 100644
--- a/qpid/java/lib/poms/jetty-security-7.6.3.v20120416.xml
+++ b/qpid/java/lib/poms/jetty-security-7.6.10.v20130312.xml
@@ -18,7 +18,7 @@
<dep>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
- <version>7.6.3.v20120416</version>
+ <version>7.6.10.v20130312</version>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
diff --git a/qpid/java/lib/poms/jetty-server-7.6.3.v20120416.xml b/qpid/java/lib/poms/jetty-server-7.6.10.v20130312.xml
index 1e7ce42623..587860b50f 100644
--- a/qpid/java/lib/poms/jetty-server-7.6.3.v20120416.xml
+++ b/qpid/java/lib/poms/jetty-server-7.6.10.v20130312.xml
@@ -18,7 +18,7 @@
<dep>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
- <version>7.6.3.v20120416</version>
+ <version>7.6.10.v20130312</version>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty.orbit</groupId>
diff --git a/qpid/java/lib/poms/jetty-servlet-7.6.3.v20120416.xml b/qpid/java/lib/poms/jetty-servlet-7.6.10.v20130312.xml
index 001bcce824..4c0ff0a41b 100644
--- a/qpid/java/lib/poms/jetty-servlet-7.6.3.v20120416.xml
+++ b/qpid/java/lib/poms/jetty-servlet-7.6.10.v20130312.xml
@@ -18,7 +18,7 @@
<dep>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
- <version>7.6.3.v20120416</version>
+ <version>7.6.10.v20130312</version>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
diff --git a/qpid/java/lib/poms/jetty-util-7.6.3.v20120416.xml b/qpid/java/lib/poms/jetty-util-7.6.10.v20130312.xml
index c40d7e5f60..f5c990248f 100644
--- a/qpid/java/lib/poms/jetty-util-7.6.3.v20120416.xml
+++ b/qpid/java/lib/poms/jetty-util-7.6.10.v20130312.xml
@@ -18,5 +18,5 @@
<dep>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
- <version>7.6.3.v20120416</version>
+ <version>7.6.10.v20130312</version>
</dep>
diff --git a/qpid/java/lib/poms/jetty-websocket-7.6.3.v20120416.xml b/qpid/java/lib/poms/jetty-websocket-7.6.10.v20130312.xml
index bba80d9236..4d3ebd1666 100644
--- a/qpid/java/lib/poms/jetty-websocket-7.6.3.v20120416.xml
+++ b/qpid/java/lib/poms/jetty-websocket-7.6.10.v20130312.xml
@@ -18,7 +18,7 @@
<dep>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
- <version>7.6.3.v20120416</version>
+ <version>7.6.10.v20130312</version>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
diff --git a/qpid/java/systests/etc/config-systests.json b/qpid/java/systests/etc/config-systests.json
index b06b469891..c47744c47c 100644
--- a/qpid/java/systests/etc/config-systests.json
+++ b/qpid/java/systests/etc/config-systests.json
@@ -19,23 +19,30 @@
*
*/
{
- "name": "QpidBroker",
- "defaultAuthenticationProvider" : "plain",
+ "name": "Broker",
"defaultVirtualHost" : "test",
- "keyStorePath": "${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_keystore.jks",
- "keyStorePassword": "password",
- "trustStorePath": "${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_truststore.jks",
- "trustStorePassword": "password",
"authenticationproviders" : [ {
"name" : "plain",
"type" : "PlainPasswordFile",
"path" : "${QPID_HOME}/etc/passwd"
} ],
+ "keystores" : [ {
+ "name" : "systestsKeyStore",
+ "path" : "${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_keystore.jks",
+ "password" : "password"
+ } ],
+ "truststores" : [ {
+ "name" : "systestsTrustStore",
+ "path" : "${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_truststore.jks",
+ "password" : "password"
+ } ],
"ports" : [ {
"name" : "amqp",
+ "authenticationProvider" : "plain",
"port" : "${test.port}"
}, {
"name" : "http",
+ "authenticationProvider" : "plain",
"port" : "${test.hport}",
"protocols" : [ "HTTP" ]
}, {
@@ -44,6 +51,7 @@
"protocols" : [ "RMI" ]
}, {
"name" : "jmx",
+ "authenticationProvider" : "plain",
"port" : "${test.cport}",
"protocols" : [ "JMX_RMI" ]
}],
@@ -61,4 +69,4 @@
"name" : "jmxManagement"
} ]
*/
-} \ No newline at end of file
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java
index 884e89fb65..71b763685e 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java
@@ -362,9 +362,12 @@ public class SSLTest extends QpidBrokerTestCase
Map<String, Object> sslPortAttributes = new HashMap<String, Object>();
sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT);
+ sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
sslPortAttributes.put(Port.NEED_CLIENT_AUTH, needClientAuth);
sslPortAttributes.put(Port.WANT_CLIENT_AUTH, wantClientAuth);
sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT);
+ sslPortAttributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE);
+ sslPortAttributes.put(Port.TRUST_STORES, Collections.singleton(TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE));
getBrokerConfiguration().addPortConfiguration(sslPortAttributes);
}
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java
index c5f5e06ae1..95a378f1f6 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java
@@ -95,9 +95,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
{
String TESTID="BRK-1006";
- // This logging startup code only occurs when you run a Java broker,
- // that broker must be started via Main so not an InVM broker.
- if (isJavaBroker() && isExternalBroker())
+ if (isJavaBroker())
{
startBroker();
@@ -165,8 +163,6 @@ public class BrokerLoggingTest extends AbstractTestLogging
*/
public void testBrokerStartupDefaultLog4j() throws Exception
{
- // This logging startup code only occurs when you run a Java broker,
- // that broker must be started via Main so not an InVM broker.
if (isJavaBroker() && isExternalBroker() && !isInternalBroker())
{
String TESTID = "BRK-1007";
@@ -256,7 +252,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
public void testBrokerStartupCustomLog4j() throws Exception
{
// This logging startup code only occurs when you run a Java broker
- if (isJavaBroker() && isExternalBroker())
+ if (isJavaBroker())
{
String customLog4j = getBrokerCommandLog4JFile().getAbsolutePath();
@@ -344,7 +340,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
{
// This logging startup code only occurs when you run a Java broker,
// that broker must be started via Main so not an InVM broker.
- if (isJavaBroker() && isExternalBroker())
+ if (isJavaBroker())
{
String TESTID = "BRK-1001";
@@ -426,9 +422,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
*/
public void testBrokerStartupListeningTCPDefault() throws Exception
{
- // This logging startup code only occurs when you run a Java broker,
- // that broker must be started via Main so not an InVM broker.
- if (isJavaBroker() && isExternalBroker())
+ if (isJavaBroker())
{
String TESTID = "BRK-1002";
@@ -484,7 +478,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
//3
String message = getMessageString(log);
assertTrue("Expected Listen log not correct" + message,
- message.endsWith("Listening on [TCP] port " + getPort()));
+ message.endsWith("Listening on TCP port " + getPort()));
validation = true;
}
@@ -534,9 +528,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
*/
public void testBrokerStartupListeningTCPSSL() throws Exception
{
- // This logging startup code only occurs when you run a Java broker,
- // that broker must be started via Main so not an InVM broker.
- if (isJavaBroker() && isExternalBroker())
+ if (isJavaBroker())
{
String TESTID = "BRK-1002";
@@ -545,6 +537,8 @@ public class BrokerLoggingTest extends AbstractTestLogging
sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT);
sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT);
+ sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
+ sslPortAttributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE);
getBrokerConfiguration().addPortConfiguration(sslPortAttributes);
startBroker();
@@ -595,16 +589,23 @@ public class BrokerLoggingTest extends AbstractTestLogging
assertEquals("Four listen messages should be found.",
4, listenMessages .size());
- //3
- //Check the first
- String message = getMessageString(getLog(listenMessages .get(0)));
- assertTrue("Expected Listen log not correct" + message,
- message.endsWith("Listening on [TCP] port " + getPort()));
+ int tcpStarted = 0;
+ int sslStarted = 0;
- // Check the third, ssl listen.
- message = getMessageString(getLog(listenMessages .get(2)));
- assertTrue("Expected Listen log not correct" + message,
- message.endsWith("Listening on [SSL] port " + DEFAULT_SSL_PORT));
+ for (String message : listenMessages)
+ {
+ if (message.endsWith("Listening on TCP port " + getPort()))
+ {
+ tcpStarted++;
+ }
+ if (message.endsWith("Listening on SSL port " + DEFAULT_SSL_PORT))
+ {
+ sslStarted++;
+ }
+ }
+
+ assertEquals("Unexpected number of logs 'Listening on TCP port'", 2, tcpStarted);
+ assertEquals("Unexpected number of logs 'Listening on SSL port'", 2, sslStarted);
//4 Test ports open
testSocketOpen(getPort());
@@ -643,9 +644,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
*/
public void testBrokerStartupReady() throws Exception
{
- // This logging startup code only occurs when you run a Java broker,
- // that broker must be started via Main so not an InVM broker.
- if (isJavaBroker() && isExternalBroker())
+ if (isJavaBroker())
{
String TESTID = "BRK-1004";
@@ -731,9 +730,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
*/
public void testBrokerShutdownListeningTCPDefault() throws Exception
{
- // This logging startup code only occurs when you run a Java broker,
- // that broker must be started via Main so not an InVM broker.
- if (isJavaBroker() && isExternalBroker())
+ if (isJavaBroker() && isInternalBroker())
{
String TESTID = "BRK-1003";
@@ -825,9 +822,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
*/
public void testBrokerShutdownListeningTCPSSL() throws Exception
{
- // This logging startup code only occurs when you run a Java broker,
- // that broker must be started via Main so not an InVM broker.
- if (isJavaBroker() && isExternalBroker())
+ if (isJavaBroker() && isInternalBroker())
{
String TESTID = "BRK-1003";
@@ -836,6 +831,8 @@ public class BrokerLoggingTest extends AbstractTestLogging
sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT);
sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT);
+ sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
+ sslPortAttributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE);
getBrokerConfiguration().addPortConfiguration(sslPortAttributes);
startBroker();
@@ -869,15 +866,23 @@ public class BrokerLoggingTest extends AbstractTestLogging
assertEquals("Two shutdown messages should be found.",
2, listenMessages.size());
- //3
- String message = getMessageString(getLog(listenMessages.get(0)));
- assertTrue("Expected shutdown log not correct" + message,
- message.endsWith("TCP port " + getPort()));
+ int tcpShuttingDown = 0;
+ int sslShuttingDown = 0;
- // Check second, ssl, listen.
- message = getMessageString(getLog(listenMessages.get(1)));
- assertTrue("Expected shutdown log not correct" + message,
- message.endsWith("TCP/SSL port " + DEFAULT_SSL_PORT));
+ for (String m : listenMessages)
+ {
+ if (m.endsWith("Shutting down : TCP port " + getPort()))
+ {
+ tcpShuttingDown++;
+ }
+ if (m.endsWith("Shutting down : SSL port " + DEFAULT_SSL_PORT))
+ {
+ sslShuttingDown++;
+ }
+ }
+
+ assertEquals("Unexpected number of logs 'Shutting down : TCP port'", 1, tcpShuttingDown);
+ assertEquals("Unexpected number of logs 'Shutting down : SSL port'", 1, sslShuttingDown);
//4
//Test Port closed
@@ -913,9 +918,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
*/
public void testBrokerShutdownStopped() throws Exception
{
- // This logging startup code only occurs when you run a Java broker,
- // that broker must be started via Main so not an InVM broker.
- if (isJavaBroker() && isExternalBroker())
+ if (isJavaBroker() && isInternalBroker())
{
String TESTID = "BRK-1005";
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java
index 1ea105ae1a..25dd5fd2f8 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java
@@ -105,22 +105,25 @@ public class VirtualHostLoggingTest extends AbstractTestLogging
*/
public void testVirtualhostClosure() throws Exception
{
- stopBroker();
+ if (isJavaBroker() && isInternalBroker())
+ {
+ stopBroker();
- // Wait for the correct VHT message to arrive.
- waitForMessage(VHT_PREFIX + "1002");
+ // Wait for the correct VHT message to arrive.
+ waitForMessage(VHT_PREFIX + "1002");
- // Validate each vhost logs a closure
- List<String> results = findMatches(VHT_PREFIX + "1002");
+ // Validate each vhost logs a closure
+ List<String> results = findMatches(VHT_PREFIX + "1002");
- try
- {
- assertEquals("Each vhost did not close their store.", 1, results.size());
- }
- catch (AssertionFailedError afe)
- {
- dumpLogs(results, _monitor);
- throw afe;
+ try
+ {
+ assertEquals("Each vhost did not close their store.", 1, results.size());
+ }
+ catch (AssertionFailedError afe)
+ {
+ dumpLogs(results, _monitor);
+ throw afe;
+ }
}
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java
index 782709b24f..41d93b5ca2 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ModelTest.java
@@ -65,9 +65,10 @@ public class ModelTest extends QpidBrokerTestCase
@Override
public void setUp() throws Exception
{
+ getBrokerConfiguration().addJmxManagementConfiguration();
+
// Create a JMX Helper
_jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
super.setUp();
// Open the JMX Connection
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java
index 13053d02df..8bebcc703d 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java
@@ -64,8 +64,9 @@ public class ProducerFlowControlTest extends AbstractTestLogging
public void setUp() throws Exception
{
+ getBrokerConfiguration().addJmxManagementConfiguration();
+
_jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
_jmxUtilConnected=false;
super.setUp();
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
index 814936f342..7a3edd316f 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
@@ -63,7 +63,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements
@Override
public void setUp() throws Exception
{
- getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, System.getProperty(QPID_HOME) + "/etc/groups-systests");
+ getBrokerConfiguration().addGroupFileConfiguration(System.getProperty(QPID_HOME) + "/etc/groups-systests");
// run test specific setup
String testSetup = StringUtils.replace(getName(), "test", "setUp");
@@ -110,7 +110,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements
if (vhost == null)
{
- testcase.getBrokerConfiguration().setBrokerAttribute(Broker.ACL_FILE, aclFile.getAbsolutePath());
+ testcase.getBrokerConfiguration().addAclFileConfiguration(aclFile.getAbsolutePath());
}
else
{
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
index 1830040007..e200741161 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
@@ -21,6 +21,7 @@ package org.apache.qpid.server.security.acl;
import org.apache.qpid.management.common.mbeans.ServerInformation;
import org.apache.qpid.server.security.access.ObjectType;
import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
@@ -43,11 +44,15 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
@Override
public void setUp() throws Exception
{
+ //remove the normal 'test' vhost, we will configure the vhosts below
+ getBrokerConfiguration(0).removeObjectConfiguration(TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST);
+
createTestVirtualHost(0, TEST_VHOST);
createTestVirtualHost(0, TEST2_VHOST);
+ getBrokerConfiguration().addJmxManagementConfiguration();
+
_jmx = new JMXTestUtils(this);
- _jmx.setUp();
super.setUp();
_jmx.open();
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java
index 2e051d93dd..6cc4ec17c7 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java
@@ -20,12 +20,16 @@
*/
package org.apache.qpid.server.security.auth.manager;
+import static org.apache.qpid.test.utils.TestSSLConstants.BROKER_PEERSTORE;
+import static org.apache.qpid.test.utils.TestSSLConstants.BROKER_PEERSTORE_PASSWORD;
import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE;
import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE_PASSWORD;
import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE;
import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD;
import static org.apache.qpid.test.utils.TestSSLConstants.UNTRUSTED_KEYSTORE;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -38,9 +42,9 @@ import org.apache.commons.configuration.ConfigurationException;
import org.apache.qpid.client.AMQConnectionURL;
import org.apache.qpid.management.common.mbeans.ManagedConnection;
import org.apache.qpid.server.model.AuthenticationProvider;
-import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.plugin.AuthenticationManagerFactory;
import org.apache.qpid.test.utils.JMXTestUtils;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
@@ -52,6 +56,7 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase
protected void setUp() throws Exception
{
// not calling super.setUp() to avoid broker start-up
+ setSystemProperty("javax.net.debug", "ssl");
}
/**
@@ -61,7 +66,6 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase
public void testExternalAuthenticationManagerOnSSLPort() throws Exception
{
setCommonBrokerSSLProperties(true);
- getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
super.setUp();
setClientKeystoreProperties();
@@ -88,13 +92,13 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase
}
/**
- * Tests that when EXTERNAL authentication manager is set as the default, clients presenting certificates are able to connect.
- * Also, checks a client with valid username and password but not using ssl is unable to connect to the non SSL port.
+ * Tests that when EXTERNAL authentication manager is set on the non-SSL port, clients with valid username and password
+ * but not using ssl are unable to connect to the non-SSL port.
*/
- public void testExternalAuthenticationManagerAsDefault() throws Exception
+ public void testExternalAuthenticationManagerOnNonSslPort() throws Exception
{
setCommonBrokerSSLProperties(true);
- getBrokerConfiguration().setBrokerAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
+ getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT, Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
super.setUp();
setClientKeystoreProperties();
@@ -109,25 +113,15 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase
{
// pass
}
-
- try
- {
- getExternalSSLConnection(false);
- }
- catch (JMSException e)
- {
- fail("Should be able to create a connection to the SSL port. " + e.getMessage());
- }
}
/**
- * Tests that when EXTERNAL authentication manager is set as the default, clients without certificates are unable to connect to the SSL port
+ * Tests that when EXTERNAL authentication manager is used, clients without certificates are unable to connect to the SSL port
* even with valid username and password.
*/
public void testExternalAuthenticationManagerWithoutClientKeyStore() throws Exception
{
setCommonBrokerSSLProperties(false);
- getBrokerConfiguration().setBrokerAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
super.setUp();
setClientTrustoreProperties();
@@ -150,7 +144,6 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase
public void testExternalAuthenticationDeniesUntrustedClientCert() throws Exception
{
setCommonBrokerSSLProperties(true);
- getBrokerConfiguration().setBrokerAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
super.setUp();
setUntrustedClientKeystoreProperties();
@@ -168,31 +161,85 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase
}
/**
- * Tests that when using the EXTERNAL auth provide and the broker 'peerstore' is configured to contain a certificate that is
- * otherwise untrusted by the broker [truststore], clients using that certificate will then be able to connect.
+ * Tests that when using the EXTERNAL auth provider and a 'peersOnly' truststore, clients using certs directly in
+ * in the store will be able to connect and clients using certs signed by the same CA but not in the store will not.
*/
- public void testExternalAuthenticationWithPeerStoreAllowsOtherwiseUntrustedClientCert() throws Exception
+ public void testExternalAuthenticationWithPeersOnlyTrustStore() throws Exception
{
- setCommonBrokerSSLProperties(true);
- getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
+ externalAuthenticationWithPeersOnlyTrustStoreTestImpl(false);
+ }
+
+ /**
+ * Tests that when using the EXTERNAL auth provider, with both the regular trust store and a 'peersOnly' truststore, clients
+ * using certs signed by the CA in the trust store are allowed even if they are not present in the 'peersOnly' store.
+ */
+ public void testExternalAuthenticationWithRegularAndPeersOnlyTrustStores() throws Exception
+ {
+ externalAuthenticationWithPeersOnlyTrustStoreTestImpl(true);
+ }
+
+ private void externalAuthenticationWithPeersOnlyTrustStoreTestImpl(boolean useTrustAndPeerStore) throws Exception
+ {
+ String peerStoreName = "myPeerStore";
+
+ List<String> storeNames = null;
+ if(useTrustAndPeerStore)
+ {
+ //Use the regular trust store AND the 'peersOnly' store. The regular trust store trusts the CA that
+ //signed both the app1 and app2 certs. The peersOnly store contains only app1 and so does not trust app2
+ storeNames = Arrays.asList(TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE, peerStoreName);
+ }
+ else
+ {
+ //use only the 'peersOnly' store, which contains only app1 and so does not trust app2
+ storeNames = Arrays.asList(peerStoreName);
+ }
- //Use the untrusted client keystore as the brokers peerstore to make the broker trust the cert.
- getBrokerConfiguration().setBrokerAttribute(Broker.PEER_STORE_PATH, UNTRUSTED_KEYSTORE);
- getBrokerConfiguration().setBrokerAttribute(Broker.PEER_STORE_PASSWORD, KEYSTORE_PASSWORD);
+ //set the brokers SSL config, inc which SSL stores to use
+ setCommonBrokerSSLProperties(true, storeNames);
+
+ //add the peersOnly store to the config
+ Map<String, Object> sslTrustStoreAttributes = new HashMap<String, Object>();
+ sslTrustStoreAttributes.put(TrustStore.NAME, peerStoreName);
+ sslTrustStoreAttributes.put(TrustStore.PATH, BROKER_PEERSTORE);
+ sslTrustStoreAttributes.put(TrustStore.PASSWORD, BROKER_PEERSTORE_PASSWORD);
+ sslTrustStoreAttributes.put(TrustStore.PEERS_ONLY, true);
+ getBrokerConfiguration().addTrustStoreConfiguration(sslTrustStoreAttributes);
super.setUp();
- setUntrustedClientKeystoreProperties();
+ setClientKeystoreProperties();
setClientTrustoreProperties();
try
{
- getExternalSSLConnection(false);
- fail("Untrusted client's validation against the broker's multi store manager unexpectedly passed.");
+ //use the app1 cert, which IS in the peerstore (and has CA in the trustStore)
+ getExternalSSLConnection(false, "&ssl_cert_alias='app1'");
+ }
+ catch (JMSException e)
+ {
+ fail("Client's validation against the broker's multi store manager unexpectedly failed, when configured store was expected to allow.");
+ }
+
+ try
+ {
+ //use the app2 cert, which is NOT in the peerstore (but is signed by the same CA as app1)
+ getExternalSSLConnection(false, "&ssl_cert_alias='app2'");
+ if(!useTrustAndPeerStore)
+ {
+ fail("Client's validation against the broker's multi store manager unexpectedly passed, when configured store was expected to deny.");
+ }
}
catch (JMSException e)
{
- // expected
+ if(useTrustAndPeerStore)
+ {
+ fail("Client's validation against the broker's multi store manager unexpectedly failed, when configured store was expected to allow.");
+ }
+ else
+ {
+ //expected, the CA in trust store should allow both app1 and app2
+ }
}
}
@@ -203,10 +250,9 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase
public void testExternalAuthenticationManagerUsernameAsCN() throws Exception
{
JMXTestUtils jmxUtils = new JMXTestUtils(this);
- jmxUtils.setUp();
setCommonBrokerSSLProperties(true);
- getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
+ getBrokerConfiguration().addJmxManagementConfiguration();
super.setUp();
@@ -215,7 +261,7 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase
try
{
- getExternalSSLConnection(false);
+ getExternalSSLConnection(false, "&ssl_cert_alias='app2'");
}
catch (JMSException e)
{
@@ -237,11 +283,10 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase
public void testExternalAuthenticationManagerUsernameAsDN() throws Exception
{
JMXTestUtils jmxUtils = new JMXTestUtils(this);
- jmxUtils.setUp();
setCommonBrokerSSLProperties(true);
- getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER, ExternalAuthenticationManagerFactory.ATTRIBUTE_USE_FULL_DN, "true");
+ getBrokerConfiguration().addJmxManagementConfiguration();
super.setUp();
@@ -250,7 +295,7 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase
try
{
- getExternalSSLConnection(false);
+ getExternalSSLConnection(false, "&ssl_cert_alias='app2'");
}
catch (JMSException e)
{
@@ -267,32 +312,47 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase
private Connection getExternalSSLConnection(boolean includeUserNameAndPassword) throws Exception
{
- String url = "amqp://%s@test/?brokerlist='tcp://localhost:%s?ssl='true'&sasl_mechs='EXTERNAL'&ssl_cert_alias='app2''";
+ return getExternalSSLConnection(includeUserNameAndPassword, "");
+ }
+
+ private Connection getExternalSSLConnection(boolean includeUserNameAndPassword, String optionString) throws Exception
+ {
+ String url = "amqp://%s@test/?brokerlist='tcp://localhost:%s?ssl='true'&sasl_mechs='EXTERNAL'%s'";
if (includeUserNameAndPassword)
{
- url = String.format(url, "guest:guest", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT));
+ url = String.format(url, "guest:guest", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT), optionString);
}
else
{
- url = String.format(url, ":", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT));
+ url = String.format(url, ":", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT), optionString);
}
return getConnection(new AMQConnectionURL(url));
}
private void setCommonBrokerSSLProperties(boolean needClientAuth) throws ConfigurationException
{
+ setCommonBrokerSSLProperties(needClientAuth, Collections.singleton(TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE));
+ }
+
+ private void setCommonBrokerSSLProperties(boolean needClientAuth, Collection<String> trustStoreNames) throws ConfigurationException
+ {
TestBrokerConfiguration config = getBrokerConfiguration();
+
Map<String, Object> sslPortAttributes = new HashMap<String, Object>();
sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT);
sslPortAttributes.put(Port.NEED_CLIENT_AUTH, String.valueOf(needClientAuth));
sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT);
+ sslPortAttributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE);
+ sslPortAttributes.put(Port.TRUST_STORES, trustStoreNames);
config.addPortConfiguration(sslPortAttributes);
Map<String, Object> externalAuthProviderAttributes = new HashMap<String, Object>();
- externalAuthProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, ExternalAuthenticationManagerFactory.PROVIDER_TYPE);
externalAuthProviderAttributes.put(AuthenticationProvider.NAME, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
+ externalAuthProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, ExternalAuthenticationManagerFactory.PROVIDER_TYPE);
config.addAuthenticationProviderConfiguration(externalAuthProviderAttributes);
+
+ config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
}
private void setUntrustedClientKeystoreProperties()
@@ -311,6 +371,5 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase
{
setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE);
setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);
- setSystemProperty("javax.net.debug", "ssl");
}
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java
index 40346d7424..44057025ba 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java
@@ -56,6 +56,8 @@ public class MultipleAuthenticationManagersTest extends QpidBrokerTestCase
sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT);
sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT);
+ sslPortAttributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE);
+ sslPortAttributes.put(Port.TRUST_STORES, Collections.singleton(TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE));
sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER);
config.addPortConfiguration(sslPortAttributes);
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java
index 954208e78e..3f979bea27 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java
@@ -40,8 +40,10 @@ public class BrokerManagementTest extends QpidBrokerTestCase
public void setUp() throws Exception
{
+ getBrokerConfiguration().addJmxManagementConfiguration();
+
_jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
+
super.setUp();
_jmxUtils.open();
_managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST);
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java
index 28d7bf4aed..34b13dfaca 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java
@@ -51,8 +51,10 @@ public class ConnectionManagementTest extends QpidBrokerTestCase
public void setUp() throws Exception
{
+ getBrokerConfiguration().addJmxManagementConfiguration();
+
_jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp(); // modifies broker config therefore must be done before super.setUp()
+
super.setUp();
_jmxUtils.open();
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java
index 3c3bbdca41..3717c1594d 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java
@@ -47,8 +47,9 @@ public class LoggingManagementTest extends QpidBrokerTestCase
public void setUp() throws Exception
{
+ getBrokerConfiguration().addJmxManagementConfiguration();
+
_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.
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java
index 47b38381c5..69e81cf85d 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java
@@ -49,8 +49,10 @@ public class ManagementActorLoggingTest extends AbstractTestLogging
@Override
public void setUp() throws Exception
{
+ getBrokerConfiguration().addJmxManagementConfiguration();
+
_jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
+
super.setUp();
_jmxUtils.open();
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
index 9279287117..7a66fe6a7c 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
@@ -277,7 +277,6 @@ public class ManagementLoggingTest extends AbstractTestLogging
List<String> closeResults = null;
try
{
- jmxUtils.setUp();
jmxUtils.open();
openResults = waitAndFindMatches("MNG-1007");
}
@@ -314,11 +313,9 @@ public class ManagementLoggingTest extends AbstractTestLogging
if(useManagementSSL)
{
- // This test requires we have an ssl connection
+ // This test requires we have ssl, change the transport and add they keystore to the port config
config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_JMX_PORT, Port.TRANSPORTS, Collections.singleton(Transport.SSL));
-
- setSystemProperty("javax.net.ssl.keyStore", "test-profiles/test_resources/ssl/java_broker_keystore.jks");
- setSystemProperty("javax.net.ssl.keyStorePassword", "password");
+ config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_JMX_PORT, Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE);
}
startBroker();
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
index 0d3289d1bd..448886d056 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
@@ -87,8 +87,9 @@ public class QueueManagementTest extends QpidBrokerTestCase
public void setUp() throws Exception
{
+ getBrokerConfiguration().addJmxManagementConfiguration();
+
_jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
super.setUp();
_sourceQueueName = getTestQueueName() + "_src";
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java
index 72fbd65acc..6e4ea13cfc 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java
@@ -56,8 +56,9 @@ public class StatisticsTest extends QpidBrokerTestCase
createTestVirtualHost(0, TEST_VIRTUALHOST1);
createTestVirtualHost(0, TEST_VIRTUALHOST2);
+ getBrokerConfiguration().addJmxManagementConfiguration();
+
_jmxUtils = new JMXTestUtils(this, TEST_USER, TEST_PASSWORD);
- _jmxUtils.setUp();
super.setUp();
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java
index 7eff1c89ee..9fc92c98a3 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java
@@ -65,9 +65,9 @@ public class UserManagementTest extends QpidBrokerTestCase
newAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, getAuthenticationManagerType());
newAttributes.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_PATH, _passwordFile.getAbsolutePath());
getBrokerConfiguration().setObjectAttributes(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, newAttributes);
+ getBrokerConfiguration().addJmxManagementConfiguration();
_jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
super.setUp();
_jmxUtils.open();
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AccessControlProviderRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AccessControlProviderRestTest.java
new file mode 100644
index 0000000000..ae7c648197
--- /dev/null
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AccessControlProviderRestTest.java
@@ -0,0 +1,256 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.model.AccessControlProvider;
+import org.apache.qpid.server.security.access.FileAccessControlProviderConstants;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+import org.apache.qpid.test.utils.TestFileUtils;
+
+public class AccessControlProviderRestTest extends QpidRestTestCase
+{
+ private static final String ALLOWED_USER = "allowed";
+ private static final String DENIED_USER = "denied";
+ private static final String OTHER_USER = "other";
+
+ private String _aclFileContent1 =
+ "ACL ALLOW-LOG " + ALLOWED_USER + " ACCESS MANAGEMENT\n" +
+ "ACL ALLOW-LOG " + ALLOWED_USER + " CONFIGURE BROKER\n" +
+ "ACL DENY-LOG ALL ALL";
+
+ private String _aclFileContent2 =
+ "ACL ALLOW-LOG " + ALLOWED_USER + " ACCESS MANAGEMENT\n" +
+ "ACL ALLOW-LOG " + OTHER_USER + " ACCESS MANAGEMENT\n" +
+ "ACL ALLOW-LOG " + ALLOWED_USER + " CONFIGURE BROKER\n" +
+ "ACL DENY-LOG ALL ALL";
+
+ @Override
+ protected void customizeConfiguration() throws ConfigurationException, IOException
+ {
+ super.customizeConfiguration();
+ getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER, OTHER_USER);
+
+ getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT,
+ "httpBasicAuthenticationEnabled", true);
+ }
+
+ public void testCreateAccessControlProvider() throws Exception
+ {
+ String accessControlProviderName = getTestName();
+
+ //verify that the access control provider doesn't exist, and
+ //in doing so implicitly verify that the 'denied' user can
+ //actually currently connect because no ACL is in effect yet
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+ assertAccessControlProviderExistence(accessControlProviderName, false);
+
+ //create the access control provider using the 'allowed' user
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+ int responseCode = createAccessControlProvider(accessControlProviderName, _aclFileContent1);
+ assertEquals("Access control provider creation should be allowed", 201, responseCode);
+
+ //verify it exists with the 'allowed' user
+ assertAccessControlProviderExistence(accessControlProviderName, true);
+
+ //verify the 'denied' user can no longer access the management interface
+ //due to the just-created ACL file now preventing it
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+ assertCanAccessManagementInterface(accessControlProviderName, false);
+ }
+
+ public void testRemoveAccessControlProvider() throws Exception
+ {
+ String accessControlProviderName = getTestName();
+
+ //verify that the access control provider doesn't exist, and
+ //in doing so implicitly verify that the 'denied' user can
+ //actually currently connect because no ACL is in effect yet
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+ assertAccessControlProviderExistence(accessControlProviderName, false);
+
+ //create the access control provider using the 'allowed' user
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+ int responseCode = createAccessControlProvider(accessControlProviderName, _aclFileContent1);
+ assertEquals("Access control provider creation should be allowed", 201, responseCode);
+
+ //verify it exists with the 'allowed' user
+ assertAccessControlProviderExistence(accessControlProviderName, true);
+
+ //verify the 'denied' user can no longer access the management interface
+ //due to the just-created ACL file now preventing it
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+ assertCanAccessManagementInterface(accessControlProviderName, false);
+
+ //remove the access control provider using the 'allowed' user
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/accesscontrolprovider/" + accessControlProviderName, "DELETE", null);
+ assertEquals("Access control provider deletion should be allowed", 200, responseCode);
+ assertAccessControlProviderExistence(accessControlProviderName, false);
+
+ //verify it is gone again, using the 'denied' user to implicitly confirm it is
+ //now able to connect to the management interface again because the ACL was removed.
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+ assertAccessControlProviderExistence(accessControlProviderName, false);
+ }
+
+ public void testReplaceAccessControlProvider() throws Exception
+ {
+ String accessControlProviderName1 = getTestName() + "1";
+
+ //verify that the access control provider doesn't exist, and
+ //in doing so implicitly verify that the 'denied' user can
+ //actually currently connect because no ACL is in effect yet
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+ assertAccessControlProviderExistence(accessControlProviderName1, false);
+
+ //create the access control provider using the 'allowed' user
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+ int responseCode = createAccessControlProvider(accessControlProviderName1, _aclFileContent1);
+ assertEquals("Access control provider creation should be allowed", 201, responseCode);
+
+ //verify it exists with the 'allowed' user
+ assertAccessControlProviderExistence(accessControlProviderName1, true);
+
+ //verify the 'denied' and 'other' user can no longer access the management
+ //interface due to the just-created ACL file now preventing them
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+ assertCanAccessManagementInterface(accessControlProviderName1, false);
+ getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
+ assertCanAccessManagementInterface(accessControlProviderName1, false);
+
+ //create the replacement access control provider using the 'allowed' user.
+ String accessControlProviderName2 = getTestName() + "2";
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+ responseCode = createAccessControlProvider(accessControlProviderName2, _aclFileContent2);
+ assertEquals("Access control provider creation should be allowed", 201, responseCode);
+
+ //Verify that it took effect immediately, replacing the first access control provider
+
+ //verify the 'denied' user still can't access the management interface, but the 'other' user now CAN.
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+ assertCanAccessManagementInterface(accessControlProviderName2, false);
+ getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
+ assertCanAccessManagementInterface(accessControlProviderName2, true);
+
+ //remove the original access control provider using the 'allowed' user
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+ responseCode = getRestTestHelper().submitRequest("/rest/accesscontrolprovider/" + accessControlProviderName1, "DELETE", null);
+ assertEquals("Access control provider deletion should be allowed", 200, responseCode);
+ assertAccessControlProviderExistence(accessControlProviderName1, false);
+
+ //verify the 'denied' user still can't access the management interface, the 'other' user still can, thus
+ //confirming that the second access control provider is still in effect
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+ assertCanAccessManagementInterface(accessControlProviderName2, false);
+ getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
+ assertCanAccessManagementInterface(accessControlProviderName2, true);
+ }
+
+
+ public void testAddAndRemoveSecondAccessControlProviderReinstatesOriginal() throws Exception
+ {
+ String accessControlProviderName1 = getTestName() + "1";
+
+ //verify that the access control provider doesn't exist, and
+ //in doing so implicitly verify that the 'denied' user can
+ //actually currently connect because no ACL is in effect yet
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+ assertAccessControlProviderExistence(accessControlProviderName1, false);
+
+ //create the access control provider using the 'allowed' user
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+ int responseCode = createAccessControlProvider(accessControlProviderName1, _aclFileContent1);
+ assertEquals("Access control provider creation should be allowed", 201, responseCode);
+
+ //verify it exists with the 'allowed' user
+ assertAccessControlProviderExistence(accessControlProviderName1, true);
+
+ //verify the 'denied' and 'other' user can no longer access the management
+ //interface due to the just-created ACL file now preventing them
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+ assertCanAccessManagementInterface(accessControlProviderName1, false);
+ getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
+ assertCanAccessManagementInterface(accessControlProviderName1, false);
+
+ //create the replacement access control provider using the 'allowed' user.
+ String accessControlProviderName2 = getTestName() + "2";
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+ responseCode = createAccessControlProvider(accessControlProviderName2, _aclFileContent2);
+ assertEquals("Access control provider creation should be allowed", 201, responseCode);
+
+ //Verify that it took effect immediately, replacing the first access control provider
+
+ //verify the 'denied' user still can't access the management interface, but the 'other' user now CAN.
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+ assertCanAccessManagementInterface(accessControlProviderName2, false);
+ getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
+ assertCanAccessManagementInterface(accessControlProviderName2, true);
+
+ //remove the second access control provider using the 'allowed' user
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+ responseCode = getRestTestHelper().submitRequest("/rest/accesscontrolprovider/" + accessControlProviderName2, "DELETE", null);
+ assertEquals("Access control provider deletion should be allowed", 200, responseCode);
+ assertAccessControlProviderExistence(accessControlProviderName2, false);
+
+ //verify the 'denied' user still can't access the management interface, the
+ //'other' now CANT again, the 'allowed' still can, thus confirming that the
+ //first access control provider is now in effect once again
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+ assertCanAccessManagementInterface(accessControlProviderName2, false);
+ getRestTestHelper().setUsernameAndPassword(OTHER_USER, OTHER_USER);
+ assertCanAccessManagementInterface(accessControlProviderName2, false);
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+ assertCanAccessManagementInterface(accessControlProviderName2, true);
+ }
+
+ private void assertCanAccessManagementInterface(String accessControlProviderName, boolean canAccess) throws Exception
+ {
+ int expected = canAccess ? 200 : 403;
+ int responseCode = getRestTestHelper().submitRequest("/rest/accesscontrolprovider/" + accessControlProviderName, "GET", null);
+ assertEquals("Unexpected response code", expected, responseCode);
+ }
+
+ private void assertAccessControlProviderExistence(String accessControlProviderName, boolean exists) throws Exception
+ {
+ String path = "/rest/accesscontrolprovider/" + accessControlProviderName;
+ List<Map<String, Object>> providers = getRestTestHelper().getJsonAsList(path);
+ assertEquals("Unexpected result", exists, !providers.isEmpty());
+ }
+
+ private int createAccessControlProvider(String accessControlProviderName, String content) throws Exception
+ {
+ File file = TestFileUtils.createTempFile(this, ".acl", content);
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(AccessControlProvider.NAME, accessControlProviderName);
+ attributes.put(AccessControlProvider.TYPE, FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE);
+ attributes.put(FileAccessControlProviderConstants.PATH, file.getAbsoluteFile());
+
+ return getRestTestHelper().submitRequest("/rest/accesscontrolprovider/" + accessControlProviderName, "PUT", attributes);
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AnonymousAccessRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AnonymousAccessRestTest.java
new file mode 100644
index 0000000000..907b476bc4
--- /dev/null
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AnonymousAccessRestTest.java
@@ -0,0 +1,95 @@
+package org.apache.qpid.systest.rest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.plugin.AuthenticationManagerFactory;
+import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+
+public class AnonymousAccessRestTest extends QpidRestTestCase
+{
+ @Override
+ public void startBroker()
+ {
+ // prevent broker from starting in setUp
+ }
+
+ public void startBrokerNow() throws Exception
+ {
+ super.startBroker();
+ }
+
+ @Override
+ protected void customizeConfiguration() throws ConfigurationException, IOException
+ {
+ super.customizeConfiguration();
+ TestBrokerConfiguration config = getBrokerConfiguration();
+
+ Map<String, Object> anonymousAuthProviderAttributes = new HashMap<String, Object>();
+ anonymousAuthProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, AnonymousAuthenticationManagerFactory.PROVIDER_TYPE);
+ anonymousAuthProviderAttributes.put(AuthenticationProvider.NAME, TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER);
+ config.addAuthenticationProviderConfiguration(anonymousAuthProviderAttributes);
+
+ // set anonymous authentication provider on http port for the tests
+ config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.AUTHENTICATION_PROVIDER,
+ TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER);
+ config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, "httpBasicAuthenticationEnabled", false);
+
+ // reset credentials
+ getRestTestHelper().setUsernameAndPassword(null, null);
+ }
+
+ public void testGetWithAnonymousProvider() throws Exception
+ {
+ startBrokerNow();
+
+ Map<String, Object> brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker");
+ assertNotNull("Unexpected broker attributes", brokerDetails);
+ assertNotNull("Unexpected value of attribute " + Broker.ID, brokerDetails.get(Broker.ID));
+ }
+
+ public void testPutAnonymousProvider() throws Exception
+ {
+ startBrokerNow();
+
+ Map<String, Object> brokerAttributes = new HashMap<String, Object>();
+ brokerAttributes.put(Broker.DEFAULT_VIRTUAL_HOST, TEST3_VIRTUALHOST);
+
+ int response = getRestTestHelper().submitRequest("/rest/broker", "PUT", brokerAttributes);
+ assertEquals("Unexpected update response", 200, response);
+
+ Map<String, Object> brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker");
+ assertNotNull("Unexpected broker attributes", brokerDetails);
+ assertNotNull("Unexpected value of attribute " + Broker.ID, brokerDetails.get(Broker.ID));
+ assertEquals("Unexpected default virtual host", TEST3_VIRTUALHOST, brokerDetails.get(Broker.DEFAULT_VIRTUAL_HOST));
+ }
+
+ public void testGetWithPasswordAuthProvider() throws Exception
+ {
+ getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.AUTHENTICATION_PROVIDER,
+ TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
+ startBrokerNow();
+
+ int response = getRestTestHelper().submitRequest("/rest/broker", "GET", null);
+ assertEquals("Anonymous access should be denied", 401, response);
+ }
+
+ public void testPutWithPasswordAuthProvider() throws Exception
+ {
+ getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.AUTHENTICATION_PROVIDER,
+ TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
+ startBrokerNow();
+
+ Map<String, Object> brokerAttributes = new HashMap<String, Object>();
+ brokerAttributes.put(Broker.DEFAULT_VIRTUAL_HOST, TEST3_VIRTUALHOST);
+
+ int response = getRestTestHelper().submitRequest("/rest/broker", "PUT", brokerAttributes);
+ assertEquals("Anonymous access should be denied", 401, response);
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java
index e20db6a6ac..6f795cc61d 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java
@@ -207,14 +207,14 @@ public class Asserts
}
if (isAMQPPort)
{
- assertAttributesPresent(port, Port.AVAILABLE_ATTRIBUTES, Port.CREATED, Port.UPDATED, Port.AUTHENTICATION_PROVIDER);
+ assertAttributesPresent(port, Port.AVAILABLE_ATTRIBUTES, Port.CREATED, Port.UPDATED, Port.AUTHENTICATION_PROVIDER, Port.KEY_STORE, Port.TRUST_STORES);
assertNotNull("Unexpected value of attribute " + Port.BINDING_ADDRESS, port.get(Port.BINDING_ADDRESS));
}
else
{
assertAttributesPresent(port, Port.AVAILABLE_ATTRIBUTES, Port.CREATED, Port.UPDATED, Port.AUTHENTICATION_PROVIDER,
Port.BINDING_ADDRESS, Port.TCP_NO_DELAY, Port.SEND_BUFFER_SIZE, Port.RECEIVE_BUFFER_SIZE,
- Port.NEED_CLIENT_AUTH, Port.WANT_CLIENT_AUTH);
+ Port.NEED_CLIENT_AUTH, Port.WANT_CLIENT_AUTH, Port.KEY_STORE, Port.TRUST_STORES);
}
@SuppressWarnings("unchecked")
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java
index 0574b6cc24..ea63cc7f4e 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java
@@ -58,6 +58,8 @@ public class BasicAuthRestTest extends QpidRestTestCase
if (useSsl)
{
getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.PROTOCOLS, Collections.singleton(Protocol.HTTPS));
+ getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE);
+
}
super.customizeConfiguration();
}
@@ -68,7 +70,7 @@ public class BasicAuthRestTest extends QpidRestTestCase
assertEquals(responseCode, conn.getResponseCode());
}
- public void testDefaultEnabledWithHttps() throws Exception
+ public void testBasicAuthWhenEnabledWithHttps() throws Exception
{
configure(true);
super.setUp();
@@ -81,15 +83,16 @@ public class BasicAuthRestTest extends QpidRestTestCase
verifyGetBrokerAttempt(HttpServletResponse.SC_OK);
}
- public void testDefaultDisabledWithHttp() throws Exception
+ public void testBasicAuthWhenDisabledWithHttp() throws Exception
{
configure(false);
+ getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, "httpBasicAuthenticationEnabled", false);
super.setUp();
// Try the attempt with authentication, it should fail because
// BASIC auth is disabled by default on non-secure connections.
getRestTestHelper().setUsernameAndPassword(USERNAME, USERNAME);
- verifyGetBrokerAttempt(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ verifyGetBrokerAttempt(HttpServletResponse.SC_UNAUTHORIZED);
}
public void testEnablingForHttp() throws Exception
@@ -116,6 +119,6 @@ public class BasicAuthRestTest extends QpidRestTestCase
// Try the attempt with authentication, it should fail because
// BASIC auth is now disabled on secure connections.
getRestTestHelper().setUsernameAndPassword(USERNAME, USERNAME);
- verifyGetBrokerAttempt(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ verifyGetBrokerAttempt(HttpServletResponse.SC_UNAUTHORIZED);
}
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java
index 06927946ba..da38b9be33 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java
@@ -54,6 +54,7 @@ public class BrokerRestHttpsTest extends QpidRestTestCase
Map<String, Object> newAttributes = new HashMap<String, Object>();
newAttributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.HTTPS));
newAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
+ newAttributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE);
getBrokerConfiguration().setObjectAttributes(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT,newAttributes);
}
@@ -62,8 +63,6 @@ public class BrokerRestHttpsTest extends QpidRestTestCase
Map<String, Object> brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker");
Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES, Broker.BYTES_RETAINED,
- Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES, Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED,
- Broker.ACL_FILE, Broker.KEY_STORE_CERT_ALIAS, Broker.TRUST_STORE_PATH, Broker.TRUST_STORE_PASSWORD,
- Broker.GROUP_FILE, Broker.PEER_STORE_PATH, Broker.PEER_STORE_PASSWORD);
+ Broker.PROCESS_PID, Broker.SUPPORTED_VIRTUALHOST_STORE_TYPES, Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED);
}
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java
index a795063750..0d40eca745 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java
@@ -20,7 +20,6 @@
*/
package org.apache.qpid.systest.rest;
-import java.io.File;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
@@ -29,18 +28,18 @@ import java.util.List;
import java.util.Map;
import org.apache.qpid.common.QpidProperties;
+import org.apache.qpid.server.configuration.BrokerConfigurationStoreCreator;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.LifetimePolicy;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.store.MessageStoreCreator;
import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.test.utils.TestBrokerConfiguration;
-import org.apache.qpid.test.utils.TestSSLConstants;
public class BrokerRestTest extends QpidRestTestCase
{
-
private static final String BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE = "authenticationproviders";
private static final String BROKER_PORTS_ATTRIBUTE = "ports";
private static final String BROKER_VIRTUALHOSTS_ATTRIBUTE = "virtualhosts";
@@ -127,7 +126,6 @@ public class BrokerRestTest extends QpidRestTestCase
public void testPutToUpdateWithInvalidAttributeValues() throws Exception
{
Map<String, Object> invalidAttributes = new HashMap<String, Object>();
- invalidAttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "non-existing-provider");
invalidAttributes.put(Broker.DEFAULT_VIRTUAL_HOST, "non-existing-host");
invalidAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, -1000);
invalidAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, -2000);
@@ -141,15 +139,6 @@ public class BrokerRestTest extends QpidRestTestCase
invalidAttributes.put(Broker.CONNECTION_SESSION_COUNT_LIMIT, -10);
invalidAttributes.put(Broker.CONNECTION_HEART_BEAT_DELAY, -11000);
invalidAttributes.put(Broker.STATISTICS_REPORTING_PERIOD, -12000);
- invalidAttributes.put(Broker.ACL_FILE, QpidTestCase.QPID_HOME + File.separator + "etc" + File.separator + "non-existing-acl.acl");
- invalidAttributes.put(Broker.KEY_STORE_PATH, QpidTestCase.QPID_HOME + File.separator + "etc" + File.separator + "non-existing-keystore.jks");
- invalidAttributes.put(Broker.KEY_STORE_PASSWORD, "password1");
- invalidAttributes.put(Broker.KEY_STORE_CERT_ALIAS, "java-broker1");
- invalidAttributes.put(Broker.TRUST_STORE_PATH, QpidTestCase.QPID_HOME + File.separator + "etc" + File.separator + "non-existing-truststore.jks");
- invalidAttributes.put(Broker.TRUST_STORE_PASSWORD, "password2");
- invalidAttributes.put(Broker.PEER_STORE_PATH, QpidTestCase.QPID_HOME + File.separator + "etc" + File.separator + "non-existing-peerstore.jks");
- invalidAttributes.put(Broker.PEER_STORE_PASSWORD, "password3");
- invalidAttributes.put(Broker.GROUP_FILE, QpidTestCase.QPID_HOME + File.separator + "etc" + File.separator + "groups-non-existing");
invalidAttributes.put(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, -13000);
invalidAttributes.put(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN, -14000);
invalidAttributes.put(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, -15000);
@@ -174,7 +163,6 @@ public class BrokerRestTest extends QpidRestTestCase
private Map<String, Object> getValidBrokerAttributes()
{
Map<String, Object> brokerAttributes = new HashMap<String, Object>();
- brokerAttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, ANONYMOUS_AUTHENTICATION_PROVIDER);
brokerAttributes.put(Broker.DEFAULT_VIRTUAL_HOST, TEST3_VIRTUALHOST);
brokerAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, 1000);
brokerAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 2000);
@@ -190,15 +178,6 @@ public class BrokerRestTest extends QpidRestTestCase
brokerAttributes.put(Broker.CONNECTION_HEART_BEAT_DELAY, 11000);
brokerAttributes.put(Broker.STATISTICS_REPORTING_PERIOD, 12000);
brokerAttributes.put(Broker.STATISTICS_REPORTING_RESET_ENABLED, true);
- brokerAttributes.put(Broker.ACL_FILE, QpidTestCase.QPID_HOME + File.separator + "etc" + File.separator + "broker_example.acl");
- brokerAttributes.put(Broker.KEY_STORE_PATH, TestSSLConstants.BROKER_KEYSTORE);
- brokerAttributes.put(Broker.KEY_STORE_PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
- brokerAttributes.put(Broker.KEY_STORE_CERT_ALIAS, "java-broker");
- brokerAttributes.put(Broker.TRUST_STORE_PATH, TestSSLConstants.TRUSTSTORE);
- brokerAttributes.put(Broker.TRUST_STORE_PASSWORD, TestSSLConstants.TRUSTSTORE_PASSWORD);
- brokerAttributes.put(Broker.PEER_STORE_PATH, TestSSLConstants.TRUSTSTORE);
- brokerAttributes.put(Broker.PEER_STORE_PASSWORD, TestSSLConstants.TRUSTSTORE_PASSWORD);
- brokerAttributes.put(Broker.GROUP_FILE, QpidTestCase.QPID_HOME + File.separator + "etc" + File.separator + "groups");
brokerAttributes.put(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, 13000);
brokerAttributes.put(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN, 14000);
brokerAttributes.put(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, 15000);
@@ -212,10 +191,7 @@ public class BrokerRestTest extends QpidRestTestCase
{
String attributeName = entry.getKey();
Object attributeValue = entry.getValue();
- if (attributeName.equals(Broker.KEY_STORE_PASSWORD) || attributeName.equals(Broker.TRUST_STORE_PASSWORD) || attributeName.equals(Broker.PEER_STORE_PASSWORD))
- {
- attributeValue = "********";
- }
+
Object currentValue = actualAttributes.get(attributeName);
assertEquals("Unexpected attribute " + attributeName + " value:", attributeValue, currentValue);
}
@@ -224,11 +200,8 @@ public class BrokerRestTest extends QpidRestTestCase
protected void assertBrokerAttributes(Map<String, Object> brokerDetails)
{
Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES,
- Broker.BYTES_RETAINED, Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES,
- Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED, Broker.ACL_FILE,
- Broker.KEY_STORE_PATH, Broker.KEY_STORE_PASSWORD, Broker.KEY_STORE_CERT_ALIAS,
- Broker.TRUST_STORE_PATH, Broker.TRUST_STORE_PASSWORD, Broker.GROUP_FILE,
- Broker.PEER_STORE_PATH, Broker.PEER_STORE_PASSWORD);
+ Broker.BYTES_RETAINED, Broker.PROCESS_PID,
+ Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED);
assertEquals("Unexpected value of attribute " + Broker.BUILD_VERSION, QpidProperties.getBuildVersion(),
brokerDetails.get(Broker.BUILD_VERSION));
@@ -243,7 +216,7 @@ public class BrokerRestTest extends QpidRestTestCase
assertEquals("Unexpected value of attribute " + Broker.DURABLE, Boolean.TRUE, brokerDetails.get(Broker.DURABLE));
assertEquals("Unexpected value of attribute " + Broker.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
brokerDetails.get(Broker.LIFETIME_POLICY));
- assertEquals("Unexpected value of attribute " + Broker.NAME, "QpidBroker", brokerDetails.get(Broker.NAME));
+ assertEquals("Unexpected value of attribute " + Broker.NAME, "Broker", brokerDetails.get(Broker.NAME));
assertEquals("Unexpected value of attribute " + Broker.STATE, State.ACTIVE.name(), brokerDetails.get(Broker.STATE));
assertNotNull("Unexpected value of attribute " + Broker.ID, brokerDetails.get(Broker.ID));
@@ -251,6 +224,16 @@ public class BrokerRestTest extends QpidRestTestCase
assertNotNull("Unexpected value of attribute virtualhosts", brokerDetails.get(BROKER_VIRTUALHOSTS_ATTRIBUTE));
assertNotNull("Unexpected value of attribute ports", brokerDetails.get(BROKER_PORTS_ATTRIBUTE));
assertNotNull("Unexpected value of attribute authenticationproviders", brokerDetails.get(BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE));
+
+ @SuppressWarnings("unchecked")
+ Collection<String> supportedBrokerStoreTypes = (Collection<String>)brokerDetails.get(Broker.SUPPORTED_BROKER_STORE_TYPES);
+ Collection<String> expectedSupportedBrokerStoreTypes = new BrokerConfigurationStoreCreator().getStoreTypes();
+ assertEquals("Unexpected supported broker store types", new HashSet<String>(expectedSupportedBrokerStoreTypes), new HashSet<String>(supportedBrokerStoreTypes));
+
+ @SuppressWarnings("unchecked")
+ Collection<String> supportedVirtualHostStoreTypes = (Collection<String>)brokerDetails.get(Broker.SUPPORTED_VIRTUALHOST_STORE_TYPES);
+ Collection<String> expectedSupportedVirtualHostStoreTypes = new MessageStoreCreator().getStoreTypes();
+ assertEquals("Unexpected supported virtual host store types", new HashSet<String>(expectedSupportedVirtualHostStoreTypes), new HashSet<String>(supportedVirtualHostStoreTypes));
}
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java
index 861bf8cb71..ef8e12a929 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java
@@ -22,20 +22,23 @@ package org.apache.qpid.systest.rest;
import java.io.File;
import java.io.FileOutputStream;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
-import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.Group;
import org.apache.qpid.server.model.GroupProvider;
import org.apache.qpid.server.model.LifetimePolicy;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.security.group.FileGroupManagerFactory;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+import org.apache.qpid.test.utils.TestFileUtils;
public class GroupProviderRestTest extends QpidRestTestCase
{
- private static final String FILE_GROUP_MANAGER = "FileGroupManager";
+ private static final String FILE_GROUP_MANAGER = TestBrokerConfiguration.ENTRY_NAME_GROUP_FILE;
private File _groupFile;
@Override
@@ -43,7 +46,7 @@ public class GroupProviderRestTest extends QpidRestTestCase
{
_groupFile = createTemporaryGroupFile();
- getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath());
+ getBrokerConfiguration().addGroupFileConfiguration(_groupFile.getAbsolutePath());
super.setUp();
}
@@ -69,11 +72,11 @@ public class GroupProviderRestTest extends QpidRestTestCase
assertEquals("Unexpected number of providers", 1, providerDetails.size());
for (Map<String, Object> provider : providerDetails)
{
- assertProvider(FILE_GROUP_MANAGER, provider);
+ assertProvider(FILE_GROUP_MANAGER, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE, provider);
Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/"
+ provider.get(GroupProvider.NAME));
assertNotNull("Cannot load data for " + provider.get(GroupProvider.NAME), data);
- assertProvider(FILE_GROUP_MANAGER, data);
+ assertProvider(FILE_GROUP_MANAGER, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE, data);
}
}
@@ -111,8 +114,178 @@ public class GroupProviderRestTest extends QpidRestTestCase
getRestTestHelper().assertNumberOfGroups(data, 0);
}
+ public void testCreateNewFileGroupProviderFromExistingGroupFile() throws Exception
+ {
+ String[] groupMemberNames = {"test1","test2"};
+ File groupFile = TestFileUtils.createTempFile(this, ".groups", "testusers.users=" + groupMemberNames[0] + "," + groupMemberNames[1]);
+ try
+ {
+ String providerName = getTestName();
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(GroupProvider.NAME, providerName);
+ attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+ attributes.put(FileGroupManagerFactory.PATH, groupFile.getAbsolutePath());
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes);
+ assertEquals("Group provider was not created", 201, responseCode);
+
+ Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + providerName + "?depth=2");
+ assertProvider(providerName, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE, data);
+ assertEquals("Unexpected name", providerName, data.get(GroupProvider.NAME));
+ assertEquals("Unexpected path", groupFile.getAbsolutePath(), data.get(FileGroupManagerFactory.PATH));
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> groups = (List<Map<String, Object>>) data.get("groups");
+ assertEquals("Unexpected group size", 1, groups.size());
+ Map<String, Object> group = groups.get(0);
+ assertEquals("Unexpected group name", "testusers",group.get("name"));
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> groupMemberList = (List<Map<String, Object>>) group.get("groupmembers");
+ assertEquals("Unexpected group members size", 2, groupMemberList.size());
+
+ for (String memberName : groupMemberNames)
+ {
+ boolean found = false;
+ for (Map<String, Object> memberData : groupMemberList)
+ {
+ Object name = memberData.get("name");
+ if (memberName.equals(name))
+ {
+ found = true;
+ break;
+ }
+ }
+ assertTrue("Cannot find group member " + memberName + " in " + groupMemberList , found);
+ }
+ }
+ finally
+ {
+ groupFile.delete();
+ }
+ }
+
+ public void testCreationOfNewFileGroupProviderFailsWhenPathIsMissed() throws Exception
+ {
+ String providerName = getTestName();
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(GroupProvider.NAME, providerName);
+ attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes);
+ assertEquals("Group provider was created", 409, responseCode);
+ }
+
+ public void testCreateNewFileGroupProviderFromNonExistingGroupFile() throws Exception
+ {
+ File groupFile = new File(TMP_FOLDER + File.separator + getTestName() + File.separator + "groups");
+ assertFalse("Group file should not exist", groupFile.exists());
+ try
+ {
+ String providerName = getTestName();
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(GroupProvider.NAME, providerName);
+ attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+ attributes.put(FileGroupManagerFactory.PATH, groupFile.getAbsolutePath());
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes);
+ assertEquals("Group provider was not created", 201, responseCode);
+
+ Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + providerName);
+ assertEquals("Unexpected name", providerName, data.get(GroupProvider.NAME));
+ assertEquals("Unexpected path", groupFile.getAbsolutePath(), data.get(FileGroupManagerFactory.PATH));
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> groups = (List<Map<String, Object>>) data.get("groups");
+ assertNull("Unexpected groups", groups);
+
+ assertTrue("Group file has not been created", groupFile.exists());
+ }
+ finally
+ {
+ groupFile.delete();
+ groupFile.getParentFile().delete();
+ }
+ }
+
+ public void testCreateNewFileGroupProviderForTheSameGroupFileFails() throws Exception
+ {
+ File groupFile = TestFileUtils.createTempFile(this, ".groups", "testusers.users=test1,test2");
+ String providerName = getTestName();
+ try
+ {
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(GroupProvider.NAME, providerName);
+ attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+ attributes.put(FileGroupManagerFactory.PATH, groupFile.getAbsolutePath());
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes);
+ assertEquals("Group provider was not created", 201, responseCode);
+
+ attributes.put(GroupProvider.NAME, providerName + 2);
+ responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName + 2, "PUT", attributes);
+ assertEquals("Group provider for the same group file was created", 409, responseCode);
+ }
+ finally
+ {
+ groupFile.delete();
+ }
+ }
+
+ public void testDeleteGroupProvider() throws Exception
+ {
+ File groupFile = TestFileUtils.createTempFile(this, ".groups", "testusers.users=test1,test2");
+ String providerName = getTestName();
+ try
+ {
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(GroupProvider.NAME, providerName);
+ attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+ attributes.put(FileGroupManagerFactory.PATH, groupFile.getAbsolutePath());
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes);
+ assertEquals("Expected to fail because we can have only one password provider", 201, responseCode);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName , "DELETE", null);
+ assertEquals("Group provider was not deleted", 200, responseCode);
+
+ List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList("/rest/groupprovider/" + providerName);
+ assertEquals("Provider was not deleted", 0, providerDetails.size());
+ assertFalse("Groups file should be deleted", groupFile.exists());
+ }
+ finally
+ {
+ groupFile.delete();
+ }
+ }
+
+ public void testUpdateGroupProviderAttributesFails() throws Exception
+ {
+ File groupFile = TestFileUtils.createTempFile(this, ".groups", "testusers.users=test1,test2");
+ String providerName = getTestName();
+ try
+ {
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(GroupProvider.NAME, providerName);
+ attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+ attributes.put(FileGroupManagerFactory.PATH, groupFile.getAbsolutePath());
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes);
+ assertEquals("Expected to fail because we can have only one password provider", 201, responseCode);
+
+ File newGroupFile = new File(TMP_FOLDER + File.separator + getTestName() + File.separator + "groups");
+ attributes.put(FileGroupManagerFactory.PATH, newGroupFile.getAbsolutePath());
+
+ responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes);
+ assertEquals("Expected to fail because we can have only one password provider", 409, responseCode);
+ }
+ finally
+ {
+ groupFile.delete();
+ }
+ }
- private void assertProvider(String type, Map<String, Object> provider)
+ private void assertProvider(String name, String type, Map<String, Object> provider)
{
Asserts.assertAttributesPresent(provider, GroupProvider.AVAILABLE_ATTRIBUTES,
GroupProvider.CREATED, GroupProvider.UPDATED, GroupProvider.DESCRIPTION,
@@ -126,9 +299,8 @@ public class GroupProviderRestTest extends QpidRestTestCase
assertEquals("Unexpected value of provider attribute " + GroupProvider.TYPE, type,
provider.get(GroupProvider.TYPE));
- final String name = (String) provider.get(GroupProvider.NAME);
- assertEquals("Unexpected value of provider attribute " + GroupProvider.NAME, type,
- name);
+ assertEquals("Unexpected value of provider attribute " + GroupProvider.NAME, name,
+ (String) provider.get(GroupProvider.NAME));
@SuppressWarnings("unchecked")
List<Map<String, Object>> groups = (List<Map<String, Object>>) provider.get("groups");
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java
index d3f93cc0fe..67e50b1bd1 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java
@@ -26,13 +26,13 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
-import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.GroupMember;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
public class GroupRestTest extends QpidRestTestCase
{
private static final String GROUP_NAME = "myGroup";
- private static final String FILE_GROUP_MANAGER = "FileGroupManager";
+ private static final String FILE_GROUP_MANAGER = TestBrokerConfiguration.ENTRY_NAME_GROUP_FILE;
private static final String EXISTING_MEMBER = "user1";
private static final String NEW_MEMBER = "user2";
@@ -43,7 +43,7 @@ public class GroupRestTest extends QpidRestTestCase
{
_groupFile = createTemporaryGroupFile();
- getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath());
+ getBrokerConfiguration().addGroupFileConfiguration(_groupFile.getAbsolutePath());
super.setUp();
}
@@ -64,7 +64,7 @@ public class GroupRestTest extends QpidRestTestCase
public void testGet() throws Exception
{
- Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup");
+ Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/" + FILE_GROUP_MANAGER + "/myGroup");
List<Map<String, Object>> groupmembers = (List<Map<String, Object>>) group.get("groupmembers");
assertEquals(1, groupmembers.size());
@@ -74,23 +74,23 @@ public class GroupRestTest extends QpidRestTestCase
public void testCreateNewMemberOfGroup() throws Exception
{
- Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup");
+ Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/" + FILE_GROUP_MANAGER + "/myGroup");
getRestTestHelper().assertNumberOfGroupMembers(group, 1);
getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, GROUP_NAME, NEW_MEMBER);
- group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup");
+ group = getRestTestHelper().getJsonAsSingletonList("/rest/group/" + FILE_GROUP_MANAGER + "/myGroup");
getRestTestHelper().assertNumberOfGroupMembers(group, 2);
}
public void testRemoveMemberFromGroup() throws Exception
{
- Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup");
+ Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/" + FILE_GROUP_MANAGER + "/myGroup");
getRestTestHelper().assertNumberOfGroupMembers(group, 1);
getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, GROUP_NAME, EXISTING_MEMBER);
- group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup");
+ group = getRestTestHelper().getJsonAsSingletonList("/rest/group/" + FILE_GROUP_MANAGER + "/myGroup");
getRestTestHelper().assertNumberOfGroupMembers(group, 0);
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java
new file mode 100644
index 0000000000..c38d9bb396
--- /dev/null
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java
@@ -0,0 +1,270 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.KeyStore;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.server.model.adapter.AbstractKeyStoreAdapter;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+import org.apache.qpid.test.utils.TestSSLConstants;
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+
+public class KeyStoreRestTest extends QpidRestTestCase
+{
+ @Override
+ public void setUp() throws Exception
+ {
+ // not calling super.setUp() to avoid broker start-up until
+ // after any necessary configuration
+ }
+
+ public void testGet() throws Exception
+ {
+ super.setUp();
+
+ //verify existence of the default keystore used by the systests
+ List<Map<String, Object>> keyStores = assertNumberOfKeyStores(1);
+
+ Map<String, Object> keystore = keyStores.get(0);
+ assertKeyStoreAttributes(keystore, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE,
+ System.getProperty(QPID_HOME) + "/../" + TestSSLConstants.BROKER_KEYSTORE, null);
+ }
+
+ public void testCreate() throws Exception
+ {
+ super.setUp();
+
+ String name = getTestName();
+ String certAlias = "app2";
+
+ assertNumberOfKeyStores(1);
+ createKeyStore(name, certAlias);
+ assertNumberOfKeyStores(2);
+
+ List<Map<String, Object>> keyStores = getRestTestHelper().getJsonAsList("/rest/keystore/" + name);
+ assertNotNull("details cannot be null", keyStores);
+
+ assertKeyStoreAttributes(keyStores.get(0), name, TestSSLConstants.KEYSTORE, certAlias);
+ }
+
+ public void testDelete() throws Exception
+ {
+ super.setUp();
+
+ String name = getTestName();
+ String certAlias = "app2";
+
+ assertNumberOfKeyStores(1);
+ createKeyStore(name, certAlias);
+ assertNumberOfKeyStores(2);
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/keystore/" + name , "DELETE", null);
+ assertEquals("Unexpected response code for provider deletion", 200, responseCode);
+
+ List<Map<String, Object>> keyStore = getRestTestHelper().getJsonAsList("/rest/keystore/" + name);
+ assertNotNull("details should not be null", keyStore);
+ assertTrue("details should be empty as the keystore no longer exists", keyStore.isEmpty());
+
+ //check only the default systests key store remains
+ List<Map<String, Object>> keyStores = assertNumberOfKeyStores(1);
+ Map<String, Object> keystore = keyStores.get(0);
+ assertKeyStoreAttributes(keystore, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE,
+ System.getProperty(QPID_HOME) + "/../" + TestSSLConstants.BROKER_KEYSTORE, null);
+ }
+
+ public void testDeleteFailsWhenKeyStoreInUse() throws Exception
+ {
+ String name = "testDeleteFailsWhenKeyStoreInUse";
+
+ //add a new key store config to use
+ Map<String, Object> sslKeyStoreAttributes = new HashMap<String, Object>();
+ sslKeyStoreAttributes.put(KeyStore.NAME, name);
+ sslKeyStoreAttributes.put(KeyStore.PATH, TestSSLConstants.BROKER_KEYSTORE);
+ sslKeyStoreAttributes.put(KeyStore.PASSWORD, TestSSLConstants.BROKER_KEYSTORE_PASSWORD);
+ getBrokerConfiguration().addKeyStoreConfiguration(sslKeyStoreAttributes);
+
+ //add the SSL port using it
+ Map<String, Object> sslPortAttributes = new HashMap<String, Object>();
+ sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
+ sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT);
+ sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT);
+ sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
+ sslPortAttributes.put(Port.KEY_STORE, name);
+ getBrokerConfiguration().addPortConfiguration(sslPortAttributes);
+
+ super.setUp();
+
+ //verify the keystore is there
+ assertNumberOfKeyStores(2);
+
+ List<Map<String, Object>> keyStore = getRestTestHelper().getJsonAsList("/rest/keystore/" + name);
+ assertNotNull("details should not be null", keyStore);
+ assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.BROKER_KEYSTORE, null);
+
+ //try to delete it, which should fail as it is in use
+ int responseCode = getRestTestHelper().submitRequest("/rest/keystore/" + name , "DELETE", null);
+ assertEquals("Unexpected response code for provider deletion", 409, responseCode);
+
+ //check its still there
+ assertNumberOfKeyStores(2);
+ keyStore = getRestTestHelper().getJsonAsList("/rest/keystore/" + name);
+ assertNotNull("details should not be null", keyStore);
+ assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.BROKER_KEYSTORE, null);
+ }
+
+ public void testUpdateWithGoodPathSucceeds() throws Exception
+ {
+ super.setUp();
+
+ String name = getTestName();
+
+ assertNumberOfKeyStores(1);
+ createKeyStore(name, null);
+ assertNumberOfKeyStores(2);
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(KeyStore.NAME, name);
+ attributes.put(KeyStore.PATH, TestSSLConstants.UNTRUSTED_KEYSTORE);
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/keystore/" + name , "PUT", attributes);
+ assertEquals("Unexpected response code for keystore update", 200, responseCode);
+
+ List<Map<String, Object>> keyStore = getRestTestHelper().getJsonAsList("/rest/keystore/" + name);
+ assertNotNull("details should not be null", keyStore);
+
+ assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.UNTRUSTED_KEYSTORE, null);
+ }
+
+ public void testUpdateWithNonExistentPathFails() throws Exception
+ {
+ super.setUp();
+
+ String name = getTestName();
+
+ assertNumberOfKeyStores(1);
+ createKeyStore(name, null);
+ assertNumberOfKeyStores(2);
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(KeyStore.NAME, name);
+ attributes.put(KeyStore.PATH, "does.not.exist");
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/keystore/" + name , "PUT", attributes);
+ assertEquals("Unexpected response code for keystore update", 409, responseCode);
+
+ List<Map<String, Object>> keyStore = getRestTestHelper().getJsonAsList("/rest/keystore/" + name);
+ assertNotNull("details should not be null", keyStore);
+
+ //verify the details remain unchanged
+ assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.KEYSTORE, null);
+ }
+
+ public void testUpdateCertificateAlias() throws Exception
+ {
+ super.setUp();
+
+ String name = getTestName();
+
+ assertNumberOfKeyStores(1);
+ createKeyStore(name, "app1");
+ assertNumberOfKeyStores(2);
+
+ List<Map<String, Object>> keyStore = getRestTestHelper().getJsonAsList("/rest/keystore/" + name);
+ assertNotNull("details should not be null", keyStore);
+ assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.KEYSTORE, "app1");
+
+ //Update the certAlias from app1 to app2
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(KeyStore.NAME, name);
+ attributes.put(KeyStore.CERTIFICATE_ALIAS, "app2");
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/keystore/" + name , "PUT", attributes);
+ assertEquals("Unexpected response code for keystore update", 200, responseCode);
+
+ keyStore = getRestTestHelper().getJsonAsList("/rest/keystore/" + name);
+ assertNotNull("details should not be null", keyStore);
+
+ assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.KEYSTORE, "app2");
+
+ //Update the certAlias to clear it (i.e go from from app1 to null)
+ attributes = new HashMap<String, Object>();
+ attributes.put(KeyStore.NAME, name);
+ attributes.put(KeyStore.CERTIFICATE_ALIAS, null);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/keystore/" + name , "PUT", attributes);
+ assertEquals("Unexpected response code for keystore update", 200, responseCode);
+
+ keyStore = getRestTestHelper().getJsonAsList("/rest/keystore/" + name);
+ assertNotNull("details should not be null", keyStore);
+
+ assertKeyStoreAttributes(keyStore.get(0), name, TestSSLConstants.KEYSTORE, null);
+ }
+
+ private List<Map<String, Object>> assertNumberOfKeyStores(int numberOfKeystores) throws IOException,
+ JsonParseException, JsonMappingException
+ {
+ List<Map<String, Object>> keyStores = getRestTestHelper().getJsonAsList("/rest/keystore");
+ assertNotNull("keystores should not be null", keyStores);
+ assertEquals("Unexpected number of keystores", numberOfKeystores, keyStores.size());
+
+ return keyStores;
+ }
+
+ private void createKeyStore(String name, String certAlias) throws IOException, JsonGenerationException, JsonMappingException
+ {
+ Map<String, Object> keyStoreAttributes = new HashMap<String, Object>();
+ keyStoreAttributes.put(KeyStore.NAME, name);
+ keyStoreAttributes.put(KeyStore.PATH, TestSSLConstants.KEYSTORE);
+ keyStoreAttributes.put(KeyStore.PASSWORD, TestSSLConstants.KEYSTORE_PASSWORD);
+ keyStoreAttributes.put(KeyStore.CERTIFICATE_ALIAS, certAlias);
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/keystore/" + name, "PUT", keyStoreAttributes);
+ assertEquals("Unexpected response code", 201, responseCode);
+ }
+
+ private void assertKeyStoreAttributes(Map<String, Object> keystore, String name, String path, String certAlias)
+ {
+ assertEquals("default systests key store is missing",
+ name, keystore.get(KeyStore.NAME));
+ assertEquals("unexpected path to key store",
+ path, keystore.get(KeyStore.PATH));
+ assertEquals("unexpected (dummy) password of default systests key store",
+ AbstractKeyStoreAdapter.DUMMY_PASSWORD_MASK, keystore.get(KeyStore.PASSWORD));
+ assertEquals("unexpected type of default systests key store",
+ java.security.KeyStore.getDefaultType(), keystore.get(KeyStore.TYPE));
+ assertEquals("unexpected certificateAlias value",
+ certAlias, keystore.get(KeyStore.CERTIFICATE_ALIAS));
+ if(certAlias == null)
+ {
+ assertFalse("should not be a certificateAlias attribute",
+ keystore.containsKey(KeyStore.CERTIFICATE_ALIAS));
+ }
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java
index 1497d740dc..be4dea6e81 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java
@@ -30,7 +30,6 @@ import java.util.List;
import java.util.Map;
import org.apache.qpid.server.model.AuthenticationProvider;
-import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Protocol;
import org.apache.qpid.server.model.State;
@@ -79,6 +78,7 @@ public class PortRestTest extends QpidRestTestCase
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(Port.NAME, portName);
attributes.put(Port.PORT, findFreePort());
+ attributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
int responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
assertEquals("Unexpected response code", 201, responseCode);
@@ -139,6 +139,7 @@ public class PortRestTest extends QpidRestTestCase
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(Port.NAME, portName);
attributes.put(Port.PORT, findFreePort());
+ attributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
int responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
assertEquals("Unexpected response code for port creation", 201, responseCode);
@@ -162,25 +163,6 @@ public class PortRestTest extends QpidRestTestCase
responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
assertEquals("Port cannot be updated in non management mode", 409, responseCode);
-
- restartBrokerInManagementMode();
-
- responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
- assertEquals("Port should be allwed to update in a management mode", 200, responseCode);
-
- portDetails = getRestTestHelper().getJsonAsList("/rest/port/" + portName);
- assertNotNull("Port details cannot be null", portDetails);
- assertEquals("Unexpected number of ports with name " + portName, 1, portDetails.size());
- port = portDetails.get(0);
-
- assertEquals("Unexpected authentication provider", TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER, port.get(Port.AUTHENTICATION_PROVIDER));
- Object protocols = port.get(Port.PROTOCOLS);
- assertNotNull("Protocols attribute is not found", protocols);
- assertTrue("Protocol attribute value is not collection:" + protocols, protocols instanceof Collection);
- @SuppressWarnings("unchecked")
- Collection<String> protocolsCollection = ((Collection<String>)protocols);
- assertEquals("Unexpected protocols size", 1, protocolsCollection.size());
- assertEquals("Unexpected protocols", Protocol.AMQP_0_9_1.name(), protocolsCollection.iterator().next());
}
public void testPutUpdateOpenedAmqpPortFails() throws Exception
@@ -200,16 +182,19 @@ public class PortRestTest extends QpidRestTestCase
public void testUpdatePortTransportFromTCPToSSLWhenKeystoreIsConfigured() throws Exception
{
restartBrokerInManagementMode();
+ getRestTestHelper().setManagementModeCredentials();
String portName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT;
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(Port.NAME, portName);
attributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
+ attributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE);
int responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
assertEquals("Transport has not been changed to SSL " , 200, responseCode);
restartBroker();
+ getRestTestHelper().setUsernameAndPassword("webadmin", "webadmin");
Map<String, Object> port = getRestTestHelper().getJsonAsSingletonList("/rest/port/" + portName);
@@ -217,13 +202,15 @@ public class PortRestTest extends QpidRestTestCase
Collection<String> transports = (Collection<String>) port.get(Port.TRANSPORTS);
assertEquals("Unexpected auth provider", new HashSet<String>(Arrays.asList(Transport.SSL.name())),
new HashSet<String>(transports));
+
+ String keyStore = (String) port.get(Port.KEY_STORE);
+ assertEquals("Unexpected auth provider", TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE, keyStore);
}
public void testUpdateTransportFromTCPToSSLWithoutKeystoreConfiguredFails() throws Exception
{
- getBrokerConfiguration().setBrokerAttribute(Broker.KEY_STORE_PATH, null);
- getBrokerConfiguration().setSaved(false);
restartBrokerInManagementMode();
+ getRestTestHelper().setManagementModeCredentials();
String portName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT;
Map<String, Object> attributes = new HashMap<String, Object>();
@@ -240,12 +227,16 @@ public class PortRestTest extends QpidRestTestCase
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(Port.NAME, portName);
attributes.put(Port.PORT, DEFAULT_SSL_PORT);
+ attributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
attributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
+ attributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE);
+ attributes.put(Port.TRUST_STORES, Collections.singleton(TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE));
int responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
assertEquals("SSL port was not added", 201, responseCode);
restartBrokerInManagementMode();
+ getRestTestHelper().setManagementModeCredentials();
attributes.put(Port.NEED_CLIENT_AUTH, true);
attributes.put(Port.WANT_CLIENT_AUTH, true);
@@ -254,18 +245,25 @@ public class PortRestTest extends QpidRestTestCase
assertEquals("Attributes for need/want client auth are not set", 200, responseCode);
restartBroker();
+ getRestTestHelper().setUsernameAndPassword("webadmin", "webadmin");
Map<String, Object> port = getRestTestHelper().getJsonAsSingletonList("/rest/port/" + portName);
assertEquals("Unexpected " + Port.NEED_CLIENT_AUTH, true, port.get(Port.NEED_CLIENT_AUTH));
assertEquals("Unexpected " + Port.WANT_CLIENT_AUTH, true, port.get(Port.WANT_CLIENT_AUTH));
+ assertEquals("Unexpected " + Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE, port.get(Port.KEY_STORE));
+ @SuppressWarnings("unchecked")
+ Collection<String> trustStores = (Collection<String>) port.get(Port.TRUST_STORES);
+ assertEquals("Unexpected auth provider", new HashSet<String>(Arrays.asList(TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE)),
+ new HashSet<String>(trustStores));
restartBrokerInManagementMode();
+ getRestTestHelper().setManagementModeCredentials();
attributes = new HashMap<String, Object>();
attributes.put(Port.NAME, portName);
attributes.put(Port.TRANSPORTS, Collections.singleton(Transport.TCP));
responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
- assertEquals("Should not be able to change transport to SSL without reseting of attributes for need/want client auth", 409, responseCode);
+ assertEquals("Should not be able to change transport to TCP without reseting of attributes for need/want client auth", 409, responseCode);
attributes = new HashMap<String, Object>();
attributes.put(Port.NAME, portName);
@@ -277,6 +275,7 @@ public class PortRestTest extends QpidRestTestCase
assertEquals("Should be able to change transport to TCP ", 200, responseCode);
restartBroker();
+ getRestTestHelper().setUsernameAndPassword("webadmin", "webadmin");
port = getRestTestHelper().getJsonAsSingletonList("/rest/port/" + portName);
assertEquals("Unexpected " + Port.NEED_CLIENT_AUTH, false, port.get(Port.NEED_CLIENT_AUTH));
assertEquals("Unexpected " + Port.WANT_CLIENT_AUTH, false, port.get(Port.WANT_CLIENT_AUTH));
@@ -290,6 +289,7 @@ public class PortRestTest extends QpidRestTestCase
public void testUpdateSettingWantNeedCertificateFailsForNonSSLPort() throws Exception
{
restartBrokerInManagementMode();
+ getRestTestHelper().setManagementModeCredentials();
String portName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT;
Map<String, Object> attributes = new HashMap<String, Object>();
@@ -308,6 +308,7 @@ public class PortRestTest extends QpidRestTestCase
public void testUpdatePortAuthenticationProvider() throws Exception
{
restartBrokerInManagementMode();
+ getRestTestHelper().setManagementModeCredentials();
String portName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT;
Map<String, Object> attributes = new HashMap<String, Object>();
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java
index f83eb391e7..e5aacbba4b 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java
@@ -27,9 +27,7 @@ import java.util.Map;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Port;
-import org.apache.qpid.server.plugin.AuthenticationManagerFactory;
import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory;
-import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManagerFactory;
import org.apache.qpid.test.utils.TestBrokerConfiguration;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
@@ -49,10 +47,17 @@ public class QpidRestTestCase extends QpidBrokerTestCase
@Override
public void setUp() throws Exception
{
+ // use webadmin account to perform tests
+ getRestTestHelper().setUsernameAndPassword("webadmin", "webadmin");
+
+ //remove the normal 'test' vhost, we will configure the vhosts below
+ getBrokerConfiguration(0).removeObjectConfiguration(TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST);
+
// Set up virtualhost config with queues and bindings to the amq.direct
for (String virtualhost : EXPECTED_VIRTUALHOSTS)
{
createTestVirtualHost(0, virtualhost);
+
for (String queue : EXPECTED_QUEUES)
{
setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".queues.exchange", "amq.direct");
@@ -89,6 +94,11 @@ public class QpidRestTestCase extends QpidBrokerTestCase
anonymousProviderAttributes.put(AuthenticationProvider.TYPE, AnonymousAuthenticationManagerFactory.PROVIDER_TYPE);
anonymousProviderAttributes.put(AuthenticationProvider.NAME, ANONYMOUS_AUTHENTICATION_PROVIDER);
config.addAuthenticationProviderConfiguration(anonymousProviderAttributes);
+
+ // set password authentication provider on http port for the tests
+ config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.AUTHENTICATION_PROVIDER,
+ TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
+ config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, "httpBasicAuthenticationEnabled", true);
}
public RestTestHelper getRestTestHelper()
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java
index 9628423a00..c15e5d7285 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java
@@ -51,6 +51,7 @@ import junit.framework.Assert;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.security.auth.manager.AbstractPrincipalDatabaseAuthManagerFactory;
import org.apache.qpid.ssl.SSLContextFactory;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
@@ -400,6 +401,11 @@ public class RestTestHelper
_password = password;
}
+ public void setManagementModeCredentials()
+ {
+ setUsernameAndPassword(BrokerOptions.MANAGEMENT_MODE_USER_NAME, QpidBrokerTestCase.MANAGEMENT_MODE_PASSWORD);
+ }
+
/**
* Create password file that follows the convention username=password, which is deleted by {@link #tearDown()}
*/
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java
index 856fda9419..1c05f17e25 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java
@@ -20,20 +20,20 @@
*/
package org.apache.qpid.systest.rest;
+import static org.apache.qpid.server.security.auth.sasl.SaslUtil.generateCramMD5ClientResponse;
+import static org.apache.qpid.server.security.auth.sasl.SaslUtil.generateCramMD5HexClientResponse;
+import static org.apache.qpid.server.security.auth.sasl.SaslUtil.generatePlainClientResponse;
+
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
-import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import javax.crypto.Mac;
-import javax.crypto.spec.SecretKeySpec;
-
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.qpid.server.plugin.AuthenticationManagerFactory;
@@ -131,7 +131,7 @@ public class SaslRestTest extends QpidRestTestCase
os.flush();
int code = connection.getResponseCode();
- assertEquals("Unexpected response code", 403, code);
+ assertEquals("Unexpected response code", 401, code);
List<String> cookies = connection.getHeaderFields().get("Set-Cookie");
@@ -156,7 +156,7 @@ public class SaslRestTest extends QpidRestTestCase
os.flush();
int code = connection.getResponseCode();
- assertEquals("Unexpected response code", 403, code);
+ assertEquals("Unexpected response code", 401, code);
List<String> cookies = connection.getHeaderFields().get("Set-Cookie");
@@ -196,7 +196,7 @@ public class SaslRestTest extends QpidRestTestCase
// authenticate user with correct credentials
int code = authenticateUser(connection, "admin", "incorrect", "CRAM-MD5");
- assertEquals("Unexpected response code", 403, code);
+ assertEquals("Unexpected response code", 401, code);
// request authenticated user details
connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET");
@@ -215,7 +215,7 @@ public class SaslRestTest extends QpidRestTestCase
// authenticate user with correct credentials
int code = authenticateUser(connection, "nonexisting", "admin", "CRAM-MD5");
- assertEquals("Unexpected response code", 403, code);
+ assertEquals("Unexpected response code", 401, code);
// request authenticated user details
connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET");
@@ -254,7 +254,7 @@ public class SaslRestTest extends QpidRestTestCase
// try to authenticate user with incorrect passowrd
int code = authenticateUser(connection, "admin", "incorrect", "CRAM-MD5-HEX");
- assertEquals("Unexpected response code", 403, code);
+ assertEquals("Unexpected response code", 401, code);
// request authenticated user details
connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET");
@@ -273,7 +273,7 @@ public class SaslRestTest extends QpidRestTestCase
// try to authenticate non-existing user
int code = authenticateUser(connection, "nonexisting", "admin", "CRAM-MD5-HEX");
- assertEquals("Unexpected response code", 403, code);
+ assertEquals("Unexpected response code", 401, code);
// request authenticated user details
connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET");
@@ -345,59 +345,6 @@ public class SaslRestTest extends QpidRestTestCase
}
}
- private static byte SEPARATOR = 0;
-
- private byte[] generatePlainClientResponse(String userName, String userPassword) throws Exception
- {
- byte[] password = userPassword.getBytes("UTF8");
- byte user[] = userName.getBytes("UTF8");
- byte response[] = new byte[password.length + user.length + 2 ];
- int size = 0;
- response[size++] = SEPARATOR;
- System.arraycopy(user, 0, response, size, user.length);
- size += user.length;
- response[size++] = SEPARATOR;
- System.arraycopy(password, 0, response, size, password.length);
- return response;
- }
-
- private byte[] generateCramMD5HexClientResponse(String userName, String userPassword, byte[] challengeBytes) throws Exception
- {
- String macAlgorithm = "HmacMD5";
- byte[] digestedPasswordBytes = MessageDigest.getInstance("MD5").digest(userPassword.getBytes("UTF-8"));
- byte[] hexEncodedDigestedPasswordBytes = toHex(digestedPasswordBytes).getBytes("UTF-8");
- Mac mac = Mac.getInstance(macAlgorithm);
- mac.init(new SecretKeySpec(hexEncodedDigestedPasswordBytes, macAlgorithm));
- final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes);
- String responseAsString = userName + " " + toHex(messageAuthenticationCode);
- return responseAsString.getBytes();
- }
-
- private byte[] generateCramMD5ClientResponse(String userName, String userPassword, byte[] challengeBytes) throws Exception
- {
- String macAlgorithm = "HmacMD5";
- Mac mac = Mac.getInstance(macAlgorithm);
- mac.init(new SecretKeySpec(userPassword.getBytes("UTF-8"), macAlgorithm));
- final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes);
- String responseAsString = userName + " " + toHex(messageAuthenticationCode);
- return responseAsString.getBytes();
- }
-
- private String toHex(byte[] data)
- {
- StringBuffer hash = new StringBuffer();
- for (int i = 0; i < data.length; i++)
- {
- String hex = Integer.toHexString(0xFF & data[i]);
- if (hex.length() == 1)
- {
- hash.append('0');
- }
- hash.append(hex);
- }
- return hash.toString();
- }
-
private void configureBase64MD5FilePrincipalDatabase() throws IOException, ConfigurationException
{
// generate user password entry
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java
index 5593ad0b42..cb4fd1ad5b 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java
@@ -33,7 +33,7 @@ public class StructureRestTest extends QpidRestTestCase
{
Map<String, Object> structure = getRestTestHelper().getJsonAsMap("/rest/structure");
assertNotNull("Structure data cannot be null", structure);
- assertNode(structure, "QpidBroker");
+ assertNode(structure, "Broker");
@SuppressWarnings("unchecked")
List<Map<String, Object>> virtualhosts = (List<Map<String, Object>>) structure.get("virtualhosts");
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java
new file mode 100644
index 0000000000..8b788780d6
--- /dev/null
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java
@@ -0,0 +1,262 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.KeyStore;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.server.model.TrustStore;
+import org.apache.qpid.server.model.adapter.AbstractKeyStoreAdapter;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+import org.apache.qpid.test.utils.TestSSLConstants;
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+
+public class TrustStoreRestTest extends QpidRestTestCase
+{
+ @Override
+ public void setUp() throws Exception
+ {
+ // not calling super.setUp() to avoid broker start-up until
+ // after any necessary configuration
+ }
+
+ public void testGet() throws Exception
+ {
+ super.setUp();
+
+ //verify existence of the default trust store used by the systests
+ List<Map<String, Object>> trustStores = assertNumberOfTrustStores(1);
+
+ Map<String, Object> truststore = trustStores.get(0);
+ assertTrustStoreAttributes(truststore, TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE,
+ System.getProperty(QPID_HOME) + "/../" + TestSSLConstants.BROKER_TRUSTSTORE, false);
+ }
+
+ public void testCreate() throws Exception
+ {
+ super.setUp();
+
+ String name = getTestName();
+
+ assertNumberOfTrustStores(1);
+ createTrustStore(name, true);
+ assertNumberOfTrustStores(2);
+
+ List<Map<String, Object>> trustStores = getRestTestHelper().getJsonAsList("/rest/truststore/" + name);
+ assertNotNull("details cannot be null", trustStores);
+
+ assertTrustStoreAttributes(trustStores.get(0), name, TestSSLConstants.TRUSTSTORE, true);
+ }
+
+ public void testDelete() throws Exception
+ {
+ super.setUp();
+
+ String name = getTestName();
+
+ assertNumberOfTrustStores(1);
+ createTrustStore(name, false);
+ assertNumberOfTrustStores(2);
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/truststore/" + name , "DELETE", null);
+ assertEquals("Unexpected response code for provider deletion", 200, responseCode);
+
+ List<Map<String, Object>> trustStore = getRestTestHelper().getJsonAsList("/rest/truststore/" + name);
+ assertNotNull("details should not be null", trustStore);
+ assertTrue("details should be empty as the truststore no longer exists", trustStore.isEmpty());
+
+ //check only the default systests trust store remains
+ List<Map<String, Object>> trustStores = assertNumberOfTrustStores(1);
+ Map<String, Object> truststore = trustStores.get(0);
+ assertTrustStoreAttributes(truststore, TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE,
+ System.getProperty(QPID_HOME) + "/../" + TestSSLConstants.BROKER_TRUSTSTORE, false);
+ }
+
+ public void testDeleteFailsWhenTrustStoreInUse() throws Exception
+ {
+ String name = "testDeleteFailsWhenTrustStoreInUse";
+
+ //add a new trust store config to use
+ Map<String, Object> sslTrustStoreAttributes = new HashMap<String, Object>();
+ sslTrustStoreAttributes.put(TrustStore.NAME, name);
+ sslTrustStoreAttributes.put(TrustStore.PATH, TestSSLConstants.TRUSTSTORE);
+ sslTrustStoreAttributes.put(TrustStore.PASSWORD, TestSSLConstants.TRUSTSTORE_PASSWORD);
+ getBrokerConfiguration().addTrustStoreConfiguration(sslTrustStoreAttributes);
+
+ //add the SSL port using it
+ Map<String, Object> sslPortAttributes = new HashMap<String, Object>();
+ sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
+ sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT);
+ sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT);
+ sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
+ sslPortAttributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE);
+ sslPortAttributes.put(Port.TRUST_STORES, Collections.singleton(name));
+ getBrokerConfiguration().addPortConfiguration(sslPortAttributes);
+
+ super.setUp();
+
+ //verify the truststore is there
+ assertNumberOfTrustStores(2);
+
+ List<Map<String, Object>> trustStore = getRestTestHelper().getJsonAsList("/rest/truststore/" + name);
+ assertNotNull("details should not be null", trustStore);
+ assertTrustStoreAttributes(trustStore.get(0), name, TestSSLConstants.TRUSTSTORE, false);
+
+ //try to delete it, which should fail as it is in use
+ int responseCode = getRestTestHelper().submitRequest("/rest/truststore/" + name , "DELETE", null);
+ assertEquals("Unexpected response code for provider deletion", 409, responseCode);
+
+ //check its still there
+ assertNumberOfTrustStores(2);
+ trustStore = getRestTestHelper().getJsonAsList("/rest/truststore/" + name);
+ assertNotNull("details should not be null", trustStore);
+ assertTrustStoreAttributes(trustStore.get(0), name, TestSSLConstants.TRUSTSTORE, false);
+ }
+
+ public void testUpdateWithGoodPathSucceeds() throws Exception
+ {
+ super.setUp();
+
+ String name = getTestName();
+
+ assertNumberOfTrustStores(1);
+ createTrustStore(name, false);
+ assertNumberOfTrustStores(2);
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(TrustStore.NAME, name);
+ attributes.put(TrustStore.PATH, TestSSLConstants.TRUSTSTORE);
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/truststore/" + name , "PUT", attributes);
+ assertEquals("Unexpected response code for truststore update", 200, responseCode);
+
+ List<Map<String, Object>> trustStore = getRestTestHelper().getJsonAsList("/rest/truststore/" + name);
+ assertNotNull("details should not be null", trustStore);
+
+ assertTrustStoreAttributes(trustStore.get(0), name, TestSSLConstants.TRUSTSTORE, false);
+ }
+
+ public void testUpdateWithNonExistentPathFails() throws Exception
+ {
+ super.setUp();
+
+ String name = getTestName();
+
+ assertNumberOfTrustStores(1);
+ createTrustStore(name, false);
+ assertNumberOfTrustStores(2);
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(TrustStore.NAME, name);
+ attributes.put(TrustStore.PATH, "does.not.exist");
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/truststore/" + name , "PUT", attributes);
+ assertEquals("Unexpected response code for trust store update", 409, responseCode);
+
+ List<Map<String, Object>> trustStore = getRestTestHelper().getJsonAsList("/rest/truststore/" + name);
+ assertNotNull("details should not be null", trustStore);
+
+ //verify the details remain unchanged
+ assertTrustStoreAttributes(trustStore.get(0), name, TestSSLConstants.TRUSTSTORE, false);
+ }
+
+ public void testUpdatePeersOnly() throws Exception
+ {
+ super.setUp();
+
+ String name = getTestName();
+
+ assertNumberOfTrustStores(1);
+ createTrustStore(name, false);
+ assertNumberOfTrustStores(2);
+
+ //update the peersOnly attribute from false to true
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(TrustStore.NAME, name);
+ attributes.put(TrustStore.PEERS_ONLY, true);
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/truststore/" + name , "PUT", attributes);
+ assertEquals("Unexpected response code for trust store update", 200, responseCode);
+
+ List<Map<String, Object>> trustStore = getRestTestHelper().getJsonAsList("/rest/truststore/" + name);
+ assertNotNull("details should not be null", trustStore);
+
+ assertTrustStoreAttributes(trustStore.get(0), name, TestSSLConstants.TRUSTSTORE, true);
+
+ //Update peersOnly to clear it (i.e go from from true to null, which will default to false)
+ attributes = new HashMap<String, Object>();
+ attributes.put(TrustStore.NAME, name);
+ attributes.put(TrustStore.PEERS_ONLY, null);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/truststore/" + name , "PUT", attributes);
+ assertEquals("Unexpected response code for trust store update", 200, responseCode);
+
+ trustStore = getRestTestHelper().getJsonAsList("/rest/truststore/" + name);
+ assertNotNull("details should not be null", trustStore);
+
+ assertTrustStoreAttributes(trustStore.get(0), name, TestSSLConstants.TRUSTSTORE, false);
+ }
+
+ private List<Map<String, Object>> assertNumberOfTrustStores(int numberOfTrustStores) throws IOException,
+ JsonParseException, JsonMappingException
+ {
+ List<Map<String, Object>> trustStores = getRestTestHelper().getJsonAsList("/rest/truststore");
+ assertNotNull("trust stores should not be null", trustStores);
+ assertEquals("Unexpected number of trust stores", numberOfTrustStores, trustStores.size());
+
+ return trustStores;
+ }
+
+ private void createTrustStore(String name, boolean peersOnly) throws IOException, JsonGenerationException, JsonMappingException
+ {
+ Map<String, Object> trustStoreAttributes = new HashMap<String, Object>();
+ trustStoreAttributes.put(TrustStore.NAME, name);
+ //deliberately using the client trust store to differentiate from the one we are already for broker
+ trustStoreAttributes.put(TrustStore.PATH, TestSSLConstants.TRUSTSTORE);
+ trustStoreAttributes.put(TrustStore.PASSWORD, TestSSLConstants.TRUSTSTORE_PASSWORD);
+ trustStoreAttributes.put(TrustStore.PEERS_ONLY, peersOnly);
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/truststore/" + name, "PUT", trustStoreAttributes);
+ assertEquals("Unexpected response code", 201, responseCode);
+ }
+
+ private void assertTrustStoreAttributes(Map<String, Object> truststore, String name, String path, boolean peersOnly)
+ {
+ assertEquals("default systests trust store is missing",
+ name, truststore.get(TrustStore.NAME));
+ assertEquals("unexpected path to trust store",
+ path, truststore.get(TrustStore.PATH));
+ assertEquals("unexpected (dummy) password of default systests trust store",
+ AbstractKeyStoreAdapter.DUMMY_PASSWORD_MASK, truststore.get(TrustStore.PASSWORD));
+ assertEquals("unexpected type of default systests trust store",
+ java.security.KeyStore.getDefaultType(), truststore.get(TrustStore.TYPE));
+ assertEquals("unexpected peersOnly value",
+ peersOnly, truststore.get(TrustStore.PEERS_ONLY));
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserRestTest.java
index 017467a8be..e2a6762731 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserRestTest.java
@@ -34,6 +34,7 @@ public class UserRestTest extends QpidRestTestCase
getRestTestHelper().configureTemporaryPasswordFile(this, "user1", "user2");
super.setUp(); // do this last because it starts the broker, using the modified config
+ getRestTestHelper().setUsernameAndPassword("user1", "user1");
}
public void testGet() throws Exception
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java
index 5d23219336..220d2bc574 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java
@@ -28,22 +28,32 @@ import java.util.List;
import java.util.Map;
import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.model.AccessControlProvider;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.GroupProvider;
+import org.apache.qpid.server.model.KeyStore;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.security.access.FileAccessControlProviderConstants;
import org.apache.qpid.server.security.acl.AbstractACLTestCase;
import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory;
import org.apache.qpid.server.security.auth.manager.PlainPasswordFileAuthenticationManagerFactory;
+import org.apache.qpid.server.security.group.FileGroupManagerFactory;
import org.apache.qpid.systest.rest.QpidRestTestCase;
import org.apache.qpid.test.utils.TestBrokerConfiguration;
import org.apache.qpid.test.utils.TestFileUtils;
+import org.apache.qpid.test.utils.TestSSLConstants;
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.map.JsonMappingException;
public class BrokerACLTest extends QpidRestTestCase
{
private static final String ALLOWED_USER = "user1";
private static final String DENIED_USER = "user2";
+ private String _secondaryAclFileContent = "";
@Override
protected void customizeConfiguration() throws ConfigurationException, IOException
@@ -57,10 +67,18 @@ public class BrokerACLTest extends QpidRestTestCase
"ACL DENY-LOG " + DENIED_USER + " CONFIGURE BROKER",
"ACL DENY-LOG ALL ALL");
+ _secondaryAclFileContent =
+ "ACL ALLOW-LOG ALL ACCESS MANAGEMENT\n" +
+ "ACL ALLOW-LOG " + ALLOWED_USER + " CONFIGURE BROKER\n" +
+ "ACL DENY-LOG " + DENIED_USER + " CONFIGURE BROKER\n" +
+ "ACL DENY-LOG ALL ALL";
+
getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT,
"httpBasicAuthenticationEnabled", true);
}
+ /* === AuthenticationProvider === */
+
public void testCreateAuthenticationProviderAllowed() throws Exception
{
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
@@ -168,6 +186,8 @@ public class BrokerACLTest extends QpidRestTestCase
provider.get(PlainPasswordFileAuthenticationManagerFactory.ATTRIBUTE_PATH));
}
+ /* === VirtualHost === */
+
public void testCreateVirtualHostAllowed() throws Exception
{
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
@@ -218,6 +238,8 @@ public class BrokerACLTest extends QpidRestTestCase
assertVirtualHostExists(TEST2_VIRTUALHOST);
}
+ /* === Port === */
+
public void testCreatePortAllowed() throws Exception
{
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
@@ -249,8 +271,6 @@ public class BrokerACLTest extends QpidRestTestCase
String portName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT;
assertPortExists(portName);
- restartBrokerInManagementMode();
-
getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
int responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "DELETE", null);
@@ -259,15 +279,14 @@ public class BrokerACLTest extends QpidRestTestCase
assertPortExists(portName);
}
- public void testDeletePortAllowed() throws Exception
+ // TODO: test disabled until allowing the deletion of active ports outside management mode
+ public void DISABLED_testDeletePortAllowed() throws Exception
{
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
String portName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT;
assertPortExists(portName);
- restartBrokerInManagementMode();
-
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
int responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "DELETE", null);
@@ -276,7 +295,8 @@ public class BrokerACLTest extends QpidRestTestCase
assertPortDoesNotExist(portName);
}
- public void testSetPortAttributesAllowed() throws Exception
+ // TODO: test disabled until allowing the updating of active ports outside management mode
+ public void DISABLED_testSetPortAttributesAllowed() throws Exception
{
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
@@ -287,7 +307,6 @@ public class BrokerACLTest extends QpidRestTestCase
assertPortExists(portName);
- restartBrokerInManagementMode();
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(Port.NAME, portName);
@@ -311,8 +330,6 @@ public class BrokerACLTest extends QpidRestTestCase
assertPortExists(portName);
- restartBrokerInManagementMode();
-
getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
Map<String, Object> attributes = new HashMap<String, Object>();
@@ -327,48 +344,541 @@ public class BrokerACLTest extends QpidRestTestCase
TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, port.get(Port.AUTHENTICATION_PROVIDER));
}
+ /* === KeyStore === */
+
+ public void testCreateKeyStoreAllowed() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String keyStoreName = getTestName();
+
+ assertKeyStoreExistence(keyStoreName, false);
+
+ int responseCode = createKeyStore(keyStoreName, "app1");
+ assertEquals("keyStore creation should be allowed", 201, responseCode);
+
+ assertKeyStoreExistence(keyStoreName, true);
+ }
+
+ public void testCreateKeyStoreDenied() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+ String keyStoreName = getTestName();
+
+ assertKeyStoreExistence(keyStoreName, false);
+
+ int responseCode = createKeyStore(keyStoreName, "app1");
+ assertEquals("keyStore creation should be allowed", 403, responseCode);
+
+ assertKeyStoreExistence(keyStoreName, false);
+ }
+
+ public void testDeleteKeyStoreDenied() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String keyStoreName = getTestName();
+
+ assertKeyStoreExistence(keyStoreName, false);
+
+ int responseCode = createKeyStore(keyStoreName, "app1");
+ assertEquals("keyStore creation should be allowed", 201, responseCode);
+
+ assertKeyStoreExistence(keyStoreName, true);
+
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/keystore/" + keyStoreName, "DELETE", null);
+ assertEquals("keystore deletion should be denied", 403, responseCode);
+
+ assertKeyStoreExistence(keyStoreName, true);
+ }
+
+ public void testDeleteKeyStoreAllowed() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String keyStoreName = getTestName();
+
+ assertKeyStoreExistence(keyStoreName, false);
+
+ int responseCode = createKeyStore(keyStoreName, "app1");
+ assertEquals("keyStore creation should be allowed", 201, responseCode);
+
+ assertKeyStoreExistence(keyStoreName, true);
+
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/keystore/" + keyStoreName, "DELETE", null);
+ assertEquals("keystore deletion should be allowed", 200, responseCode);
+
+ assertKeyStoreExistence(keyStoreName, false);
+ }
+
+ public void testSetKeyStoreAttributesAllowed() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String keyStoreName = getTestName();
+ String initialCertAlias = "app1";
+ String updatedCertAlias = "app2";
+
+ assertKeyStoreExistence(keyStoreName, false);
+
+ int responseCode = createKeyStore(keyStoreName, initialCertAlias);
+ assertEquals("keyStore creation should be allowed", 201, responseCode);
+
+ assertKeyStoreExistence(keyStoreName, true);
+ Map<String, Object> keyStore = getRestTestHelper().getJsonAsSingletonList("/rest/keystore/" + keyStoreName);
+ assertEquals("Unexpected certificateAlias attribute value", initialCertAlias, keyStore.get(KeyStore.CERTIFICATE_ALIAS));
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(KeyStore.NAME, keyStoreName);
+ attributes.put(KeyStore.CERTIFICATE_ALIAS, updatedCertAlias);
+ responseCode = getRestTestHelper().submitRequest("/rest/keystore/" + keyStoreName, "PUT", attributes);
+ assertEquals("Setting of keystore attributes should be allowed", 200, responseCode);
+
+ keyStore = getRestTestHelper().getJsonAsSingletonList("/rest/keystore/" + keyStoreName);
+ assertEquals("Unexpected certificateAlias attribute value", updatedCertAlias, keyStore.get(KeyStore.CERTIFICATE_ALIAS));
+ }
+
+ public void testSetKeyStoreAttributesDenied() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String keyStoreName = getTestName();
+ String initialCertAlias = "app1";
+ String updatedCertAlias = "app2";
+
+ assertKeyStoreExistence(keyStoreName, false);
+
+ int responseCode = createKeyStore(keyStoreName, initialCertAlias);
+ assertEquals("keyStore creation should be allowed", 201, responseCode);
+
+ assertKeyStoreExistence(keyStoreName, true);
+ Map<String, Object> keyStore = getRestTestHelper().getJsonAsSingletonList("/rest/keystore/" + keyStoreName);
+ assertEquals("Unexpected certificateAlias attribute value", initialCertAlias, keyStore.get(KeyStore.CERTIFICATE_ALIAS));
+
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(KeyStore.NAME, keyStoreName);
+ attributes.put(KeyStore.CERTIFICATE_ALIAS, updatedCertAlias);
+ responseCode = getRestTestHelper().submitRequest("/rest/keystore/" + keyStoreName, "PUT", attributes);
+ assertEquals("Setting of keystore attributes should be denied", 403, responseCode);
+
+ keyStore = getRestTestHelper().getJsonAsSingletonList("/rest/keystore/" + keyStoreName);
+ assertEquals("Unexpected certificateAlias attribute value", initialCertAlias, keyStore.get(KeyStore.CERTIFICATE_ALIAS));
+ }
+
+ /* === TrustStore === */
+
+ public void testCreateTrustStoreAllowed() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String trustStoreName = getTestName();
+
+ assertTrustStoreExistence(trustStoreName, false);
+
+ int responseCode = createTrustStore(trustStoreName, false);
+ assertEquals("trustStore creation should be allowed", 201, responseCode);
+
+ assertTrustStoreExistence(trustStoreName, true);
+ }
+
+ public void testCreateTrustStoreDenied() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+ String trustStoreName = getTestName();
+
+ assertTrustStoreExistence(trustStoreName, false);
+
+ int responseCode = createTrustStore(trustStoreName, false);
+ assertEquals("trustStore creation should be allowed", 403, responseCode);
+
+ assertTrustStoreExistence(trustStoreName, false);
+ }
+
+ public void testDeleteTrustStoreDenied() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String trustStoreName = getTestName();
+
+ assertTrustStoreExistence(trustStoreName, false);
+
+ int responseCode = createTrustStore(trustStoreName, false);
+ assertEquals("trustStore creation should be allowed", 201, responseCode);
+
+ assertTrustStoreExistence(trustStoreName, true);
+
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/truststore/" + trustStoreName, "DELETE", null);
+ assertEquals("truststore deletion should be denied", 403, responseCode);
+
+ assertTrustStoreExistence(trustStoreName, true);
+ }
+
+ public void testDeleteTrustStoreAllowed() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String trustStoreName = getTestName();
+
+ assertTrustStoreExistence(trustStoreName, false);
+
+ int responseCode = createTrustStore(trustStoreName, false);
+ assertEquals("trustStore creation should be allowed", 201, responseCode);
+
+ assertTrustStoreExistence(trustStoreName, true);
+
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/truststore/" + trustStoreName, "DELETE", null);
+ assertEquals("truststore deletion should be allowed", 200, responseCode);
+
+ assertTrustStoreExistence(trustStoreName, false);
+ }
+
+ public void testSetTrustStoreAttributesAllowed() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String trustStoreName = getTestName();
+ boolean initialPeersOnly = false;
+ boolean updatedPeersOnly = true;
+
+ assertTrustStoreExistence(trustStoreName, false);
+
+ int responseCode = createTrustStore(trustStoreName, initialPeersOnly);
+ assertEquals("trustStore creation should be allowed", 201, responseCode);
+
+ assertTrustStoreExistence(trustStoreName, true);
+ Map<String, Object> trustStore = getRestTestHelper().getJsonAsSingletonList("/rest/truststore/" + trustStoreName);
+ assertEquals("Unexpected peersOnly attribute value", initialPeersOnly, trustStore.get(TrustStore.PEERS_ONLY));
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(TrustStore.NAME, trustStoreName);
+ attributes.put(TrustStore.PEERS_ONLY, updatedPeersOnly);
+ responseCode = getRestTestHelper().submitRequest("/rest/truststore/" + trustStoreName, "PUT", attributes);
+ assertEquals("Setting of truststore attributes should be allowed", 200, responseCode);
+
+ trustStore = getRestTestHelper().getJsonAsSingletonList("/rest/truststore/" + trustStoreName);
+ assertEquals("Unexpected peersOnly attribute value", updatedPeersOnly, trustStore.get(TrustStore.PEERS_ONLY));
+ }
+
+ public void testSetTrustStoreAttributesDenied() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String trustStoreName = getTestName();
+ boolean initialPeersOnly = false;
+ boolean updatedPeersOnly = true;
+
+ assertTrustStoreExistence(trustStoreName, false);
+
+ int responseCode = createTrustStore(trustStoreName, initialPeersOnly);
+ assertEquals("trustStore creation should be allowed", 201, responseCode);
+
+ assertTrustStoreExistence(trustStoreName, true);
+ Map<String, Object> trustStore = getRestTestHelper().getJsonAsSingletonList("/rest/truststore/" + trustStoreName);
+ assertEquals("Unexpected peersOnly attribute value", initialPeersOnly, trustStore.get(TrustStore.PEERS_ONLY));
+
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(TrustStore.NAME, trustStoreName);
+ attributes.put(TrustStore.PEERS_ONLY, updatedPeersOnly);
+ responseCode = getRestTestHelper().submitRequest("/rest/truststore/" + trustStoreName, "PUT", attributes);
+ assertEquals("Setting of truststore attributes should be denied", 403, responseCode);
+
+ trustStore = getRestTestHelper().getJsonAsSingletonList("/rest/truststore/" + trustStoreName);
+ assertEquals("Unexpected peersOnly attribute value", initialPeersOnly, trustStore.get(TrustStore.PEERS_ONLY));
+ }
+
+ /* === Broker === */
+
public void testSetBrokerAttributesAllowed() throws Exception
{
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
- String defaultAuthenticationProvider = TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER;
+ int initialAlertRepeatGap = 30000;
+ int updatedAlertRepeatGap = 29999;
+
Map<String, Object> brokerAttributes = getRestTestHelper().getJsonAsSingletonList("/rest/broker");
- assertEquals("Unexpected authentication provider", defaultAuthenticationProvider,
- brokerAttributes.get(Broker.DEFAULT_AUTHENTICATION_PROVIDER));
- restartBrokerInManagementMode();
+ assertEquals("Unexpected alert repeat gap", initialAlertRepeatGap,
+ brokerAttributes.get(Broker.QUEUE_ALERT_REPEAT_GAP));
Map<String, Object> newAttributes = new HashMap<String, Object>();
- newAttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, ANONYMOUS_AUTHENTICATION_PROVIDER);
+ newAttributes.put(Broker.QUEUE_ALERT_REPEAT_GAP, updatedAlertRepeatGap);
+
int responseCode = getRestTestHelper().submitRequest("/rest/broker", "PUT", newAttributes);
assertEquals("Setting of port attribites should be allowed", 200, responseCode);
brokerAttributes = getRestTestHelper().getJsonAsSingletonList("/rest/broker");
- assertEquals("Unexpected default authentication provider attribute value", ANONYMOUS_AUTHENTICATION_PROVIDER,
- brokerAttributes.get(Broker.DEFAULT_AUTHENTICATION_PROVIDER));
+ assertEquals("Unexpected default alert repeat gap", updatedAlertRepeatGap,
+ brokerAttributes.get(Broker.QUEUE_ALERT_REPEAT_GAP));
}
public void testSetBrokerAttributesDenied() throws Exception
{
getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
- String defaultAuthenticationProvider = TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER;
+ int initialAlertRepeatGap = 30000;
+ int updatedAlertRepeatGap = 29999;
Map<String, Object> brokerAttributes = getRestTestHelper().getJsonAsSingletonList("/rest/broker");
- assertEquals("Unexpected authentication provider", defaultAuthenticationProvider,
- brokerAttributes.get(Broker.DEFAULT_AUTHENTICATION_PROVIDER));
- restartBrokerInManagementMode();
+ assertEquals("Unexpected alert repeat gap", initialAlertRepeatGap,
+ brokerAttributes.get(Broker.QUEUE_ALERT_REPEAT_GAP));
getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
Map<String, Object> newAttributes = new HashMap<String, Object>();
- newAttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, ANONYMOUS_AUTHENTICATION_PROVIDER);
+ newAttributes.put(Broker.QUEUE_ALERT_REPEAT_GAP, updatedAlertRepeatGap);
+
int responseCode = getRestTestHelper().submitRequest("/rest/broker", "PUT", newAttributes);
assertEquals("Setting of port attribites should be allowed", 403, responseCode);
brokerAttributes = getRestTestHelper().getJsonAsSingletonList("/rest/broker");
- assertEquals("Unexpected default authentication provider attribute value", defaultAuthenticationProvider,
- brokerAttributes.get(Broker.DEFAULT_AUTHENTICATION_PROVIDER));
+ assertEquals("Unexpected default alert repeat gap", initialAlertRepeatGap,
+ brokerAttributes.get(Broker.QUEUE_ALERT_REPEAT_GAP));
+ }
+
+ /* === GroupProvider === */
+
+ public void testCreateGroupProviderAllowed() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String groupProviderName = getTestName();
+
+ assertGroupProviderExistence(groupProviderName, false);
+
+ int responseCode = createGroupProvider(groupProviderName);
+ assertEquals("Group provider creation should be allowed", 201, responseCode);
+
+ assertGroupProviderExistence(groupProviderName, true);
}
+ public void testCreateGroupProviderDenied() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+ String groupProviderName = getTestName();
+
+ assertGroupProviderExistence(groupProviderName, false);
+
+ int responseCode = createGroupProvider(groupProviderName);
+ assertEquals("Group provider creation should be denied", 403, responseCode);
+
+ assertGroupProviderExistence(groupProviderName, false);
+ }
+
+ public void testDeleteGroupProviderDenied() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String groupProviderName = getTestName();
+
+ assertGroupProviderExistence(groupProviderName, false);
+
+ int responseCode = createGroupProvider(groupProviderName);
+ assertEquals("Group provider creation should be allowed", 201, responseCode);
+
+ assertGroupProviderExistence(groupProviderName, true);
+
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + groupProviderName, "DELETE", null);
+ assertEquals("Group provider deletion should be denied", 403, responseCode);
+
+ assertGroupProviderExistence(groupProviderName, true);
+ }
+
+ public void testDeleteGroupProviderAllowed() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String groupProviderName = getTestName();
+
+ assertGroupProviderExistence(groupProviderName, false);
+
+ int responseCode = createGroupProvider(groupProviderName);
+ assertEquals("Group provider creation should be allowed", 201, responseCode);
+
+ assertGroupProviderExistence(groupProviderName, true);
+
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + groupProviderName, "DELETE", null);
+ assertEquals("Group provider deletion should be allowed", 200, responseCode);
+
+ assertGroupProviderExistence(groupProviderName, false);
+ }
+
+ public void testSetGroupProviderAttributesAllowed() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String groupProviderName = getTestName();
+
+ assertGroupProviderExistence(groupProviderName, false);
+
+ int responseCode = createGroupProvider(groupProviderName);
+ assertEquals("Group provider creation should be allowed", 201, responseCode);
+
+ assertGroupProviderExistence(groupProviderName, true);
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(GroupProvider.NAME, groupProviderName);
+ attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+ attributes.put(FileGroupManagerFactory.PATH, "/path/to/file");
+ responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + groupProviderName, "PUT", attributes);
+ assertEquals("Setting of group provider attributes should be allowed but not supported", 409, responseCode);
+ }
+
+ public void testSetGroupProviderAttributesDenied() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String groupProviderName = getTestName();
+
+ assertGroupProviderExistence(groupProviderName, false);
+
+ int responseCode = createGroupProvider(groupProviderName);
+ assertEquals("Group provider creation should be allowed", 201, responseCode);
+
+ assertGroupProviderExistence(groupProviderName, true);
+
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(GroupProvider.NAME, groupProviderName);
+ attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+ attributes.put(FileGroupManagerFactory.PATH, "/path/to/file");
+ responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + groupProviderName, "PUT", attributes);
+ assertEquals("Setting of group provider attributes should be denied", 403, responseCode);
+ }
+
+ /* === AccessControlProvider === */
+
+ public void testCreateAccessControlProviderAllowed() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String accessControlProviderName = getTestName();
+
+ assertAccessControlProviderExistence(accessControlProviderName, false);
+
+ int responseCode = createAccessControlProvider(accessControlProviderName);
+ assertEquals("Access control provider creation should be allowed", 201, responseCode);
+
+ assertAccessControlProviderExistence(accessControlProviderName, true);
+ }
+
+ public void testCreateAccessControlProviderDenied() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+ String accessControlProviderName = getTestName();
+
+ assertAccessControlProviderExistence(accessControlProviderName, false);
+
+ int responseCode = createAccessControlProvider(accessControlProviderName);
+ assertEquals("Access control provider creation should be denied", 403, responseCode);
+
+ assertAccessControlProviderExistence(accessControlProviderName, false);
+ }
+
+ public void testDeleteAccessControlProviderDenied() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String accessControlProviderName = getTestName();
+
+ assertAccessControlProviderExistence(accessControlProviderName, false);
+
+ int responseCode = createAccessControlProvider(accessControlProviderName);
+ assertEquals("Access control provider creation should be allowed", 201, responseCode);
+
+ assertAccessControlProviderExistence(accessControlProviderName, true);
+
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/accesscontrolprovider/" + accessControlProviderName, "DELETE", null);
+ assertEquals("Access control provider deletion should be denied", 403, responseCode);
+
+ assertAccessControlProviderExistence(accessControlProviderName, true);
+ }
+
+ public void testDeleteAccessControlProviderAllowed() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String accessControlProviderName = getTestName();
+
+ assertAccessControlProviderExistence(accessControlProviderName, false);
+
+ int responseCode = createAccessControlProvider(accessControlProviderName);
+ assertEquals("Access control provider creation should be allowed", 201, responseCode);
+
+ assertAccessControlProviderExistence(accessControlProviderName, true);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/accesscontrolprovider/" + accessControlProviderName, "DELETE", null);
+ assertEquals("Access control provider deletion should be allowed", 200, responseCode);
+
+ assertAccessControlProviderExistence(accessControlProviderName, false);
+ }
+
+ public void testSetAccessControlProviderAttributesAllowedButUnsupported() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String accessControlProviderName = getTestName();
+
+ assertAccessControlProviderExistence(accessControlProviderName, false);
+
+ int responseCode = createAccessControlProvider(accessControlProviderName);
+ assertEquals("Access control provider creation should be allowed", 201, responseCode);
+
+ assertAccessControlProviderExistence(accessControlProviderName, true);
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(GroupProvider.NAME, accessControlProviderName);
+ attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+ attributes.put(FileGroupManagerFactory.PATH, "/path/to/file");
+ responseCode = getRestTestHelper().submitRequest("/rest/accesscontrolprovider/" + accessControlProviderName, "PUT", attributes);
+ assertEquals("Setting of access control provider attributes should be allowed but not supported", 409, responseCode);
+ }
+
+ public void testSetAccessControlProviderAttributesDenied() throws Exception
+ {
+ getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+ String accessControlProviderName = getTestName();
+
+ assertAccessControlProviderExistence(accessControlProviderName, false);
+
+ int responseCode = createAccessControlProvider(accessControlProviderName);
+ assertEquals("Access control provider creation should be allowed", 201, responseCode);
+
+ assertAccessControlProviderExistence(accessControlProviderName, true);
+
+ getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(GroupProvider.NAME, accessControlProviderName);
+ attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+ attributes.put(FileGroupManagerFactory.PATH, "/path/to/file");
+ responseCode = getRestTestHelper().submitRequest("/rest/accesscontrolprovider/" + accessControlProviderName, "PUT", attributes);
+ assertEquals("Setting of access control provider attributes should be denied", 403, responseCode);
+ }
+
+ /* === Utility Methods === */
+
private int createPort(String portName) throws Exception
{
Map<String, Object> attributes = new HashMap<String, Object>();
@@ -395,6 +905,18 @@ public class BrokerACLTest extends QpidRestTestCase
assertEquals("Unexpected result", exists, !hosts.isEmpty());
}
+ private void assertKeyStoreExistence(String keyStoreName, boolean exists) throws Exception
+ {
+ List<Map<String, Object>> keyStores = getRestTestHelper().getJsonAsList("/rest/keystore/" + keyStoreName);
+ assertEquals("Unexpected result", exists, !keyStores.isEmpty());
+ }
+
+ private void assertTrustStoreExistence(String trustStoreName, boolean exists) throws Exception
+ {
+ List<Map<String, Object>> trustStores = getRestTestHelper().getJsonAsList("/rest/truststore/" + trustStoreName);
+ assertEquals("Unexpected result", exists, !trustStores.isEmpty());
+ }
+
private int createHost(String hostName) throws Exception
{
Map<String, Object> hostData = new HashMap<String, Object>();
@@ -452,4 +974,61 @@ public class BrokerACLTest extends QpidRestTestCase
assertEquals("Unexpected result", exists, !providers.isEmpty());
}
+ private int createKeyStore(String name, String certAlias) throws IOException, JsonGenerationException, JsonMappingException
+ {
+ Map<String, Object> keyStoreAttributes = new HashMap<String, Object>();
+ keyStoreAttributes.put(KeyStore.NAME, name);
+ keyStoreAttributes.put(KeyStore.PATH, TestSSLConstants.KEYSTORE);
+ keyStoreAttributes.put(KeyStore.PASSWORD, TestSSLConstants.KEYSTORE_PASSWORD);
+ keyStoreAttributes.put(KeyStore.CERTIFICATE_ALIAS, certAlias);
+
+ return getRestTestHelper().submitRequest("/rest/keystore/" + name, "PUT", keyStoreAttributes);
+ }
+
+ private int createTrustStore(String name, boolean peersOnly) throws IOException, JsonGenerationException, JsonMappingException
+ {
+ Map<String, Object> trustStoreAttributes = new HashMap<String, Object>();
+ trustStoreAttributes.put(TrustStore.NAME, name);
+ trustStoreAttributes.put(TrustStore.PATH, TestSSLConstants.KEYSTORE);
+ trustStoreAttributes.put(TrustStore.PASSWORD, TestSSLConstants.KEYSTORE_PASSWORD);
+ trustStoreAttributes.put(TrustStore.PEERS_ONLY, peersOnly);
+
+ return getRestTestHelper().submitRequest("/rest/truststore/" + name, "PUT", trustStoreAttributes);
+ }
+
+ private void assertGroupProviderExistence(String groupProviderName, boolean exists) throws Exception
+ {
+ String path = "/rest/groupprovider/" + groupProviderName;
+ List<Map<String, Object>> providers = getRestTestHelper().getJsonAsList(path);
+ assertEquals("Unexpected result", exists, !providers.isEmpty());
+ }
+
+ private int createGroupProvider(String groupProviderName) throws Exception
+ {
+ File file = TestFileUtils.createTempFile(this, ".groups");
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(GroupProvider.NAME, groupProviderName);
+ attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+ attributes.put(FileGroupManagerFactory.PATH, file.getAbsoluteFile());
+
+ return getRestTestHelper().submitRequest("/rest/groupprovider/" + groupProviderName, "PUT", attributes);
+ }
+
+ private void assertAccessControlProviderExistence(String accessControlProviderName, boolean exists) throws Exception
+ {
+ String path = "/rest/accesscontrolprovider/" + accessControlProviderName;
+ List<Map<String, Object>> providers = getRestTestHelper().getJsonAsList(path);
+ assertEquals("Unexpected result", exists, !providers.isEmpty());
+ }
+
+ private int createAccessControlProvider(String accessControlProviderName) throws Exception
+ {
+ File file = TestFileUtils.createTempFile(this, ".acl", _secondaryAclFileContent);
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(AccessControlProvider.NAME, accessControlProviderName);
+ attributes.put(AccessControlProvider.TYPE, FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE);
+ attributes.put(FileAccessControlProviderConstants.PATH, file.getAbsoluteFile());
+
+ return getRestTestHelper().submitRequest("/rest/accesscontrolprovider/" + accessControlProviderName, "PUT", attributes);
+ }
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java
index 40ea723b1e..3fceb27a4b 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java
@@ -29,14 +29,13 @@ import java.util.Properties;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.configuration.ConfigurationException;
-import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.security.acl.AbstractACLTestCase;
import org.apache.qpid.systest.rest.QpidRestTestCase;
import org.apache.qpid.test.utils.TestBrokerConfiguration;
public class GroupRestACLTest extends QpidRestTestCase
{
- private static final String FILE_GROUP_MANAGER = "FileGroupManager";
+ private static final String FILE_GROUP_MANAGER = TestBrokerConfiguration.ENTRY_NAME_GROUP_FILE;
private static final String ALLOWED_GROUP = "allowedGroup";
private static final String DENIED_GROUP = "deniedGroup";
@@ -52,7 +51,7 @@ public class GroupRestACLTest extends QpidRestTestCase
public void setUp() throws Exception
{
_groupFile = createTemporaryGroupFile();
- getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath());
+ getBrokerConfiguration().addGroupFileConfiguration(_groupFile.getAbsolutePath());
//DONT call super.setUp(), the tests will start the broker after configuring it
}
@@ -191,7 +190,7 @@ public class GroupRestACLTest extends QpidRestTestCase
private void assertNumberOfGroupMembers(String groupName, int expectedNumberOfMembers) throws IOException
{
- Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/" + groupName);
+ Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/" + FILE_GROUP_MANAGER + "/" + groupName);
getRestTestHelper().assertNumberOfGroupMembers(group, expectedNumberOfMembers);
}
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java
index 12973113d8..3b81df6fd1 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java
@@ -29,7 +29,6 @@ import java.util.Properties;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.configuration.ConfigurationException;
-import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.security.acl.AbstractACLTestCase;
import org.apache.qpid.systest.rest.QpidRestTestCase;
import org.apache.qpid.test.utils.TestBrokerConfiguration;
@@ -52,7 +51,7 @@ public class UserRestACLTest extends QpidRestTestCase
public void setUp() throws Exception
{
_groupFile = createTemporaryGroupFile();
- getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath());
+ getBrokerConfiguration().addGroupFileConfiguration(_groupFile.getAbsolutePath());
getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER, OTHER_USER);
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java
index 3cc15d5e9d..1ee5b997f2 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java
@@ -142,7 +142,7 @@ public class JMSDestinationTest extends QpidBrokerTestCase
{
// Setup JMXUtils
JMXTestUtils jmxUtils = new JMXTestUtils(this);
- jmxUtils.setUp();
+
// Open the JMX Connection
jmxUtils.open();
try
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java
index 4e9477f4b6..734e3f2268 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java
@@ -42,8 +42,9 @@ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase
@Override
public void setUp() throws Exception
{
+ getBrokerConfiguration().addJmxManagementConfiguration();
+
_jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
super.setUp();
_jmxUtils.open();
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
index a9ac028af6..4b61b6269c 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
@@ -24,6 +24,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQNoRouteException;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
@@ -31,6 +32,7 @@ import org.apache.qpid.management.common.JMXConnnectionFactory;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import javax.jms.Connection;
+import javax.jms.ExceptionListener;
import javax.jms.InvalidDestinationException;
import javax.jms.InvalidSelectorException;
import javax.jms.JMSException;
@@ -46,6 +48,8 @@ import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import java.io.IOException;
import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* @todo Code to check that a consumer gets only one particular method could be factored into a re-usable method (as
@@ -58,7 +62,11 @@ import java.util.Set;
public class DurableSubscriptionTest extends QpidBrokerTestCase
{
private static final Logger _logger = LoggerFactory.getLogger(DurableSubscriptionTest.class);
-
+
+ private static final String MY_TOPIC = "MyTopic";
+
+ private static final String MY_SUBSCRIPTION = "MySubscription";
+
/** Timeout for receive() if we are expecting a message */
private static final long POSITIVE_RECEIVE_TIMEOUT = 2000;
@@ -80,24 +88,29 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
public void tearDown() throws Exception
{
- if(_jmxConnected)
+ try
{
- try
+ if(_jmxConnected)
{
- _jmxc.close();
- }
- catch (IOException e)
- {
- e.printStackTrace();
+ try
+ {
+ _jmxc.close();
+ }
+ catch (IOException e)
+ {
+ _logger.error("Error closing JMX connection", e);
+ }
}
}
-
- super.tearDown();
+ finally
+ {
+ super.tearDown();
+ }
}
-
+
public void testUnsubscribe() throws Exception
{
- AMQConnection con = (AMQConnection) getConnection("guest", "guest");
+ AMQConnection con = (AMQConnection) getConnection();
AMQTopic topic = new AMQTopic(con, "MyDurableSubscriptionTestTopic");
_logger.info("Create Session 1");
Session session1 = con.createSession(false, AMQSession.NO_ACKNOWLEDGE);
@@ -109,7 +122,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
_logger.info("Create Session 2");
Session session2 = con.createSession(false, AMQSession.NO_ACKNOWLEDGE);
_logger.info("Create Durable Subscriber on Session 2");
- TopicSubscriber consumer2 = session2.createDurableSubscriber(topic, "MySubscription");
+ TopicSubscriber consumer2 = session2.createDurableSubscriber(topic, MY_SUBSCRIPTION);
_logger.info("Starting connection");
con.start();
@@ -118,7 +131,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
producer.send(session1.createTextMessage("A"));
//check the dur sub's underlying queue now has msg count 1
- AMQQueue subQueue = new AMQQueue("amq.topic", "clientid" + ":" + "MySubscription");
+ AMQQueue subQueue = new AMQQueue("amq.topic", "clientid" + ":" + MY_SUBSCRIPTION);
assertEquals("Msg count should be 1", 1, ((AMQSession<?, ?>) session1).getQueueDepth(subQueue, true));
Message msg;
@@ -143,7 +156,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
consumer2.close();
_logger.info("Unsubscribe session2/consumer2");
- session2.unsubscribe("MySubscription");
+ session2.unsubscribe(MY_SUBSCRIPTION);
((AMQSession<?, ?>) session2).sync();
@@ -157,7 +170,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
_mbsc = _jmxc.getMBeanServerConnection();
//must replace the occurrence of ':' in queue name with '-'
- String queueObjectNameText = "clientid" + "-" + "MySubscription";
+ String queueObjectNameText = "clientid" + "-" + MY_SUBSCRIPTION;
ObjectName objName = new ObjectName("org.apache.qpid:type=VirtualHost.Queue,name="
+ queueObjectNameText + ",*");
@@ -189,7 +202,74 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
_logger.info("Close connection");
con.close();
}
-
+
+
+ /**
+ * Specifically uses a subscriber with a selector because QPID-4731 found that selectors
+ * can prevent queue removal.
+ */
+ public void testUnsubscribeWhenUsingSelectorMakesTopicUnreachable() throws Exception
+ {
+ setTestClientSystemProperty("qpid.default_mandatory_topic","true");
+
+ // set up subscription
+ AMQConnection connection = (AMQConnection) getConnection();
+ connection.start();
+
+ Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ Topic topic = new AMQTopic(connection, MY_TOPIC);
+ MessageProducer producer = session.createProducer(topic);
+
+ TopicSubscriber subscriber = session.createDurableSubscriber(topic, MY_SUBSCRIPTION, "1 = 1", false);
+ StoringExceptionListener exceptionListener = new StoringExceptionListener();
+ connection.setExceptionListener(exceptionListener);
+
+ // send message and verify it was consumed
+ producer.send(session.createTextMessage("message1"));
+ assertNotNull("Message should have been successfully received", subscriber.receive(POSITIVE_RECEIVE_TIMEOUT));
+ assertEquals(null, exceptionListener.getException());
+ session.unsubscribe(MY_SUBSCRIPTION);
+
+ // send another message and verify that the connection exception listener was fired.
+ StoringExceptionListener exceptionListener2 = new StoringExceptionListener();
+ connection.setExceptionListener(exceptionListener2);
+
+ producer.send(session.createTextMessage("message that should be unroutable"));
+ ((AMQSession<?, ?>) session).sync();
+
+ JMSException exception = exceptionListener2.awaitException();
+ assertNotNull("Expected exception as message should no longer be routable", exception);
+
+ Throwable linkedException = exception.getLinkedException();
+ assertNotNull("The linked exception of " + exception + " should be the 'no route' exception", linkedException);
+ assertEquals(AMQNoRouteException.class, linkedException.getClass());
+ }
+
+ private final class StoringExceptionListener implements ExceptionListener
+ {
+ private volatile JMSException _exception;
+ private CountDownLatch _latch = new CountDownLatch(1);
+
+ @Override
+ public void onException(JMSException exception)
+ {
+ _exception = exception;
+ _logger.info("Exception listener received: " + exception);
+ _latch.countDown();
+ }
+
+ public JMSException awaitException() throws InterruptedException
+ {
+ _latch.await(POSITIVE_RECEIVE_TIMEOUT, TimeUnit.MILLISECONDS);
+ return _exception;
+ }
+
+ public JMSException getException()
+ {
+ return _exception;
+ }
+ }
+
public void testDurabilityNOACK() throws Exception
{
durabilityImpl(AMQSession.NO_ACKNOWLEDGE, false);
@@ -223,8 +303,8 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
private void durabilityImpl(int ackMode, boolean restartBroker) throws Exception
{
- AMQConnection con = (AMQConnection) getConnection("guest", "guest");
- AMQTopic topic = new AMQTopic(con, "MyTopic");
+ AMQConnection con = (AMQConnection) getConnection();
+ AMQTopic topic = new AMQTopic(con, MY_TOPIC);
Session session1 = con.createSession(false, ackMode);
MessageConsumer consumer1 = session1.createConsumer(topic);
@@ -232,7 +312,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
MessageProducer producer = sessionProd.createProducer(topic);
Session session2 = con.createSession(false, ackMode);
- TopicSubscriber consumer2 = session2.createDurableSubscriber(topic, "MySubscription");
+ TopicSubscriber consumer2 = session2.createDurableSubscriber(topic, MY_SUBSCRIPTION);
con.start();
@@ -267,13 +347,13 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
consumer2.close();
session2.close();
-
+
//Send message C, then connect consumer 3 to durable subscription and get
//message B if not using NO_ACK, then receive C with consumer 1 and 3
producer.send(session1.createTextMessage("C"));
Session session3 = con.createSession(false, ackMode);
- MessageConsumer consumer3 = session3.createDurableSubscriber(topic, "MySubscription");
+ MessageConsumer consumer3 = session3.createDurableSubscriber(topic, MY_SUBSCRIPTION);
if(ackMode == AMQSession.NO_ACKNOWLEDGE)
{
@@ -307,7 +387,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
consumer1.close();
consumer3.close();
- session3.unsubscribe("MySubscription");
+ session3.unsubscribe(MY_SUBSCRIPTION);
con.close();
@@ -328,28 +408,28 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
{
Message msg;
// Create producer.
- AMQConnection con0 = (AMQConnection) getConnection("guest", "guest");
+ AMQConnection con0 = (AMQConnection) getConnection();
con0.start();
Session session0 = con0.createSession(false, ackMode);
- AMQTopic topic = new AMQTopic(con0, "MyTopic");
+ AMQTopic topic = new AMQTopic(con0, MY_TOPIC);
Session sessionProd = con0.createSession(false, ackMode);
MessageProducer producer = sessionProd.createProducer(topic);
// Create consumer 1.
- AMQConnection con1 = (AMQConnection) getConnection("guest", "guest");
+ AMQConnection con1 = (AMQConnection) getConnection();
con1.start();
Session session1 = con1.createSession(false, ackMode);
MessageConsumer consumer1 = session1.createConsumer(topic);
// Create consumer 2.
- AMQConnection con2 = (AMQConnection) getConnection("guest", "guest");
+ AMQConnection con2 = (AMQConnection) getConnection();
con2.start();
Session session2 = con2.createSession(false, ackMode);
- TopicSubscriber consumer2 = session2.createDurableSubscriber(topic, "MySubscription");
+ TopicSubscriber consumer2 = session2.createDurableSubscriber(topic, MY_SUBSCRIPTION);
// Send message and check that both consumers get it and only it.
producer.send(session0.createTextMessage("A"));
@@ -393,11 +473,11 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
// Re-attach a new consumer to the durable subscription, and check that it gets message B it left (if not NO_ACK)
// and also gets message C sent after it was disconnected.
- AMQConnection con3 = (AMQConnection) getConnection("guest", "guest");
+ AMQConnection con3 = (AMQConnection) getConnection();
con3.start();
Session session3 = con3.createSession(false, ackMode);
- TopicSubscriber consumer3 = session3.createDurableSubscriber(topic, "MySubscription");
+ TopicSubscriber consumer3 = session3.createDurableSubscriber(topic, MY_SUBSCRIPTION);
if(ackMode == AMQSession.NO_ACKNOWLEDGE)
{
@@ -423,7 +503,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
consumer1.close();
consumer3.close();
- session3.unsubscribe("MySubscription");
+ session3.unsubscribe(MY_SUBSCRIPTION);
con0.close();
con1.close();
@@ -540,7 +620,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
TopicSubscriber subB = session.createDurableSubscriber(topic,
"testResubscribeWithChangedSelector","Match = False", false);
- //verify no messages are now recieved.
+ //verify no messages are now received.
rMsg = subB.receive(NEGATIVE_RECEIVE_TIMEOUT);
assertNull("Should not have received message as the selector was changed", rMsg);
@@ -746,7 +826,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
* <li>create another durable subscriber with a selector and same name
* <li>check first subscriber is now closed
* <li>create a publisher and send messages
- * <li>check messages are recieved correctly
+ * <li>check messages are received correctly
* </ul>
* <p>
* QPID-2418
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java
index 6e6e3271f0..b8ca4b3f7f 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java
@@ -21,7 +21,6 @@
package org.apache.qpid.test.utils;
import junit.framework.TestCase;
-import org.apache.commons.configuration.ConfigurationException;
import org.apache.qpid.management.common.JMXConnnectionFactory;
import org.apache.qpid.management.common.mbeans.LoggingManagement;
@@ -31,8 +30,6 @@ import org.apache.qpid.management.common.mbeans.ManagedExchange;
import org.apache.qpid.management.common.mbeans.ManagedQueue;
import org.apache.qpid.management.common.mbeans.ServerInformation;
import org.apache.qpid.management.common.mbeans.UserManagement;
-import org.apache.qpid.server.model.Plugin;
-import org.apache.qpid.server.plugin.PluginFactory;
import javax.management.InstanceNotFoundException;
import javax.management.JMException;
@@ -47,9 +44,7 @@ import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Set;
/**
@@ -79,11 +74,6 @@ public class JMXTestUtils
this(test, DEFAULT_USERID, DEFAULT_PASSWORD);
}
- public void setUp() throws IOException, ConfigurationException, Exception
- {
- _test.getBrokerConfiguration().addJmxManagementConfiguration();
- }
-
public void open() throws Exception
{
open(0); // Zero signifies default broker to QBTC.
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
index ba7fac3312..c14c724419 100755
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
@@ -184,6 +184,7 @@ public class QpidBrokerTestCase extends QpidTestCase
protected List<Connection> _connections = new ArrayList<Connection>();
public static final String QUEUE = "queue";
public static final String TOPIC = "topic";
+ public static final String MANAGEMENT_MODE_PASSWORD = "mm_password";
/** Map to hold test defined environment properties */
private Map<String, String> _env;
@@ -467,6 +468,10 @@ public class QpidBrokerTestCase extends QpidTestCase
options.setConfigurationStoreType(_brokerStoreType);
options.setConfigurationStoreLocation(testConfig);
options.setManagementMode(managementMode);
+ if (managementMode)
+ {
+ options.setManagementModePassword(MANAGEMENT_MODE_PASSWORD);
+ }
//Set the log config file, relying on the log4j.configuration system property
//set on the JVM by the JUnit runner task in module.xml.
@@ -486,9 +491,11 @@ public class QpidBrokerTestCase extends QpidTestCase
String[] cmd = _brokerCommandHelper.getBrokerCommand(port, testConfig, _brokerStoreType, _logConfigFile);
if (managementMode)
{
- String[] newCmd = new String[cmd.length + 1];
+ String[] newCmd = new String[cmd.length + 3];
System.arraycopy(cmd, 0, newCmd, 0, cmd.length);
newCmd[cmd.length] = "-mm";
+ newCmd[cmd.length + 1] = "-mmpass";
+ newCmd[cmd.length + 2] = MANAGEMENT_MODE_PASSWORD;
cmd = newCmd;
}
_logger.info("Starting spawn broker using command: " + StringUtils.join(cmd, ' '));
@@ -849,7 +856,7 @@ public class QpidBrokerTestCase extends QpidTestCase
attributes.put(VirtualHost.NAME, virtualHostName);
attributes.put(VirtualHost.CONFIG_PATH, System.getProperty("broker.virtualhosts-config"));
int port = getPort(brokerPort);
- getBrokerConfiguration(port).addHostConfiguration(attributes);
+ getBrokerConfiguration(port).addVirtualHostConfiguration(attributes);
}
/**
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java
index db10bfb7e7..a91c9bb752 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java
@@ -21,6 +21,7 @@
package org.apache.qpid.test.utils;
import java.io.File;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -29,13 +30,20 @@ import java.util.Set;
import java.util.UUID;
import org.apache.qpid.server.configuration.ConfigurationEntry;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.store.MemoryConfigurationEntryStore;
+import org.apache.qpid.server.model.AccessControlProvider;
import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.GroupProvider;
+import org.apache.qpid.server.model.KeyStore;
import org.apache.qpid.server.model.Plugin;
import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.plugin.PluginFactory;
+import org.apache.qpid.server.security.access.FileAccessControlProviderConstants;
+import org.apache.qpid.server.security.group.FileGroupManagerFactory;
public class TestBrokerConfiguration
{
@@ -52,13 +60,16 @@ public class TestBrokerConfiguration
public static final String ENTRY_NAME_JMX_MANAGEMENT = "MANAGEMENT-JMX";
public static final String MANAGEMENT_JMX_PLUGIN_TYPE = "MANAGEMENT-JMX";
public static final String ENTRY_NAME_ANONYMOUS_PROVIDER = "anonymous";
+ public static final String ENTRY_NAME_SSL_KEYSTORE = "systestsKeyStore";
+ public static final String ENTRY_NAME_SSL_TRUSTSTORE = "systestsTrustStore";
+ public static final String ENTRY_NAME_GROUP_FILE = "groupFile";
+ public static final String ENTRY_NAME_ACL_FILE = "aclFile";
private MemoryConfigurationEntryStore _store;
private boolean _saved;
public TestBrokerConfiguration(String storeType, String intialStoreLocation)
{
- // TODO: add support for DERBY store
_store = new MemoryConfigurationEntryStore(intialStoreLocation, null);
}
@@ -105,7 +116,7 @@ public class TestBrokerConfiguration
public UUID addObjectConfiguration(String name, String type, Map<String, Object> attributes)
{
- UUID id = UUIDGenerator.generateBrokerChildUUID(type, name);
+ UUID id = UUIDGenerator.generateRandomUUID();
addObjectConfiguration(id, type, attributes);
return id;
}
@@ -126,13 +137,33 @@ public class TestBrokerConfiguration
return addObjectConfiguration(ENTRY_NAME_HTTP_MANAGEMENT, Plugin.class.getSimpleName(), attributes);
}
+ public UUID addGroupFileConfiguration(String groupFilePath)
+ {
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(GroupProvider.NAME, ENTRY_NAME_GROUP_FILE);
+ attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE);
+ attributes.put(FileGroupManagerFactory.PATH, groupFilePath);
+
+ return addGroupProviderConfiguration(attributes);
+ }
+
+ public UUID addAclFileConfiguration(String aclFilePath)
+ {
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(AccessControlProvider.NAME, ENTRY_NAME_ACL_FILE);
+ attributes.put(AccessControlProvider.TYPE, FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE);
+ attributes.put(FileAccessControlProviderConstants.PATH, aclFilePath);
+
+ return addAccessControlConfiguration(attributes);
+ }
+
public UUID addPortConfiguration(Map<String, Object> attributes)
{
String name = (String) attributes.get(Port.NAME);
return addObjectConfiguration(name, Port.class.getSimpleName(), attributes);
}
- public UUID addHostConfiguration(Map<String, Object> attributes)
+ public UUID addVirtualHostConfiguration(Map<String, Object> attributes)
{
String name = (String) attributes.get(VirtualHost.NAME);
return addObjectConfiguration(name, VirtualHost.class.getSimpleName(), attributes);
@@ -144,6 +175,30 @@ public class TestBrokerConfiguration
return addObjectConfiguration(name, AuthenticationProvider.class.getSimpleName(), attributes);
}
+ public UUID addGroupProviderConfiguration(Map<String, Object> attributes)
+ {
+ String name = (String) attributes.get(GroupProvider.NAME);
+ return addObjectConfiguration(name, GroupProvider.class.getSimpleName(), attributes);
+ }
+
+ public UUID addAccessControlConfiguration(Map<String, Object> attributes)
+ {
+ String name = (String) attributes.get(AccessControlProvider.NAME);
+ return addObjectConfiguration(name, AccessControlProvider.class.getSimpleName(), attributes);
+ }
+
+ public UUID addTrustStoreConfiguration(Map<String, Object> attributes)
+ {
+ String name = (String) attributes.get(TrustStore.NAME);
+ return addObjectConfiguration(name, TrustStore.class.getSimpleName(), attributes);
+ }
+
+ public UUID addKeyStoreConfiguration(Map<String, Object> attributes)
+ {
+ String name = (String) attributes.get(KeyStore.NAME);
+ return addObjectConfiguration(name, KeyStore.class.getSimpleName(), attributes);
+ }
+
private boolean setObjectAttributes(ConfigurationEntry entry, Map<String, Object> attributes)
{
Map<String, Object> newAttributes = new HashMap<String, Object>(entry.getAttributes());
@@ -188,6 +243,11 @@ public class TestBrokerConfiguration
{
ConfigurationEntry entry = new ConfigurationEntry(id, type, attributes, Collections.<UUID> emptySet(), _store);
ConfigurationEntry root = _store.getRootEntry();
+
+ Map<String, Collection<ConfigurationEntry>> children = root.getChildren();
+
+ verifyChildWithNameDoesNotExist(id, type, attributes, children);
+
Set<UUID> childrenIds = new HashSet<UUID>(root.getChildrenIds());
childrenIds.add(id);
ConfigurationEntry newRoot = new ConfigurationEntry(root.getId(), root.getType(), root.getAttributes(), childrenIds,
@@ -195,6 +255,26 @@ public class TestBrokerConfiguration
_store.save(newRoot, entry);
}
+ private void verifyChildWithNameDoesNotExist(UUID id, String type,
+ Map<String, Object> attributes,
+ Map<String, Collection<ConfigurationEntry>> children)
+ {
+ Collection<ConfigurationEntry> childrenOfType = children.get(type);
+
+ if(childrenOfType != null)
+ {
+ String name = (String) attributes.get("name");
+ for(ConfigurationEntry ce : childrenOfType)
+ {
+ Object ceName = ce.getAttributes().get("name");
+ if(name.equals(ceName) && !id.equals(ce.getId()))
+ {
+ throw new IllegalConfigurationException("A " + type + " with name " + name + " already exists with a different ID");
+ }
+ }
+ }
+ }
+
private boolean setObjectAttribute(ConfigurationEntry entry, String attributeName, Object value)
{
Map<String, Object> attributes = new HashMap<String, Object>(entry.getAttributes());
diff --git a/qpid/java/test-profiles/CPPExcludes b/qpid/java/test-profiles/CPPExcludes
index 8b74a19b8e..b429305572 100755
--- a/qpid/java/test-profiles/CPPExcludes
+++ b/qpid/java/test-profiles/CPPExcludes
@@ -60,6 +60,7 @@ org.apache.qpid.test.client.timeouts.SyncWaitTimeoutDelayTest#*
// c++ broker doesn't support message bouncing
org.apache.qpid.server.exchange.ReturnUnroutableMandatoryMessageTest#*
+org.apache.qpid.test.unit.topic.DurableSubscriptionTest#testUnsubscribeWhenUsingSelectorMakesTopicUnreachable
// c++ broker expires messages on delivery or when the queue cleaner thread runs.
org.apache.qpid.server.queue.TimeToLiveTest#testActiveTTL
diff --git a/qpid/java/test-profiles/Excludes b/qpid/java/test-profiles/Excludes
index 9c07fea574..7a6089004e 100644
--- a/qpid/java/test-profiles/Excludes
+++ b/qpid/java/test-profiles/Excludes
@@ -17,16 +17,4 @@
// under the License.
//
-//
-// QPID-2031 : Broker is not cleanly shutdown by QpidTestCase
-//
-org.apache.qpid.server.logging.BrokerLoggingTest#testBrokerShutdownListeningTCPDefault
-org.apache.qpid.server.logging.BrokerLoggingTest#testBrokerShutdownListeningTCPSSL
-org.apache.qpid.server.logging.BrokerLoggingTest#testBrokerShutdownStopped
-org.apache.qpid.server.logging.VirtualHostLoggingTest#testVirtualhostClosure
-org.apache.qpid.server.logging.MemoryMessageStoreLoggingTest#testMessageStoreClose
-
-// QPID-3424 : Test fails to start external broker due to Derby Exception.
-org.apache.qpid.server.logging.DerbyMessageStoreLoggingTest#*
-
org.apache.qpid.client.ssl.SSLTest#testVerifyLocalHostLocalDomain
diff --git a/qpid/java/test-profiles/Java010Excludes b/qpid/java/test-profiles/Java010Excludes
index c4b3ac8d66..6ae5a40f89 100755
--- a/qpid/java/test-profiles/Java010Excludes
+++ b/qpid/java/test-profiles/Java010Excludes
@@ -25,6 +25,7 @@ org.apache.qpid.test.client.FlowControlTest#*
// 0-10 protocol doesn't support message bouncing
org.apache.qpid.server.exchange.ReturnUnroutableMandatoryMessageTest#*
+org.apache.qpid.test.unit.topic.DurableSubscriptionTest#testUnsubscribeWhenUsingSelectorMakesTopicUnreachable
// 0-10 and 0-9 connections dont generate the exact same logging due to protocol differences
org.apache.qpid.server.logging.ChannelLoggingTest#testChannelStartsFlowStopped