You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2012/11/01 10:48:57 UTC

svn commit: r1404521 [1/6] - in /qpid/branches/java-broker-config-qpid-4390/qpid/java: ./ broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ bro...

Author: orudyy
Date: Thu Nov  1 09:48:52 2012
New Revision: 1404521

URL: http://svn.apache.org/viewvc?rev=1404521&view=rev
Log:
QPID-4390: WIP - Add ConfigurationEntryStore, implement XMLConfigurationEntryStore for existing broker XML configuration, add Recoverers to recover broker configured objects from the store

Added:
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/CustomRMIServerSocketFactory.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameAccessor.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameCachingRMIJRMPServer.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporterTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerLauncher.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationEntry.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationEntryStore.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationEntryStoreException.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/IllegalConfigurationException.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AttributeMap.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/PortRecoverer.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/VirtualHostRecoverer.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/PortConfigurationHelper.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/XMLConfigurationEntryStore.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObjectType.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactory.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAttributeDestringifier.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/AmqpPortAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/PortConfigurationHelperTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactoryTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortAttributeDestringifierTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/model/configuration/
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/model/configuration/ConfigurationEntryTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/TestAuthenticationManagerFactory.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/resources/
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/resources/META-INF/
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/resources/META-INF/services/
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.AuthenticationManagerFactory
Removed:
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogActorTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistryTest.java
Modified:
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/GroupProvider.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/AuthenticationManagerFactory.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerFactory.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerFactory.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManagerFactory.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthManagerFactory.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactory.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupPrincipalAccessor.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthManagerFactoryTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/GroupPrincipalAccessorTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/module.xml
    qpid/branches/java-broker-config-qpid-4390/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java
    qpid/branches/java-broker-config-qpid-4390/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java

Modified: qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
URL: http://svn.apache.org/viewvc/qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java?rev=1404521&r1=1404520&r2=1404521&view=diff
==============================================================================
--- qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java (original)
+++ qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java Thu Nov  1 09:48:52 2012
@@ -21,8 +21,9 @@
 package org.apache.qpid.server.management.plugin;
 
 import java.io.File;
-import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.log4j.Logger;
@@ -50,7 +51,7 @@ import org.apache.qpid.server.model.Port
 import org.apache.qpid.server.model.Protocol;
 import org.apache.qpid.server.model.Queue;
 import org.apache.qpid.server.model.Session;
-import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.server.model.State;
 import org.apache.qpid.server.model.User;
 import org.apache.qpid.server.model.VirtualHost;
 import org.eclipse.jetty.server.Connector;
@@ -72,79 +73,135 @@ public class HttpManagement implements M
 
     private final Broker _broker;
 
-    private final Collection<Server> _servers = new ArrayList<Server>();
+    private final Map<Integer, Server> _servers = new ConcurrentHashMap<Integer, Server>();
 
-    private final String _keyStorePassword;
-    private final String _keyStorePath;
-    private final int _sessionTimeout;
+    private String _keyStorePassword;
+    private String _keyStorePath;
+    private int _sessionTimeout;
 
+    // XXX refactor back to use a single instance of server and add connectors for different ports
     public HttpManagement(Broker broker, String keyStorePath, String keyStorePassword, int sessionTimeout) throws ConfigurationException
     {
         _broker = broker;
         _keyStorePassword = keyStorePassword;
         _keyStorePath = keyStorePath;
         _sessionTimeout = sessionTimeout;
+    }
+
+    @Override
+    public void start() throws Exception
+    {
+        CurrentActor.get().message(ManagementConsoleMessages.STARTUP(OPERATIONAL_LOGGING_NAME));
 
-        Collection<Port> ports = broker.getPorts();
-        int httpPort = -1, httpsPort = -1;
+        Collection<Port> ports = _broker.getPorts();
         for (Port port : ports)
         {
-            if (port.getProtocols().contains(Protocol.HTTP))
+            if (isManagementHttp(port))
             {
-                if (port.getTransports().contains(Transport.TCP))
+                if(port.getActualState() == State.ACTIVE)
                 {
-                    httpPort = port.getPort();
-                }
-            }
-            if (port.getProtocols().contains(Protocol.HTTPS))
-            {
-                if (port.getTransports().contains(Transport.SSL))
-                {
-                    httpsPort = port.getPort();
+                    startServer(port);
                 }
             }
         }
 
-        if (httpPort != -1 || httpsPort != -1)
+        CurrentActor.get().message(ManagementConsoleMessages.READY(OPERATIONAL_LOGGING_NAME));
+    }
+
+    @Override
+    public void stop() throws Exception
+    {
+        Collection<Port> ports = _broker.getPorts();
+        for (Port port : ports)
         {
-            _servers.add(createServer(httpPort, httpsPort));
-            if (_logger.isDebugEnabled())
+            if (isManagementHttp(port))
             {
-                _logger.debug(_servers.size() + " server(s) defined");
+                stopServer(port);
             }
         }
-        else
+        CurrentActor.get().message(ManagementConsoleMessages.STOPPED(OPERATIONAL_LOGGING_NAME));
+    }
+
+    /** Added for testing purposes */
+    Broker getBroker()
+    {
+        return _broker;
+    }
+
+    /** Added for testing purposes */
+    String getKeyStorePassword()
+    {
+        return _keyStorePassword;
+    }
+
+    /** Added for testing purposes */
+    String getKeyStorePath()
+    {
+        return _keyStorePath;
+    }
+
+    /** Added for testing purposes */
+    int getSessionTimeout()
+    {
+        return _sessionTimeout;
+    }
+
+    protected void stopServer(Port port)
+    {
+        Server server = _servers.remove(port.getPort());
+        if (server != null)
         {
-            if (_logger.isInfoEnabled())
+            try
+            {
+                server.stop();
+                logOperationalShutdownMessage(server);
+            }
+            catch (Exception e)
             {
-                _logger.info("Cannot create web server as neither HTTP nor HTTPS port specified");
+                throw new RuntimeException("Failed to stop http management on port " + port.getPort());
             }
         }
     }
 
+    private void startServer(Port port)
+    {
+        Server server = createServer(port);
+        try
+        {
+            server.start();
+
+            logOperationalListenMessages(server);
+
+            _servers.put(port.getPort(), server);
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException("Failed to start http management on port " + port.getPort());
+        }
+    }
+
+    private boolean isManagementHttp(Port port)
+    {
+        return port.getProtocols().contains(Protocol.HTTP) || port.getProtocols().contains(Protocol.HTTPS);
+    }
+
     @SuppressWarnings("unchecked")
-    private Server createServer(int port, int sslPort) throws ConfigurationException
+    private Server createServer(Port port)
     {
         if (_logger.isInfoEnabled())
         {
-            _logger.info("Starting up web server on" + (port == -1 ? "" : " HTTP port " + port)
-                    + (sslPort == -1 ? "" : " HTTPS port " + sslPort));
+            _logger.info("Starting up web server on " + port.getPort());
         }
 
         Server server = new Server();
 
-        if (port != -1)
+        final Collection<Protocol> protocols = port.getProtocols();
+        Connector connector = null;
+        if (protocols.contains(Protocol.HTTP))
         {
-            SelectChannelConnector connector = new SelectChannelConnector();
-            connector.setPort(port);
-            if (sslPort != -1)
-            {
-                connector.setConfidentialPort(sslPort);
-            }
-            server.addConnector(connector);
+            connector = new SelectChannelConnector();
         }
-
-        if (sslPort != -1)
+        else if (protocols.contains(Protocol.HTTPS))
         {
             checkKeyStorePath(_keyStorePath);
 
@@ -152,10 +209,14 @@ public class HttpManagement implements M
             factory.setKeyStorePath(_keyStorePath);
             factory.setKeyStorePassword(_keyStorePassword);
 
-            SslSocketConnector connector = new SslSocketConnector(factory);
-            connector.setPort(sslPort);
-            server.addConnector(connector);
+            connector = new SslSocketConnector(factory);
         }
+        else
+        {
+            throw new IllegalArgumentException("Unexpected protocol " + protocols);
+        }
+        connector.setPort(port.getPort());
+        server.addConnector(connector);
 
         ServletContextHandler root = new ServletContextHandler(ServletContextHandler.SESSIONS);
         root.setContextPath("/");
@@ -209,50 +270,22 @@ public class HttpManagement implements M
         root.addServlet(new ServletHolder(new RestServlet(_broker, hierarchy)), "/rest/" + name + "/*");
     }
 
-    @Override
-    public void start() throws Exception
-    {
-        CurrentActor.get().message(ManagementConsoleMessages.STARTUP(OPERATIONAL_LOGGING_NAME));
-
-        for (Server server : _servers)
-        {
-            server.start();
-
-            logOperationalListenMessages(server);
-        }
-
-        CurrentActor.get().message(ManagementConsoleMessages.READY(OPERATIONAL_LOGGING_NAME));
-    }
-
-    @Override
-    public void stop() throws Exception
-    {
-        for (Server server : _servers)
-        {
-            logOperationalShutdownMessage(server);
-
-            server.stop();
-        }
-
-        CurrentActor.get().message(ManagementConsoleMessages.STOPPED(OPERATIONAL_LOGGING_NAME));
-    }
-
-    private void checkKeyStorePath(String keyStorePath) throws ConfigurationException
+    private void checkKeyStorePath(String keyStorePath)
     {
         if (keyStorePath == null)
         {
-            throw new ConfigurationException("Management SSL keystore path not defined, unable to start SSL protected HTTP connector");
+            throw new RuntimeException("Management SSL keystore path not defined, unable to start SSL protected HTTP connector");
         }
         else
         {
             File ksf = new File(keyStorePath);
             if (!ksf.exists())
             {
-                throw new ConfigurationException("Cannot find management SSL keystore file: " + ksf);
+                throw new RuntimeException("Cannot find management SSL keystore file: " + ksf);
             }
             if (!ksf.canRead())
             {
-                throw new ConfigurationException("Cannot read management SSL keystore file: " + ksf + ". Check permissions.");
+                throw new RuntimeException("Cannot read management SSL keystore file: " + ksf + ". Check permissions.");
             }
         }
     }
@@ -287,28 +320,4 @@ public class HttpManagement implements M
     {
         return connector instanceof SslSocketConnector ? "HTTPS" : "HTTP";
     }
-
-    /** Added for testing purposes */
-    Broker getBroker()
-    {
-        return _broker;
-    }
-
-    /** Added for testing purposes */
-    String getKeyStorePassword()
-    {
-        return _keyStorePassword;
-    }
-
-    /** Added for testing purposes */
-    String getKeyStorePath()
-    {
-        return _keyStorePath;
-    }
-
-    /** Added for testing purposes */
-    int getSessionTimeout()
-    {
-        return _sessionTimeout;
-    }
 }

Added: qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/CustomRMIServerSocketFactory.java
URL: http://svn.apache.org/viewvc/qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/CustomRMIServerSocketFactory.java?rev=1404521&view=auto
==============================================================================
--- qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/CustomRMIServerSocketFactory.java (added)
+++ qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/CustomRMIServerSocketFactory.java Thu Nov  1 09:48:52 2012
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.jmx;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.rmi.server.RMIServerSocketFactory;
+
+/**
+ * Custom RMIServerSocketFactory class, used to prevent updates to the RMI registry.
+ * Supplied to the registry at creation, this will prevent RMI-based operations on the
+ * registry such as attempting to bind a new object, thereby securing it from tampering.
+ * This is accomplished by always returning null when attempting to determine the address
+ * of the caller, thus ensuring the registry will refuse the attempt. Calls to bind etc
+ * made using the object reference will not be affected and continue to operate normally.
+ */
+class CustomRMIServerSocketFactory implements RMIServerSocketFactory
+{
+
+    public ServerSocket createServerSocket(int port) throws IOException
+    {
+        return new NoLocalAddressServerSocket(port);
+    }
+
+    private static class NoLocalAddressServerSocket extends ServerSocket
+    {
+        NoLocalAddressServerSocket(int port) throws IOException
+        {
+            super(port);
+        }
+
+        @Override
+        public Socket accept() throws IOException
+        {
+            Socket s = new NoLocalAddressSocket();
+            super.implAccept(s);
+            return s;
+        }
+    }
+
+    private static class NoLocalAddressSocket extends Socket
+    {
+        @Override
+        public InetAddress getInetAddress()
+        {
+            return null;
+        }
+    }
+}
\ No newline at end of file

Modified: qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java
URL: http://svn.apache.org/viewvc/qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java?rev=1404521&r1=1404520&r2=1404521&view=diff
==============================================================================
--- qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java (original)
+++ qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java Thu Nov  1 09:48:52 2012
@@ -26,50 +26,40 @@ import org.apache.qpid.AMQException;
 import org.apache.qpid.server.configuration.ServerConfiguration;
 import org.apache.qpid.server.logging.actors.CurrentActor;
 import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
-
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Transport;
 
 import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
+import org.apache.qpid.server.registry.IApplicationRegistry;
 import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator;
 import javax.management.JMException;
 import javax.management.MBeanServer;
 import javax.management.MBeanServerFactory;
-import javax.management.Notification;
-import javax.management.NotificationFilterSupport;
-import javax.management.NotificationListener;
 import javax.management.ObjectName;
-import javax.management.remote.JMXConnectionNotification;
 import javax.management.remote.JMXConnectorServer;
 import javax.management.remote.JMXServiceURL;
 import javax.management.remote.MBeanServerForwarder;
-import javax.management.remote.rmi.RMIConnection;
 import javax.management.remote.rmi.RMIConnectorServer;
-import javax.management.remote.rmi.RMIJRMPServerImpl;
-import javax.management.remote.rmi.RMIServerImpl;
 import javax.rmi.ssl.SslRMIClientSocketFactory;
 import javax.rmi.ssl.SslRMIServerSocketFactory;
-import javax.security.auth.Subject;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.lang.management.ManagementFactory;
-import java.lang.reflect.Proxy;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
+import java.net.MalformedURLException;
 import java.net.UnknownHostException;
 import java.rmi.AlreadyBoundException;
 import java.rmi.NoSuchObjectException;
 import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
 import java.rmi.registry.LocateRegistry;
 import java.rmi.registry.Registry;
 import java.rmi.server.RMIClientSocketFactory;
 import java.rmi.server.RMIServerSocketFactory;
 import java.rmi.server.UnicastRemoteObject;
 import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * This class starts up an MBeanserver. If out of the box agent has been enabled then there are no
@@ -82,20 +72,21 @@ public class JMXManagedObjectRegistry im
     private static final String OPERATIONAL_LOGGING_NAME = "JMX";
 
     private final MBeanServer _mbeanServer;
+    private final boolean _useCustomSocketFactory;
+    private final ServerConfiguration _serverConfiguration;
+
     private JMXConnectorServer _cs;
     private Registry _rmiRegistry;
-    private boolean _useCustomSocketFactory;
 
-    private final int _jmxPortRegistryServer;
-    private final int _jmxPortConnectorServer;
-
-    private final ServerConfiguration _serverConfiguration;
+    private Port _registryPort;
+    private Port _connectorPort;
 
-    public JMXManagedObjectRegistry(ServerConfiguration serverConfiguration) throws AMQException
+    // XXX get rid from ServerConfiguration
+    public JMXManagedObjectRegistry(ServerConfiguration serverConfiguration, Port connectorPort, Port registryPort) throws AMQException
     {
-        _log.info("Initialising managed object registry using platform MBean server");
-
         _serverConfiguration = serverConfiguration;
+        _registryPort = registryPort;
+        _connectorPort = connectorPort;
 
         // Retrieve the config parameters
         _useCustomSocketFactory = _serverConfiguration.getUseCustomRMISocketFactory();
@@ -104,11 +95,9 @@ public class JMXManagedObjectRegistry im
         _mbeanServer =
                 platformServer ? ManagementFactory.getPlatformMBeanServer()
                 : MBeanServerFactory.createMBeanServer(ManagedObject.DOMAIN);
-
-        _jmxPortRegistryServer = _serverConfiguration.getJMXPortRegistryServer();
-        _jmxPortConnectorServer = _serverConfiguration.getJMXConnectorServerPort();
     }
 
+    @Override
     public void start() throws IOException, ConfigurationException
     {
         CurrentActor.get().message(ManagementConsoleMessages.STARTUP(OPERATIONAL_LOGGING_NAME));
@@ -117,48 +106,33 @@ public class JMXManagedObjectRegistry im
         if (areOutOfTheBoxJMXOptionsSet())
         {
             CurrentActor.get().message(ManagementConsoleMessages.READY(OPERATIONAL_LOGGING_NAME));
-            return;
         }
+        else
+        {
+            startRegistryAndConnector();
+        }
+    }
 
-        //Socket factories for the RMIConnectorServer, either default or SLL depending on configuration
+    private void startRegistryAndConnector() throws ConfigurationException,
+            FileNotFoundException, RemoteException, IOException,
+            MalformedURLException
+    {
+        //Socket factories for the RMIConnectorServer, either default or SSL depending on configuration
         RMIClientSocketFactory csf;
         RMIServerSocketFactory ssf;
 
-        //check ssl enabled option in config, default to true if option is not set
-        boolean sslEnabled = _serverConfiguration.getManagementSSLEnabled();
+        //check ssl enabled option on connector port (note we don't provide ssl for registry server at
+        //moment).
+        boolean connectorSslEnabled = _connectorPort.getTransports().contains(Transport.SSL);
 
-        if (sslEnabled)
+        if (connectorSslEnabled)
         {
             //set the SSL related system properties used by the SSL RMI socket factories to the values
             //given in the configuration file
             String keyStorePath = _serverConfiguration.getManagementKeyStorePath();
+            checkKeyStorePathExistsAndIsReadable(keyStorePath);
 
-            //check the keystore path value is valid
-            if (keyStorePath == null)
-            {
-                throw new ConfigurationException("JMX management SSL keystore path not defined, " +
-                                                 "unable to start SSL protected JMX ConnectorServer");
-            }
-            else
-            {
-                //ensure the system property is set (for use by SslRMIClientSocketFactory and SslRMIServerSocketFactory)
-                System.setProperty("javax.net.ssl.keyStore", keyStorePath);
-
-                //check the file is usable
-                File ksf = new File(keyStorePath);
-
-                if (!ksf.exists())
-                {
-                    throw new FileNotFoundException("Cannot find JMX management SSL keystore file: " + ksf);
-                }
-                if (!ksf.canRead())
-                {
-                    throw new FileNotFoundException("Cannot read JMX management SSL keystore file: "
-                                                    + ksf +  ". Check permissions.");
-                }
-
-                CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(ksf.getAbsolutePath()));
-            }
+            CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(keyStorePath));
 
             if (_serverConfiguration.getManagementKeyStorePassword() == null)
             {
@@ -167,8 +141,7 @@ public class JMXManagedObjectRegistry im
             }
             else
             {
-               System.setProperty("javax.net.ssl.keyStorePassword",
-                       _serverConfiguration.getManagementKeyStorePassword());
+               System.setProperty("javax.net.ssl.keyStorePassword", _serverConfiguration.getManagementKeyStorePassword());
             }
 
             //create the SSL RMI socket factories
@@ -182,10 +155,14 @@ public class JMXManagedObjectRegistry im
             ssf = null;
         }
 
+        int jmxPortRegistryServer = _registryPort.getPort();
+        int jmxPortConnectorServer = _connectorPort.getPort();
+
         //add a JMXAuthenticator implementation the env map to authenticate the RMI based JMX connector server
-        RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator(ApplicationRegistry.getInstance(), new InetSocketAddress(_jmxPortRegistryServer));
-        HashMap<String,Object> env = new HashMap<String,Object>();
-        env.put(JMXConnectorServer.AUTHENTICATOR, rmipa);
+        final IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
+        RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator(appRegistry, new InetSocketAddress(jmxPortRegistryServer));
+        HashMap<String,Object> connectorEnv = new HashMap<String,Object>();
+        connectorEnv.put(JMXConnectorServer.AUTHENTICATOR, rmipa);
 
         /*
          * Start a RMI registry on the management port, to hold the JMX RMI ConnectorServer stub.
@@ -193,18 +170,7 @@ public class JMXManagedObjectRegistry im
          * As a result, only binds made using the object reference will succeed, thus securing it from external change.
          */
         System.setProperty("java.rmi.server.randomIDs", "true");
-        if(_useCustomSocketFactory)
-        {
-            _log.debug("Using custom RMIServerSocketFactory");
-            _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, new CustomRMIServerSocketFactory());
-        }
-        else
-        {
-            _log.debug("Using default RMIServerSocketFactory");
-            _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, null);
-        }
-
-        CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", _jmxPortRegistryServer));
+        _rmiRegistry = createRmiRegistry(jmxPortRegistryServer, _useCustomSocketFactory);
 
         /*
          * We must now create the RMI ConnectorServer manually, as the JMX Factory methods use RMI calls
@@ -212,57 +178,16 @@ public class JMXManagedObjectRegistry im
          * locked it from any RMI based modifications, including our own. Instead, we will manually bind
          * the RMIConnectorServer stub to the registry using its object reference, which will still succeed.
          *
-         * The registry is exported on the defined management port 'port'. We will export the RMIConnectorServer
-         * on 'port +1'. Use of these two well-defined ports will ease any navigation through firewall's.
+         * The registry is exported on the defined management port 'port'.
          */
-        final Map<String, String> connectionIdUsernameMap = new ConcurrentHashMap<String, String>();
-        final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(_jmxPortConnectorServer, csf, ssf, env)
-        {
+        final UsernameCachingRMIJRMPServer usernameCachingRmiServer = new UsernameCachingRMIJRMPServer(jmxPortConnectorServer, csf, ssf, connectorEnv);
 
-            /**
-             * Override makeClient so we can cache the username of the client in a Map keyed by connectionId.
-             * ConnectionId is guaranteed to be unique per client connection, according to the JMX spec.
-             * An instance of NotificationListener (mapCleanupListener) will be responsible for removing these Map
-             * entries.
-             *
-             * @see javax.management.remote.rmi.RMIJRMPServerImpl#makeClient(String, javax.security.auth.Subject)
-             */
-            @Override
-            protected RMIConnection makeClient(String connectionId, Subject subject) throws IOException
-            {
-                final RMIConnection makeClient = super.makeClient(connectionId, subject);
-                final AuthenticatedPrincipal authenticatedPrincipalFromSubject = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject);
-                connectionIdUsernameMap.put(connectionId, authenticatedPrincipalFromSubject.getName());
-                return makeClient;
-            }
-        };
-
-        // Create a Listener responsible for removing the map entries add by the #makeClient entry above.
-        final NotificationListener mapCleanupListener = new NotificationListener()
-        {
-
-            public void handleNotification(Notification notification, Object handback)
-            {
-                final String connectionId = ((JMXConnectionNotification) notification).getConnectionId();
-                connectionIdUsernameMap.remove(connectionId);
-            }
-        };
-
-        String localHost;
-        try
-        {
-            localHost = InetAddress.getLocalHost().getHostName();
-        }
-        catch(UnknownHostException ex)
-        {
-            localHost="127.0.0.1";
-        }
-        final String hostname = localHost;
+        final String localHostName = getLocalhost();
         final JMXServiceURL externalUrl = new JMXServiceURL(
-                "service:jmx:rmi://"+hostname+":"+(_jmxPortConnectorServer)+"/jndi/rmi://"+hostname+":"+_jmxPortRegistryServer+"/jmxrmi");
+                "service:jmx:rmi://"+localHostName+":"+(jmxPortConnectorServer)+"/jndi/rmi://"+localHostName+":"+jmxPortRegistryServer+"/jmxrmi");
 
-        final JMXServiceURL internalUrl = new JMXServiceURL("rmi", hostname, _jmxPortConnectorServer);
-        _cs = new RMIConnectorServer(internalUrl, env, rmiConnectorServerStub, _mbeanServer)
+        final JMXServiceURL internalUrl = new JMXServiceURL("rmi", localHostName, jmxPortConnectorServer);
+        _cs = new RMIConnectorServer(internalUrl, connectorEnv, usernameCachingRmiServer, _mbeanServer)
         {
             @Override
             public synchronized void start() throws IOException
@@ -270,7 +195,7 @@ public class JMXManagedObjectRegistry im
                 try
                 {
                     //manually bind the connector server to the registry at key 'jmxrmi', like the out-of-the-box agent
-                    _rmiRegistry.bind("jmxrmi", rmiConnectorServerStub);
+                    _rmiRegistry.bind("jmxrmi", usernameCachingRmiServer);
                 }
                 catch (AlreadyBoundException abe)
                 {
@@ -298,7 +223,6 @@ public class JMXManagedObjectRegistry im
                 }
                 catch (NotBoundException nbe)
                 {
-                    // TODO consider if we want to keep new logging
                     _log.error("Failed to unbind jmxrmi", nbe);
                     //ignore
                 }
@@ -313,97 +237,104 @@ public class JMXManagedObjectRegistry im
                 //must return our pre-crafted url that includes the full details, inc JNDI details
                 return externalUrl;
             }
-
         };
 
-
         //Add the custom invoker as an MBeanServerForwarder, and start the RMIConnectorServer.
         MBeanServerForwarder mbsf = MBeanInvocationHandlerImpl.newProxyInstance();
         _cs.setMBeanServerForwarder(mbsf);
 
+        // Install a ManagementLogonLogoffReporter so we can report as users logon/logoff
+        ManagementLogonLogoffReporter jmxManagementUserLogonLogoffReporter = new ManagementLogonLogoffReporter(appRegistry.getRootMessageLogger(), usernameCachingRmiServer);
+        _cs.addNotificationListener(jmxManagementUserLogonLogoffReporter, jmxManagementUserLogonLogoffReporter, null);
 
-        // Get the handler that is used by the above MBInvocationHandler Proxy.
-        // which is the MBeanInvocationHandlerImpl and so also a NotificationListener.
-        final NotificationListener invocationHandler = (NotificationListener) Proxy.getInvocationHandler(mbsf);
-
-        // Install a notification listener on OPENED, CLOSED, and FAILED,
-        // passing the map of connection-ids to usernames as hand-back data.
-        final NotificationFilterSupport invocationHandlerFilter = new NotificationFilterSupport();
-        invocationHandlerFilter.enableType(JMXConnectionNotification.OPENED);
-        invocationHandlerFilter.enableType(JMXConnectionNotification.CLOSED);
-        invocationHandlerFilter.enableType(JMXConnectionNotification.FAILED);
-        _cs.addNotificationListener(invocationHandler, invocationHandlerFilter, connectionIdUsernameMap);
-
-        // Install a second notification listener on CLOSED AND FAILED only to remove the entry from the
-        // Map.  Here we rely on the fact that JMX will call the listeners in the order in which they are
-        // installed.
-        final NotificationFilterSupport mapCleanupHandlerFilter = new NotificationFilterSupport();
-        mapCleanupHandlerFilter.enableType(JMXConnectionNotification.CLOSED);
-        mapCleanupHandlerFilter.enableType(JMXConnectionNotification.FAILED);
-        _cs.addNotificationListener(mapCleanupListener, mapCleanupHandlerFilter, null);
+        // Install the usernameCachingRmiServer as a listener so it may cleanup as clients disconnect
+        _cs.addNotificationListener(usernameCachingRmiServer, usernameCachingRmiServer, null);
 
         _cs.start();
 
-        String connectorServer = (sslEnabled ? "SSL " : "") + "JMX RMIConnectorServer";
-        CurrentActor.get().message(ManagementConsoleMessages.LISTENING(connectorServer, _jmxPortConnectorServer));
-
+        String connectorServer = (connectorSslEnabled ? "SSL " : "") + "JMX RMIConnectorServer";
+        CurrentActor.get().message(ManagementConsoleMessages.LISTENING(connectorServer, jmxPortConnectorServer));
         CurrentActor.get().message(ManagementConsoleMessages.READY(OPERATIONAL_LOGGING_NAME));
     }
 
-    /*
-     * Custom RMIServerSocketFactory class, used to prevent updates to the RMI registry.
-     * Supplied to the registry at creation, this will prevent RMI-based operations on the
-     * registry such as attempting to bind a new object, thereby securing it from tampering.
-     * This is accomplished by always returning null when attempting to determine the address
-     * of the caller, thus ensuring the registry will refuse the attempt. Calls to bind etc
-     * made using the object reference will not be affected and continue to operate normally.
-     */
-
-    private static class CustomRMIServerSocketFactory implements RMIServerSocketFactory
+    private Registry createRmiRegistry(int jmxPortRegistryServer, boolean useCustomRmiRegistry)
+            throws RemoteException
     {
-
-        public ServerSocket createServerSocket(int port) throws IOException
+        Registry rmiRegistry;
+        if(useCustomRmiRegistry)
         {
-            return new NoLocalAddressServerSocket(port);
+            _log.debug("Using custom RMIServerSocketFactory");
+            rmiRegistry = LocateRegistry.createRegistry(jmxPortRegistryServer, null, new CustomRMIServerSocketFactory());
         }
+        else
+        {
+            _log.debug("Using default RMIServerSocketFactory");
+            rmiRegistry = LocateRegistry.createRegistry(jmxPortRegistryServer, null, null);
+        }
+
+        CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", jmxPortRegistryServer));
+        return rmiRegistry;
+    }
 
-        private static class NoLocalAddressServerSocket extends ServerSocket
+    private void checkKeyStorePathExistsAndIsReadable(String keyStorePath)
+            throws ConfigurationException, FileNotFoundException
+    {
+        //check the keystore path value is valid
+        if (keyStorePath == null)
         {
-            NoLocalAddressServerSocket(int port) throws IOException
-            {
-                super(port);
-            }
+            throw new ConfigurationException("JMX management SSL keystore path not defined, " +
+                                             "unable to start SSL protected JMX ConnectorServer");
+        }
+        else
+        {
+            //ensure the system property is set (for use by SslRMIClientSocketFactory and SslRMIServerSocketFactory)
+            System.setProperty("javax.net.ssl.keyStore", keyStorePath);
 
-            @Override
-            public Socket accept() throws IOException
+            //check the file is usable
+            File ksf = new File(keyStorePath);
+
+            if (!ksf.exists())
             {
-                Socket s = new NoLocalAddressSocket();
-                super.implAccept(s);
-                return s;
+                throw new FileNotFoundException("Cannot find JMX management SSL keystore file: " + ksf);
             }
-        }
-
-        private static class NoLocalAddressSocket extends Socket
-        {
-            @Override
-            public InetAddress getInetAddress()
+            if (!ksf.canRead())
             {
-                return null;
+                throw new FileNotFoundException("Cannot read JMX management SSL keystore file: "
+                                                + ksf +  ". Check permissions.");
             }
         }
     }
 
-
+    @Override
     public void registerObject(ManagedObject managedObject) throws JMException
     {
         _mbeanServer.registerMBean(managedObject, managedObject.getObjectName());
     }
 
+    @Override
     public void unregisterObject(ManagedObject managedObject) throws JMException
     {
         _mbeanServer.unregisterMBean(managedObject.getObjectName());
     }
 
+    @Override
+    public void close()
+    {
+        _log.debug("close() called");
+
+        closeConnectorAndRegistryServers();
+
+        unregisterAllMbeans();
+
+        CurrentActor.get().message(ManagementConsoleMessages.STOPPED(OPERATIONAL_LOGGING_NAME));
+    }
+
+    private void closeConnectorAndRegistryServers()
+    {
+        closeConnectorServer();
+        closeRegistryServer();
+    }
+
     // checks if the system properties are set which enable the JVM's out-of-the-box JMXAgent.
     private boolean areOutOfTheBoxJMXOptionsSet()
     {
@@ -420,29 +351,26 @@ public class JMXManagedObjectRegistry im
         return false;
     }
 
-    //Stops the JMXConnectorServer and RMIRegistry, then unregisters any remaining MBeans from the MBeanServer
-    public void close()
+    private String getLocalhost()
     {
-        _log.debug("close() called");
-
-        if (_cs != null)
+        String localHost;
+        try
         {
-            // Stopping the JMX ConnectorServer
-            try
-            {
-                CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("JMX RMIConnectorServer", _cs.getAddress().getPort()));
-                _cs.stop();
-            }
-            catch (IOException e)
-            {
-                _log.error("Exception while closing the JMX ConnectorServer: ",  e);
-            }
+            localHost = InetAddress.getLocalHost().getHostName();
         }
+        catch(UnknownHostException ex)
+        {
+            localHost="127.0.0.1";
+        }
+        return localHost;
+    }
 
+    private void closeRegistryServer()
+    {
         if (_rmiRegistry != null)
         {
             // Stopping the RMI registry
-            CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _jmxPortRegistryServer));
+            CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _registryPort.getPort()));
             try
             {
                 boolean success = UnicastRemoteObject.unexportObject(_rmiRegistry, false);
@@ -455,8 +383,36 @@ public class JMXManagedObjectRegistry im
             {
                 _log.error("Exception while closing the RMI Registry: ", e);
             }
+            finally
+            {
+                _rmiRegistry = null;
+            }
+        }
+    }
+
+    private void closeConnectorServer()
+    {
+        if (_cs != null)
+        {
+            // Stopping the JMX ConnectorServer
+            try
+            {
+                CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("JMX RMIConnectorServer", _cs.getAddress().getPort()));
+                _cs.stop();
+            }
+            catch (IOException e)
+            {
+                _log.error("Exception while closing the JMX ConnectorServer: ",  e);
+            }
+            finally
+            {
+                _cs = null;
+            }
         }
+    }
 
+    private void unregisterAllMbeans()
+    {
         //ObjectName query to gather all Qpid related MBeans
         ObjectName mbeanNameQuery = null;
         try
@@ -479,8 +435,6 @@ public class JMXManagedObjectRegistry im
                 _log.error("Exception unregistering MBean '"+ name +"': " + e.getMessage());
             }
         }
-
-        CurrentActor.get().message(ManagementConsoleMessages.STOPPED(OPERATIONAL_LOGGING_NAME));
     }
 
 }

Modified: qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java
URL: http://svn.apache.org/viewvc/qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java?rev=1404521&r1=1404520&r2=1404521&view=diff
==============================================================================
--- qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java (original)
+++ qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java Thu Nov  1 09:48:52 2012
@@ -21,6 +21,7 @@
 
 package org.apache.qpid.server.jmx;
 
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 import javax.management.JMException;
@@ -35,10 +36,13 @@ import org.apache.qpid.server.jmx.mbeans
 import org.apache.qpid.server.jmx.mbeans.VirtualHostMBean;
 import org.apache.qpid.server.logging.log4j.LoggingManagementFacade;
 import org.apache.qpid.server.management.plugin.ManagementPlugin;
+import org.apache.qpid.server.model.AuthenticationProvider;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.ConfigurationChangeListener;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Protocol;
 import org.apache.qpid.server.model.State;
 import org.apache.qpid.server.model.VirtualHost;
 import org.apache.qpid.server.plugin.QpidServiceLoader;
@@ -47,6 +51,9 @@ public class JMXManagement implements Co
 {
     private static final Logger LOGGER = Logger.getLogger(JMXManagement.class);
 
+    private static final String REGISTRY_PORT_NAME = "registry";
+    private static final String CONNECTOR_PORT_NAME = "connector";
+
     private final Broker _broker;
     private JMXManagedObjectRegistry _objectRegistry;
 
@@ -63,16 +70,56 @@ public class JMXManagement implements Co
     @Override
     public void start() throws Exception
     {
-        _objectRegistry = new JMXManagedObjectRegistry(_serverConfiguration);
+        Port connectorPort = null;
+        Port registryPort = null;
+        Collection<Port> ports = _broker.getPorts();
+        for (Port port : ports)
+        {
+            if (port.getProtocols().contains(Protocol.JMX_RMI))
+            {
+                if(REGISTRY_PORT_NAME.equals(port.getName()))
+                {
+                    registryPort = port;
+                }
+                else if(CONNECTOR_PORT_NAME.equals(port.getName()))
+                {
+                    connectorPort = port;
+                }
+            }
+        }
+        if(connectorPort == null)
+        {
+            throw new IllegalStateException("No JMX port found with name " + CONNECTOR_PORT_NAME);
+        }
+        if(registryPort == null)
+        {
+            throw new IllegalStateException("No JMX port found with name " + REGISTRY_PORT_NAME);
+        }
+
+        //XXX review MBean creation process
+        _objectRegistry = new JMXManagedObjectRegistry(_serverConfiguration, connectorPort, registryPort);
 
         _broker.addChangeListener(this);
+
         synchronized (_children)
         {
             for(VirtualHost virtualHost : _broker.getVirtualHosts())
             {
                 if(!_children.containsKey(virtualHost))
                 {
-                    _children.put(virtualHost, new VirtualHostMBean(virtualHost, _objectRegistry));
+                    VirtualHostMBean mbean = new VirtualHostMBean(virtualHost, _objectRegistry);
+                    createAdditionalMBeansFromProviders(virtualHost, mbean);
+                }
+            }
+            Collection<AuthenticationProvider> authenticationProviders = _broker.getAuthenticationProviders();
+            for (AuthenticationProvider authenticationProvider : authenticationProviders)
+            {
+                if(authenticationProvider instanceof PasswordCredentialManagingAuthenticationProvider)
+                {
+                    UserManagementMBean mbean = new UserManagementMBean(
+                            (PasswordCredentialManagingAuthenticationProvider) authenticationProvider,
+                            _objectRegistry);
+                    _children.put(authenticationProvider, mbean);
                 }
             }
         }
@@ -86,16 +133,37 @@ public class JMXManagement implements Co
     @Override
     public void stop()
     {
+        synchronized (_children)
+        {
+            for(ConfiguredObject object : _children.keySet())
+            {
+                AMQManagedObject mbean = _children.get(object);
+                if (mbean instanceof ConfigurationChangeListener)
+                {
+                    object.removeChangeListener((ConfigurationChangeListener)mbean);
+                }
+                try
+                {
+                    mbean.unregister();
+                }
+                catch (JMException e)
+                {
+                    LOGGER.error("Error unregistering mbean", e);
+                }
+            }
+            _children.clear();
+        }
         _broker.removeChangeListener(this);
-
         _objectRegistry.close();
     }
 
+    @Override
     public void stateChanged(ConfiguredObject object, State oldState, State newState)
     {
-
+        // no-op
     }
 
+    @Override
     public void childAdded(ConfiguredObject object, ConfiguredObject child)
     {
         synchronized (_children)
@@ -130,7 +198,7 @@ public class JMXManagement implements Co
         }
     }
 
-
+    @Override
     public void childRemoved(ConfiguredObject object, ConfiguredObject child)
     {
         // TODO - implement vhost removal (possibly just removing the instanceof check below)

Modified: qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
URL: http://svn.apache.org/viewvc/qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java?rev=1404521&r1=1404520&r2=1404521&view=diff
==============================================================================
--- qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java (original)
+++ qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java Thu Nov  1 09:48:52 2012
@@ -22,10 +22,8 @@ package org.apache.qpid.server.jmx;
 
 import org.apache.log4j.Logger;
 
-import org.apache.qpid.server.logging.LogActor;
 import org.apache.qpid.server.logging.actors.CurrentActor;
 import org.apache.qpid.server.logging.actors.ManagementActor;
-import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
 import org.apache.qpid.server.registry.ApplicationRegistry;
 import org.apache.qpid.server.registry.IApplicationRegistry;
 import org.apache.qpid.server.security.SecurityManager;
@@ -37,11 +35,8 @@ import javax.management.JMException;
 import javax.management.MBeanInfo;
 import javax.management.MBeanOperationInfo;
 import javax.management.MBeanServer;
-import javax.management.Notification;
-import javax.management.NotificationListener;
 import javax.management.ObjectName;
 import javax.management.RuntimeErrorException;
-import javax.management.remote.JMXConnectionNotification;
 import javax.management.remote.MBeanServerForwarder;
 import javax.security.auth.Subject;
 import java.lang.reflect.InvocationHandler;
@@ -51,13 +46,12 @@ import java.lang.reflect.Proxy;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.util.Arrays;
-import java.util.Map;
 
 /**
  * This class can be used by the JMXConnectorServer as an InvocationHandler for the mbean operations. It delegates
  * JMX access decisions to the SecurityPlugin.
  */
-public class MBeanInvocationHandlerImpl implements InvocationHandler, NotificationListener
+public class MBeanInvocationHandlerImpl implements InvocationHandler
 {
     private static final Logger _logger = Logger.getLogger(MBeanInvocationHandlerImpl.class);
 
@@ -361,51 +355,5 @@ public class MBeanInvocationHandlerImpl 
         return (methodName.startsWith("query") || methodName.startsWith("get") || methodName.startsWith("is"));
     }
 
-    /**
-     * Receives notifications from the MBeanServer.
-     */
-    public void handleNotification(final Notification notification, final Object handback)
-    {
-        assert notification instanceof JMXConnectionNotification;
-
-        final String connectionId = ((JMXConnectionNotification) notification).getConnectionId();
-        final String type = notification.getType();
-
-        if (_logger.isDebugEnabled())
-        {
-            _logger.debug("Notification connectionId : " + connectionId + " type : " + type
-                    + " Notification handback : " + handback);
-        }
-
-        // Normally JMXManagedObjectRegistry provides a Map as handback data containing a map
-        // between connection id and username.
-        String user = null;
-        if (handback instanceof Map)
-        {
-            @SuppressWarnings("unchecked")
-            final Map<String, String> connectionIdUsernameMap = (Map<String, String>) handback;
-            user = connectionIdUsernameMap.get(connectionId);
-        }
-
-        // If user is still null, fallback to an unordered list of Principals from the connection id.
-        if (user == null)
-        {
-            final String[] splitConnectionId = connectionId.split(" ");
-            user = splitConnectionId[1];
-        }
-
-        // use a separate instance of actor as subject is not set on connect/disconnect
-        // we need to pass principal name explicitly into log actor
-        LogActor logActor = new ManagementActor(_appRegistry.getRootMessageLogger(), user);
-        if (JMXConnectionNotification.OPENED.equals(type))
-        {
-            logActor.message(ManagementConsoleMessages.OPEN(user));
-        }
-        else if (JMXConnectionNotification.CLOSED.equals(type) ||
-                 JMXConnectionNotification.FAILED.equals(type))
-        {
-            logActor.message(ManagementConsoleMessages.CLOSE(user));
-        }
-    }
 }
 

Added: qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporter.java
URL: http://svn.apache.org/viewvc/qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporter.java?rev=1404521&view=auto
==============================================================================
--- qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporter.java (added)
+++ qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporter.java Thu Nov  1 09:48:52 2012
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.jmx;
+
+import static javax.management.remote.JMXConnectionNotification.CLOSED;
+import static javax.management.remote.JMXConnectionNotification.FAILED;
+import static javax.management.remote.JMXConnectionNotification.OPENED;
+
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.remote.JMXConnectionNotification;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.RootMessageLogger;
+import org.apache.qpid.server.logging.actors.ManagementActor;
+import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
+
+public class ManagementLogonLogoffReporter implements  NotificationListener, NotificationFilter
+{
+    private static final Logger LOGGER = Logger.getLogger(ManagementLogonLogoffReporter.class);
+    private final RootMessageLogger _rootMessageLogger;
+    private final UsernameAccessor _usernameAccessor;
+
+    public ManagementLogonLogoffReporter(RootMessageLogger rootMessageLogger, UsernameAccessor usernameAccessor)
+    {
+        _rootMessageLogger = rootMessageLogger;
+        _usernameAccessor = usernameAccessor;
+    }
+
+    @Override
+    public void handleNotification(final Notification notification, final Object handback)
+    {
+        final String connectionId = ((JMXConnectionNotification) notification).getConnectionId();
+        final String type = notification.getType();
+
+        if (LOGGER.isDebugEnabled())
+        {
+            LOGGER.debug("Notification connectionId : " + connectionId + " type : " + type);
+        }
+
+        String user = _usernameAccessor.getUsernameForConnectionId(connectionId);
+
+        // If user is still null, fallback to an unordered list of Principals from the connection id.
+        if (user == null)
+        {
+            final String[] splitConnectionId = connectionId.split(" ");
+            user = splitConnectionId[1];
+        }
+
+        // use a separate instance of actor as subject is not set on connect/disconnect
+        // we need to pass principal name explicitly into log actor
+        LogActor logActor = new ManagementActor(_rootMessageLogger, user);
+        if (JMXConnectionNotification.OPENED.equals(type))
+        {
+            logActor.message(ManagementConsoleMessages.OPEN(user));
+        }
+        else if (JMXConnectionNotification.CLOSED.equals(type) ||
+                 JMXConnectionNotification.FAILED.equals(type))
+        {
+            logActor.message(ManagementConsoleMessages.CLOSE(user));
+        }
+    }
+
+    @Override
+    public boolean isNotificationEnabled(Notification notification)
+    {
+        return notification instanceof JMXConnectionNotification && isLogonTypeEvent(notification);
+    }
+
+    private boolean isLogonTypeEvent(Notification notification)
+    {
+        final String type = notification.getType();
+        return CLOSED.equals(type) || FAILED.equals(type) || OPENED.equals(type);
+    }
+
+}

Added: qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameAccessor.java
URL: http://svn.apache.org/viewvc/qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameAccessor.java?rev=1404521&view=auto
==============================================================================
--- qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameAccessor.java (added)
+++ qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameAccessor.java Thu Nov  1 09:48:52 2012
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.jmx;
+
+public interface UsernameAccessor
+{
+    public String getUsernameForConnectionId(String connectionId);
+
+}

Added: qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameCachingRMIJRMPServer.java
URL: http://svn.apache.org/viewvc/qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameCachingRMIJRMPServer.java?rev=1404521&view=auto
==============================================================================
--- qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameCachingRMIJRMPServer.java (added)
+++ qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameCachingRMIJRMPServer.java Thu Nov  1 09:48:52 2012
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.jmx;
+
+import static javax.management.remote.JMXConnectionNotification.CLOSED;
+import static javax.management.remote.JMXConnectionNotification.FAILED;
+
+import java.io.IOException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.remote.JMXConnectionNotification;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.rmi.RMIConnection;
+import javax.management.remote.rmi.RMIJRMPServerImpl;
+import javax.security.auth.Subject;
+
+import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
+
+/**
+ * An implementation of RMIJRMPServerImpl that caches the usernames of users as they log-on
+ * and makes the same available via {@link UsernameAccessor#getUsernameForConnectionId(String)}.
+ *
+ * Caller is responsible for installing this object as a {@link NotificationListener} of the
+ * {@link JMXConnectorServer} so the cache entries are removed as the clients disconnect.
+ *
+ */
+public class UsernameCachingRMIJRMPServer extends RMIJRMPServerImpl implements NotificationListener, NotificationFilter, UsernameAccessor
+{
+    // ConnectionId is guaranteed to be unique per client connection, according to the JMX spec.
+    private final Map<String, String> _connectionIdUsernameMap = new ConcurrentHashMap<String, String>();
+
+    UsernameCachingRMIJRMPServer(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf,
+            Map<String, ?> env) throws IOException
+    {
+        super(port, csf, ssf, env);
+    }
+
+    @Override
+    protected RMIConnection makeClient(String connectionId, Subject subject) throws IOException
+    {
+        final RMIConnection makeClient = super.makeClient(connectionId, subject);
+        final AuthenticatedPrincipal authenticatedPrincipalFromSubject = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject);
+        _connectionIdUsernameMap.put(connectionId, authenticatedPrincipalFromSubject.getName());
+        return makeClient;
+    }
+
+    @Override
+    public String getUsernameForConnectionId(String connectionId)
+    {
+        return _connectionIdUsernameMap.get(connectionId);
+    }
+
+    @Override
+    public void handleNotification(Notification notification, Object handback)
+    {
+        final String connectionId = ((JMXConnectionNotification) notification).getConnectionId();
+        removeConnectionIdFromCache(connectionId);
+    }
+
+     @Override
+    public boolean isNotificationEnabled(Notification notification)
+    {
+        return isClientDisconnectEvent(notification);
+    }
+
+     private void removeConnectionIdFromCache(String connectionId)
+     {
+         _connectionIdUsernameMap.remove(connectionId);
+     }
+
+    private boolean isClientDisconnectEvent(Notification notification)
+    {
+        final String type = notification.getType();
+        return CLOSED.equals(type) || FAILED.equals(type);
+    }
+
+}
\ No newline at end of file

Modified: qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java
URL: http://svn.apache.org/viewvc/qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java?rev=1404521&r1=1404520&r2=1404521&view=diff
==============================================================================
--- qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java (original)
+++ qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java Thu Nov  1 09:48:52 2012
@@ -65,7 +65,7 @@ public class VirtualHostMBean extends AM
         _managerMBean = new VirtualHostManagerMBean(this);
     }
 
-    private void initQueues() throws JMException
+    private void initQueues()
     {
         synchronized (_children)
         {
@@ -73,13 +73,20 @@ public class VirtualHostMBean extends AM
             {
                 if(!_children.containsKey(queue))
                 {
-                    _children.put(queue, new QueueMBean(queue, this));
+                    try
+                    {
+                        _children.put(queue, new QueueMBean(queue, this));
+                    }
+                    catch(Exception e)
+                    {
+                        LOGGER.error("Cannot create queue mbean for queue " + queue.getName(), e);
+                    }
                 }
             }
         }
     }
 
-    private void initExchanges() throws JMException
+    private void initExchanges()
     {
         synchronized (_children)
         {
@@ -87,13 +94,20 @@ public class VirtualHostMBean extends AM
             {
                 if(!_children.containsKey(exchange))
                 {
-                    _children.put(exchange, new ExchangeMBean(exchange, this));
+                    try
+                    {
+                        _children.put(exchange, new ExchangeMBean(exchange, this));
+                    }
+                    catch(Exception e)
+                    {
+                        LOGGER.error("Cannot create exchange mbean for exchange " + exchange.getName(), e);
+                    }
                 }
             }
         }
     }
 
-    private void initConnections() throws JMException
+    private void initConnections()
     {
         synchronized (_children)
         {
@@ -101,7 +115,14 @@ public class VirtualHostMBean extends AM
             {
                 if(!_children.containsKey(conn))
                 {
-                    _children.put(conn, new ConnectionMBean(conn, this));
+                    try
+                    {
+                        _children.put(conn, new ConnectionMBean(conn, this));
+                    }
+                    catch(Exception e)
+                    {
+                        LOGGER.error("Cannot create connection mbean for connection " + conn.getName(), e);
+                    }
                 }
             }
         }
@@ -119,7 +140,7 @@ public class VirtualHostMBean extends AM
 
     public void stateChanged(ConfiguredObject object, State oldState, State newState)
     {
-        // ignore
+        // no-op
     }
 
     public void childAdded(ConfiguredObject object, ConfiguredObject child)
@@ -208,4 +229,29 @@ public class VirtualHostMBean extends AM
 
         return queues;
     }
+
+    @Override
+    public void unregister() throws JMException
+    {
+        synchronized (_children)
+        {
+            for (AMQManagedObject mbean : _children.values())
+            {
+                if(mbean != null)
+                {
+                    try
+                    {
+                        mbean.unregister();
+                    }
+                    catch(JMException e)
+                    {
+                        LOGGER.error("Failed to remove mbean for child : " + mbean, e);
+                    }
+                }
+            }
+            _children.clear();
+        }
+        _managerMBean.unregister();
+    }
+
 }

Added: qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporterTest.java
URL: http://svn.apache.org/viewvc/qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporterTest.java?rev=1404521&view=auto
==============================================================================
--- qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporterTest.java (added)
+++ qpid/branches/java-broker-config-qpid-4390/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporterTest.java Thu Nov  1 09:48:52 2012
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.jmx;
+
+import static javax.management.remote.JMXConnectionNotification.OPENED;
+import static javax.management.remote.JMXConnectionNotification.CLOSED;
+import static javax.management.remote.JMXConnectionNotification.FAILED;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+
+import javax.management.remote.JMXConnectionNotification;
+
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.RootMessageLogger;
+
+import junit.framework.TestCase;
+
+public class ManagementLogonLogoffReporterTest extends TestCase
+{
+    private static final String TEST_JMX_UNIQUE_CONNECTION_ID = "jmxconnectionid1 jmxuser,group";
+    private static final String TEST_USER = "jmxuser";
+
+    private ManagementLogonLogoffReporter _reporter;
+    private UsernameAccessor _usernameAccessor;
+    private RootMessageLogger _rootMessageLogger;
+
+    @Override
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        _usernameAccessor = mock(UsernameAccessor.class);
+        _rootMessageLogger = mock(RootMessageLogger.class);
+        // Enable messaging so we can valid the generated strings
+        when(_rootMessageLogger.isMessageEnabled(any(LogActor.class), anyString())).thenReturn(true);
+
+        _reporter = new ManagementLogonLogoffReporter(_rootMessageLogger, _usernameAccessor);
+    }
+
+    public void testOpenedNotification()
+    {
+        when(_usernameAccessor.getUsernameForConnectionId(TEST_JMX_UNIQUE_CONNECTION_ID)).thenReturn(TEST_USER);
+        JMXConnectionNotification openNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, OPENED);
+
+        _reporter.handleNotification(openNotification, null);
+
+        verify(_rootMessageLogger).rawMessage("[main] MNG-1007 : Open : User jmxuser", "qpid.message.managementconsole.open");
+    }
+
+    public void testClosedNotification()
+    {
+        when(_usernameAccessor.getUsernameForConnectionId(TEST_JMX_UNIQUE_CONNECTION_ID)).thenReturn(TEST_USER);
+        JMXConnectionNotification closeNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, CLOSED);
+
+        _reporter.handleNotification(closeNotification, null);
+
+        verify(_rootMessageLogger).rawMessage("[main] MNG-1008 : Close : User jmxuser", "qpid.message.managementconsole.close");
+    }
+
+    public void tesNotifiedForLogOnTypeEvents()
+    {
+        JMXConnectionNotification openNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, OPENED);
+        JMXConnectionNotification closeNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, CLOSED);
+        JMXConnectionNotification failedNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, FAILED);
+
+        assertTrue(_reporter.isNotificationEnabled(openNotification));
+        assertTrue(_reporter.isNotificationEnabled(closeNotification));
+        assertTrue(_reporter.isNotificationEnabled(failedNotification));
+
+        JMXConnectionNotification otherNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, "other");
+        assertFalse(_reporter.isNotificationEnabled(otherNotification));
+    }
+
+    private JMXConnectionNotification createMockNotification(String connectionId, String notificationType)
+    {
+        JMXConnectionNotification notification = mock(JMXConnectionNotification.class);
+        when(notification.getConnectionId()).thenReturn(connectionId);
+        when(notification.getType()).thenReturn(notificationType);
+        return notification;
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org