summaryrefslogtreecommitdiff
path: root/java/broker-plugins/management-jmx/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/broker-plugins/management-jmx/src')
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/CustomRMIServerSocketFactory.java68
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java136
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java76
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java407
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java343
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementFactory.java49
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java193
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java101
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java5
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporter.java95
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameAccessor.java (renamed from java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java)21
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameCachingRMIJRMPServer.java100
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java56
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java53
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java5
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java66
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java5
-rw-r--r--java/broker-plugins/management-jmx/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.PluginFactory19
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/JMXManagementFactoryTest.java60
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogActorTest.java170
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporterTest.java101
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java6
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java124
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java283
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java149
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java480
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java317
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java696
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java204
-rw-r--r--java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java251
30 files changed, 1132 insertions, 3507 deletions
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/CustomRMIServerSocketFactory.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/CustomRMIServerSocketFactory.java
new file mode 100644
index 0000000000..b7aab78e45
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/CustomRMIServerSocketFactory.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.jmx;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.rmi.server.RMIServerSocketFactory;
+
+/**
+ * Custom RMIServerSocketFactory class, used to prevent updates to the RMI registry.
+ * Supplied to the registry at creation, this will prevent RMI-based operations on the
+ * registry such as attempting to bind a new object, thereby securing it from tampering.
+ * This is accomplished by always returning null when attempting to determine the address
+ * of the caller, thus ensuring the registry will refuse the attempt. Calls to bind etc
+ * made using the object reference will not be affected and continue to operate normally.
+ */
+class CustomRMIServerSocketFactory implements RMIServerSocketFactory
+{
+
+ public ServerSocket createServerSocket(int port) throws IOException
+ {
+ return new NoLocalAddressServerSocket(port);
+ }
+
+ private static class NoLocalAddressServerSocket extends ServerSocket
+ {
+ NoLocalAddressServerSocket(int port) throws IOException
+ {
+ super(port);
+ }
+
+ @Override
+ public Socket accept() throws IOException
+ {
+ Socket s = new NoLocalAddressSocket();
+ super.implAccept(s);
+ return s;
+ }
+ }
+
+ private static class NoLocalAddressSocket extends Socket
+ {
+ @Override
+ public InetAddress getInetAddress()
+ {
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java
deleted file mode 100644
index c588b40de7..0000000000
--- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.jmx;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-public class JMXActivator implements BundleActivator
-{
- private static final Logger LOGGER = Logger.getLogger(JMXActivator.class);
-
- private String _bundleName;
- private JMXService _jmxService;
-
- private List<ServiceRegistration> _registeredServices;
-
-
- public void start(final BundleContext ctx) throws Exception
- {
- boolean jmxManagementEnabled = ApplicationRegistry.getInstance().getConfiguration().getJMXManagementEnabled();
-
- if (jmxManagementEnabled)
- {
- _jmxService = new JMXService();
- startJmsService(_jmxService);
-
- _bundleName = ctx.getBundle().getSymbolicName();
-
- _registeredServices = registerServices(ctx);
- }
- else
- {
- LOGGER.debug("Skipping registration of JMX plugin as JMX Management disabled in config. ");
- }
- }
-
- public void stop(final BundleContext bundleContext) throws Exception
- {
- try
- {
- if (_jmxService != null)
- {
- if (LOGGER.isInfoEnabled())
- {
- LOGGER.info("Stopping jmx plugin: " + _bundleName);
- }
- _jmxService.close();
- }
-
- if (_registeredServices != null)
- {
- unregisterServices();
- }
- }
- finally
- {
- _jmxService = null;
- _registeredServices = null;
- }
- }
-
-
- private List<ServiceRegistration> registerServices(BundleContext ctx)
- {
- if (LOGGER.isInfoEnabled())
- {
- LOGGER.info("Registering jmx plugin: " + _bundleName);
- }
-
- List<ServiceRegistration> serviceRegistrations = new ArrayList<ServiceRegistration>();
-
- ServiceRegistration jmxServiceRegistration = ctx.registerService(JMXService.class.getName(), _jmxService, null);
- ServiceRegistration jmxConfigFactoryRegistration = ctx.registerService(ConfigurationPluginFactory.class.getName(), JMXConfiguration.FACTORY, null);
-
- serviceRegistrations.add(jmxServiceRegistration);
- serviceRegistrations.add(jmxConfigFactoryRegistration);
- return serviceRegistrations;
- }
-
- private void startJmsService(JMXService jmxService) throws Exception
- {
- if (LOGGER.isInfoEnabled())
- {
- LOGGER.info("Starting JMX service");
- }
- boolean startedSuccessfully = false;
- try
- {
- jmxService.start();
- startedSuccessfully = true;
- }
- finally
- {
- if (!startedSuccessfully)
- {
- LOGGER.error("JMX failed to start normally, closing service");
- jmxService.close();
- }
- }
- }
-
- private void unregisterServices()
- {
- for (Iterator<ServiceRegistration> iterator = _registeredServices.iterator(); iterator.hasNext();)
- {
- ServiceRegistration service = iterator.next();
- service.unregister();
- }
- }
-}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java
deleted file mode 100644
index dc9a712f90..0000000000
--- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.jmx;
-
-import org.apache.commons.configuration.CompositeConfiguration;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.XMLConfiguration;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
-
-import java.util.Arrays;
-import java.util.List;
-
-public class JMXConfiguration extends ConfigurationPlugin
-{
- CompositeConfiguration _finalConfig;
-
- public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory()
- {
- public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException
- {
- ConfigurationPlugin instance = new JMXConfiguration();
- instance.setConfiguration(path, config);
- return instance;
- }
-
- public List<String> getParentPaths()
- {
- return Arrays.asList("jmx");
- }
- };
-
- public String[] getElementsProcessed()
- {
- return new String[] { "" };
- }
-
- public Configuration getConfiguration()
- {
- return _finalConfig;
- }
-
-
- @Override
- public void validateConfiguration() throws ConfigurationException
- {
- // Valid Configuration either has xml links to new files
- _finalConfig = new CompositeConfiguration(getConfig());
- List subFiles = getConfig().getList("xml[@fileName]");
- for (Object subFile : subFiles)
- {
- _finalConfig.addConfiguration(new XMLConfiguration((String) subFile));
- }
-
- }
-
-}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java
index 0648235077..a045683de1 100644
--- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java
@@ -20,171 +20,114 @@
*/
package org.apache.qpid.server.jmx;
-import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
+import org.apache.qpid.server.configuration.BrokerProperties;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
-
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Transport;
import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
-import javax.management.Notification;
-import javax.management.NotificationFilterSupport;
-import javax.management.NotificationListener;
import javax.management.ObjectName;
-import javax.management.remote.JMXConnectionNotification;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.MBeanServerForwarder;
-import javax.management.remote.rmi.RMIConnection;
import javax.management.remote.rmi.RMIConnectorServer;
-import javax.management.remote.rmi.RMIJRMPServerImpl;
-import javax.management.remote.rmi.RMIServerImpl;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;
-import javax.security.auth.Subject;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.management.ManagementFactory;
-import java.lang.reflect.Proxy;
import java.net.InetAddress;
import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
import java.net.UnknownHostException;
import java.rmi.AlreadyBoundException;
import java.rmi.NoSuchObjectException;
import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
/**
- * This class starts up an MBeanserver. If out of the box agent has been enabled then there are no
+ * This class starts up an MBeanserver. If out of the box agent has been enabled then there are no
* security features implemented like user authentication and authorisation.
*/
public class JMXManagedObjectRegistry implements ManagedObjectRegistry
{
private static final Logger _log = Logger.getLogger(JMXManagedObjectRegistry.class);
+ private static final String OPERATIONAL_LOGGING_NAME = "JMX";
+
private final MBeanServer _mbeanServer;
+
private JMXConnectorServer _cs;
private Registry _rmiRegistry;
- private boolean _useCustomSocketFactory;
- private final int _jmxPortRegistryServer;
- private final int _jmxPortConnectorServer;
+ private final Broker _broker;
+ private final Port _registryPort;
+ private final Port _connectorPort;
- public JMXManagedObjectRegistry() throws AMQException
+ public JMXManagedObjectRegistry(
+ Broker broker,
+ Port connectorPort, Port registryPort,
+ JMXManagement jmxManagement)
{
- _log.info("Initialising managed object registry using platform MBean server");
- IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
+ _broker = broker;
+ _registryPort = registryPort;
+ _connectorPort = connectorPort;
- // Retrieve the config parameters
- _useCustomSocketFactory = appRegistry.getConfiguration().getUseCustomRMISocketFactory();
- boolean platformServer = appRegistry.getConfiguration().getPlatformMbeanserver();
+ boolean usePlatformServer = (Boolean)jmxManagement.getAttribute(JMXManagement.USE_PLATFORM_MBEAN_SERVER);
_mbeanServer =
- platformServer ? ManagementFactory.getPlatformMBeanServer()
+ usePlatformServer ? ManagementFactory.getPlatformMBeanServer()
: MBeanServerFactory.createMBeanServer(ManagedObject.DOMAIN);
+ }
- _jmxPortRegistryServer = appRegistry.getConfiguration().getJMXPortRegistryServer();
- _jmxPortConnectorServer = appRegistry.getConfiguration().getJMXConnectorServerPort();
-
- }
-
- public void start() throws IOException, ConfigurationException
+ @Override
+ public void start() throws IOException
{
-
- CurrentActor.get().message(ManagementConsoleMessages.STARTUP());
+ CurrentActor.get().message(ManagementConsoleMessages.STARTUP(OPERATIONAL_LOGGING_NAME));
//check if system properties are set to use the JVM's out-of-the-box JMXAgent
if (areOutOfTheBoxJMXOptionsSet())
{
- CurrentActor.get().message(ManagementConsoleMessages.READY(true));
- return;
+ CurrentActor.get().message(ManagementConsoleMessages.READY(OPERATIONAL_LOGGING_NAME));
}
+ else
+ {
+ startRegistryAndConnector();
+ }
+ }
- IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
-
-
- //Socket factories for the RMIConnectorServer, either default or SLL depending on configuration
+ private void startRegistryAndConnector() throws IOException
+ {
+ //Socket factories for the RMIConnectorServer, either default or SSL depending on configuration
RMIClientSocketFactory csf;
RMIServerSocketFactory ssf;
- //check ssl enabled option in config, default to true if option is not set
- boolean sslEnabled = appRegistry.getConfiguration().getManagementSSLEnabled();
+ //check ssl enabled option on connector port (note we don't provide ssl for registry server at
+ //moment).
+ boolean connectorSslEnabled = _connectorPort.getTransports().contains(Transport.SSL);
- if (sslEnabled)
+ if (connectorSslEnabled)
{
- //set the SSL related system properties used by the SSL RMI socket factories to the values
- //given in the configuration file, unless command line settings have already been specified
- String keyStorePath;
+ String keyStorePath = System.getProperty("javax.net.ssl.keyStore");
+ String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword");
- if(System.getProperty("javax.net.ssl.keyStore") != null)
- {
- keyStorePath = System.getProperty("javax.net.ssl.keyStore");
- }
- else
- {
- keyStorePath = appRegistry.getConfiguration().getManagementKeyStorePath();
- }
+ validateKeyStoreProperties(keyStorePath, keyStorePassword);
- //check the keystore path value is valid
- if (keyStorePath == null)
- {
- throw new ConfigurationException("JMX management SSL keystore path not defined, " +
- "unable to start SSL protected JMX ConnectorServer");
- }
- else
- {
- //ensure the system property is set
- System.setProperty("javax.net.ssl.keyStore", keyStorePath);
-
- //check the file is usable
- File ksf = new File(keyStorePath);
-
- if (!ksf.exists())
- {
- throw new FileNotFoundException("Cannot find JMX management SSL keystore file: " + ksf);
- }
- if (!ksf.canRead())
- {
- throw new FileNotFoundException("Cannot read JMX management SSL keystore file: "
- + ksf + ". Check permissions.");
- }
-
- CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(ksf.getAbsolutePath()));
- }
-
- //check the key store password is set
- if (System.getProperty("javax.net.ssl.keyStorePassword") == null)
- {
-
- if (appRegistry.getConfiguration().getManagementKeyStorePassword() == null)
- {
- throw new ConfigurationException("JMX management SSL keystore password not defined, " +
- "unable to start requested SSL protected JMX server");
- }
- else
- {
- System.setProperty("javax.net.ssl.keyStorePassword",
- appRegistry.getConfiguration().getManagementKeyStorePassword());
- }
- }
+ CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(keyStorePath));
//create the SSL RMI socket factories
csf = new SslRMIClientSocketFactory();
@@ -197,27 +140,23 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
ssf = null;
}
+ int jmxPortRegistryServer = _registryPort.getPort();
+ int jmxPortConnectorServer = _connectorPort.getPort();
+
//add a JMXAuthenticator implementation the env map to authenticate the RMI based JMX connector server
- RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator(new InetSocketAddress(_jmxPortRegistryServer));
- HashMap<String,Object> env = new HashMap<String,Object>();
- env.put(JMXConnectorServer.AUTHENTICATOR, rmipa);
+ RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator(_broker, new InetSocketAddress(jmxPortConnectorServer));
+ HashMap<String,Object> connectorEnv = new HashMap<String,Object>();
+ connectorEnv.put(JMXConnectorServer.AUTHENTICATOR, rmipa);
+
+ System.setProperty("java.rmi.server.randomIDs", "true");
+ boolean useCustomSocketFactory = Boolean.parseBoolean(System.getProperty(BrokerProperties.PROPERTY_USE_CUSTOM_RMI_SOCKET_FACTORY, Boolean.TRUE.toString()));
/*
* Start a RMI registry on the management port, to hold the JMX RMI ConnectorServer stub.
* Using custom socket factory to prevent anyone (including us unfortunately) binding to the registry using RMI.
* As a result, only binds made using the object reference will succeed, thus securing it from external change.
*/
- System.setProperty("java.rmi.server.randomIDs", "true");
- if(_useCustomSocketFactory)
- {
- _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, new CustomRMIServerSocketFactory());
- }
- else
- {
- _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, null);
- }
-
- CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", _jmxPortRegistryServer));
+ _rmiRegistry = createRmiRegistry(jmxPortRegistryServer, useCustomSocketFactory);
/*
* We must now create the RMI ConnectorServer manually, as the JMX Factory methods use RMI calls
@@ -225,57 +164,16 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
* locked it from any RMI based modifications, including our own. Instead, we will manually bind
* the RMIConnectorServer stub to the registry using its object reference, which will still succeed.
*
- * The registry is exported on the defined management port 'port'. We will export the RMIConnectorServer
- * on 'port +1'. Use of these two well-defined ports will ease any navigation through firewall's.
+ * The registry is exported on the defined management port 'port'.
*/
- final Map<String, String> connectionIdUsernameMap = new ConcurrentHashMap<String, String>();
- final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(_jmxPortConnectorServer, csf, ssf, env)
- {
-
- /**
- * Override makeClient so we can cache the username of the client in a Map keyed by connectionId.
- * ConnectionId is guaranteed to be unique per client connection, according to the JMS spec.
- * An instance of NotificationListener (mapCleanupListener) will be responsible for removing these Map
- * entries.
- *
- * @see javax.management.remote.rmi.RMIJRMPServerImpl#makeClient(String, javax.security.auth.Subject)
- */
- @Override
- protected RMIConnection makeClient(String connectionId, Subject subject) throws IOException
- {
- final RMIConnection makeClient = super.makeClient(connectionId, subject);
- final UsernamePrincipal usernamePrincipalFromSubject = UsernamePrincipal.getUsernamePrincipalFromSubject(subject);
- connectionIdUsernameMap.put(connectionId, usernamePrincipalFromSubject.getName());
- return makeClient;
- }
- };
-
- // Create a Listener responsible for removing the map entries add by the #makeClient entry above.
- final NotificationListener mapCleanupListener = new NotificationListener()
- {
-
- public void handleNotification(Notification notification, Object handback)
- {
- final String connectionId = ((JMXConnectionNotification) notification).getConnectionId();
- connectionIdUsernameMap.remove(connectionId);
- }
- };
+ final UsernameCachingRMIJRMPServer usernameCachingRmiServer = new UsernameCachingRMIJRMPServer(jmxPortConnectorServer, csf, ssf, connectorEnv);
- String localHost;
- try
- {
- localHost = InetAddress.getLocalHost().getHostName();
- }
- catch(UnknownHostException ex)
- {
- localHost="127.0.0.1";
- }
- final String hostname = localHost;
+ final String localHostName = getLocalhost();
final JMXServiceURL externalUrl = new JMXServiceURL(
- "service:jmx:rmi://"+hostname+":"+(_jmxPortConnectorServer)+"/jndi/rmi://"+hostname+":"+_jmxPortRegistryServer+"/jmxrmi");
+ "service:jmx:rmi://"+localHostName+":"+(jmxPortConnectorServer)+"/jndi/rmi://"+localHostName+":"+jmxPortRegistryServer+"/jmxrmi");
- final JMXServiceURL internalUrl = new JMXServiceURL("rmi", hostname, _jmxPortConnectorServer);
- _cs = new RMIConnectorServer(internalUrl, env, rmiConnectorServerStub, _mbeanServer)
+ final JMXServiceURL internalUrl = new JMXServiceURL("rmi", localHostName, jmxPortConnectorServer);
+ _cs = new RMIConnectorServer(internalUrl, connectorEnv, usernameCachingRmiServer, _mbeanServer)
{
@Override
public synchronized void start() throws IOException
@@ -283,7 +181,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
try
{
//manually bind the connector server to the registry at key 'jmxrmi', like the out-of-the-box agent
- _rmiRegistry.bind("jmxrmi", rmiConnectorServerStub);
+ _rmiRegistry.bind("jmxrmi", usernameCachingRmiServer);
}
catch (AlreadyBoundException abe)
{
@@ -311,7 +209,6 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
}
catch (NotBoundException nbe)
{
- // TODO consider if we want to keep new logging
_log.error("Failed to unbind jmxrmi", nbe);
//ignore
}
@@ -326,97 +223,100 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
//must return our pre-crafted url that includes the full details, inc JNDI details
return externalUrl;
}
-
};
-
//Add the custom invoker as an MBeanServerForwarder, and start the RMIConnectorServer.
- MBeanServerForwarder mbsf = MBeanInvocationHandlerImpl.newProxyInstance();
+ MBeanServerForwarder mbsf = MBeanInvocationHandlerImpl.newProxyInstance(_broker);
_cs.setMBeanServerForwarder(mbsf);
+ // Install a ManagementLogonLogoffReporter so we can report as users logon/logoff
+ ManagementLogonLogoffReporter jmxManagementUserLogonLogoffReporter = new ManagementLogonLogoffReporter(_broker.getRootMessageLogger(), usernameCachingRmiServer);
+ _cs.addNotificationListener(jmxManagementUserLogonLogoffReporter, jmxManagementUserLogonLogoffReporter, null);
- // Get the handler that is used by the above MBInvocationHandler Proxy.
- // which is the MBeanInvocationHandlerImpl and so also a NotificationListener.
- final NotificationListener invocationHandler = (NotificationListener) Proxy.getInvocationHandler(mbsf);
-
- // Install a notification listener on OPENED, CLOSED, and FAILED,
- // passing the map of connection-ids to usernames as hand-back data.
- final NotificationFilterSupport invocationHandlerFilter = new NotificationFilterSupport();
- invocationHandlerFilter.enableType(JMXConnectionNotification.OPENED);
- invocationHandlerFilter.enableType(JMXConnectionNotification.CLOSED);
- invocationHandlerFilter.enableType(JMXConnectionNotification.FAILED);
- _cs.addNotificationListener(invocationHandler, invocationHandlerFilter, connectionIdUsernameMap);
-
- // Install a second notification listener on CLOSED AND FAILED only to remove the entry from the
- // Map. Here we rely on the fact that JMX will call the listeners in the order in which they are
- // installed.
- final NotificationFilterSupport mapCleanupHandlerFilter = new NotificationFilterSupport();
- mapCleanupHandlerFilter.enableType(JMXConnectionNotification.CLOSED);
- mapCleanupHandlerFilter.enableType(JMXConnectionNotification.FAILED);
- _cs.addNotificationListener(mapCleanupListener, mapCleanupHandlerFilter, null);
+ // Install the usernameCachingRmiServer as a listener so it may cleanup as clients disconnect
+ _cs.addNotificationListener(usernameCachingRmiServer, usernameCachingRmiServer, null);
_cs.start();
- String connectorServer = (sslEnabled ? "SSL " : "") + "JMX RMIConnectorServer";
- CurrentActor.get().message(ManagementConsoleMessages.LISTENING(connectorServer, _jmxPortConnectorServer));
-
- CurrentActor.get().message(ManagementConsoleMessages.READY(false));
+ String connectorServer = (connectorSslEnabled ? "SSL " : "") + "JMX RMIConnectorServer";
+ CurrentActor.get().message(ManagementConsoleMessages.LISTENING(connectorServer, jmxPortConnectorServer));
+ CurrentActor.get().message(ManagementConsoleMessages.READY(OPERATIONAL_LOGGING_NAME));
}
- /*
- * Custom RMIServerSocketFactory class, used to prevent updates to the RMI registry.
- * Supplied to the registry at creation, this will prevent RMI-based operations on the
- * registry such as attempting to bind a new object, thereby securing it from tampering.
- * This is accomplished by always returning null when attempting to determine the address
- * of the caller, thus ensuring the registry will refuse the attempt. Calls to bind etc
- * made using the object reference will not be affected and continue to operate normally.
- */
-
- private static class CustomRMIServerSocketFactory implements RMIServerSocketFactory
+ private Registry createRmiRegistry(int jmxPortRegistryServer, boolean useCustomRmiRegistry)
+ throws RemoteException
{
-
- public ServerSocket createServerSocket(int port) throws IOException
+ Registry rmiRegistry;
+ if(useCustomRmiRegistry)
{
- return new NoLocalAddressServerSocket(port);
+ _log.debug("Using custom RMIServerSocketFactory");
+ rmiRegistry = LocateRegistry.createRegistry(jmxPortRegistryServer, null, new CustomRMIServerSocketFactory());
}
-
- private static class NoLocalAddressServerSocket extends ServerSocket
+ else
{
- NoLocalAddressServerSocket(int port) throws IOException
- {
- super(port);
- }
+ _log.debug("Using default RMIServerSocketFactory");
+ rmiRegistry = LocateRegistry.createRegistry(jmxPortRegistryServer, null, null);
+ }
- @Override
- public Socket accept() throws IOException
- {
- Socket s = new NoLocalAddressSocket();
- super.implAccept(s);
- return s;
- }
+ CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", jmxPortRegistryServer));
+ return rmiRegistry;
+ }
+
+ private void validateKeyStoreProperties(String keyStorePath, String keyStorePassword) throws FileNotFoundException
+ {
+ if (keyStorePath == null)
+ {
+ throw new IllegalConfigurationException("JVM system property 'javax.net.ssl.keyStore' is not set, "
+ + "unable to start requested SSL protected JMX connector");
+ }
+ if (keyStorePassword == null)
+ {
+ throw new IllegalConfigurationException( "JVM system property 'javax.net.ssl.keyStorePassword' is not set, "
+ + "unable to start requested SSL protected JMX connector");
}
- private static class NoLocalAddressSocket extends Socket
+ File ksf = new File(keyStorePath);
+ if (!ksf.exists())
{
- @Override
- public InetAddress getInetAddress()
- {
- return null;
- }
+ throw new FileNotFoundException("Cannot find JMX management SSL keystore file: " + ksf);
+ }
+ if (!ksf.canRead())
+ {
+ throw new FileNotFoundException("Cannot read JMX management SSL keystore file: "
+ + ksf + ". Check permissions.");
}
}
-
+ @Override
public void registerObject(ManagedObject managedObject) throws JMException
{
_mbeanServer.registerMBean(managedObject, managedObject.getObjectName());
}
+ @Override
public void unregisterObject(ManagedObject managedObject) throws JMException
{
_mbeanServer.unregisterMBean(managedObject.getObjectName());
}
+ @Override
+ public void close()
+ {
+ _log.debug("close() called");
+
+ closeConnectorAndRegistryServers();
+
+ unregisterAllMbeans();
+
+ CurrentActor.get().message(ManagementConsoleMessages.STOPPED(OPERATIONAL_LOGGING_NAME));
+ }
+
+ private void closeConnectorAndRegistryServers()
+ {
+ closeConnectorServer();
+ closeRegistryServer();
+ }
+
// checks if the system properties are set which enable the JVM's out-of-the-box JMXAgent.
private boolean areOutOfTheBoxJMXOptionsSet()
{
@@ -433,29 +333,26 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
return false;
}
- //Stops the JMXConnectorServer and RMIRegistry, then unregisters any remaining MBeans from the MBeanServer
- public void close()
+ private String getLocalhost()
{
- _log.debug("close() called");
-
- if (_cs != null)
+ String localHost;
+ try
{
- // Stopping the JMX ConnectorServer
- try
- {
- CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("JMX RMIConnectorServer", _cs.getAddress().getPort()));
- _cs.stop();
- }
- catch (IOException e)
- {
- _log.error("Exception while closing the JMX ConnectorServer: ", e);
- }
+ localHost = InetAddress.getLocalHost().getHostName();
}
-
+ catch(UnknownHostException ex)
+ {
+ localHost="127.0.0.1";
+ }
+ return localHost;
+ }
+
+ private void closeRegistryServer()
+ {
if (_rmiRegistry != null)
{
// Stopping the RMI registry
- CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _jmxPortRegistryServer));
+ CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _registryPort.getPort()));
try
{
boolean success = UnicastRemoteObject.unexportObject(_rmiRegistry, false);
@@ -468,8 +365,36 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
{
_log.error("Exception while closing the RMI Registry: ", e);
}
+ finally
+ {
+ _rmiRegistry = null;
+ }
+ }
+ }
+
+ private void closeConnectorServer()
+ {
+ if (_cs != null)
+ {
+ // Stopping the JMX ConnectorServer
+ try
+ {
+ CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("JMX RMIConnectorServer", _cs.getAddress().getPort()));
+ _cs.stop();
+ }
+ catch (IOException e)
+ {
+ _log.error("Exception while closing the JMX ConnectorServer: ", e);
+ }
+ finally
+ {
+ _cs = null;
+ }
}
-
+ }
+
+ private void unregisterAllMbeans()
+ {
//ObjectName query to gather all Qpid related MBeans
ObjectName mbeanNameQuery = null;
try
@@ -492,8 +417,6 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
_log.error("Exception unregistering MBean '"+ name +"': " + e.getMessage());
}
}
-
- CurrentActor.get().message(ManagementConsoleMessages.STOPPED());
}
}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java
new file mode 100644
index 0000000000..8f087ba50c
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java
@@ -0,0 +1,343 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.jmx;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.management.JMException;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.jmx.mbeans.LoggingManagementMBean;
+import org.apache.qpid.server.jmx.mbeans.UserManagementMBean;
+import org.apache.qpid.server.jmx.mbeans.ServerInformationMBean;
+import org.apache.qpid.server.jmx.mbeans.Shutdown;
+import org.apache.qpid.server.jmx.mbeans.VirtualHostMBean;
+import org.apache.qpid.server.logging.log4j.LoggingManagementFacade;
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+import org.apache.qpid.server.model.Plugin;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.adapter.AbstractPluginAdapter;
+import org.apache.qpid.server.plugin.PluginFactory;
+import org.apache.qpid.server.plugin.QpidServiceLoader;
+import org.apache.qpid.server.util.MapValueConverter;
+
+public class JMXManagement extends AbstractPluginAdapter implements ConfigurationChangeListener
+{
+ private static final Logger LOGGER = Logger.getLogger(JMXManagement.class);
+
+ public static final String PLUGIN_TYPE = "MANAGEMENT-JMX";
+
+ // attributes
+ public static final String USE_PLATFORM_MBEAN_SERVER = "usePlatformMBeanServer";
+ public static final String NAME = "name";
+
+ // default values
+ public static final String DEFAULT_NAME = "JMXManagement";
+ public static final boolean DEFAULT_USE_PLATFORM_MBEAN_SERVER = true;
+
+ @SuppressWarnings("serial")
+ private static final Collection<String> AVAILABLE_ATTRIBUTES = Collections.unmodifiableCollection(new HashSet<String>(Plugin.AVAILABLE_ATTRIBUTES){{
+ add(NAME);
+ add(USE_PLATFORM_MBEAN_SERVER);
+ add(PluginFactory.PLUGIN_TYPE);
+ }});
+
+ @SuppressWarnings("serial")
+ private static final Map<String, Object> DEFAULTS = new HashMap<String, Object>(){{
+ put(USE_PLATFORM_MBEAN_SERVER, DEFAULT_USE_PLATFORM_MBEAN_SERVER);
+ put(NAME, DEFAULT_NAME);
+ put(PluginFactory.PLUGIN_TYPE, PLUGIN_TYPE);
+ }};
+
+ @SuppressWarnings("serial")
+ private static final Map<String, Class<?>> ATTRIBUTE_TYPES = new HashMap<String, Class<?>>(){{
+ put(USE_PLATFORM_MBEAN_SERVER, Boolean.class);
+ put(NAME, String.class);
+ put(PluginFactory.PLUGIN_TYPE, String.class);
+ }};
+
+ private final Broker _broker;
+ private JMXManagedObjectRegistry _objectRegistry;
+
+ private final Map<ConfiguredObject, AMQManagedObject> _children = new HashMap<ConfiguredObject, AMQManagedObject>();
+
+ public JMXManagement(UUID id, Broker broker, Map<String, Object> attributes)
+ {
+ super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), broker.getTaskExecutor());
+ _broker = broker;
+ addParent(Broker.class, broker);
+ }
+
+ @Override
+ protected boolean setState(State currentState, State desiredState)
+ {
+ if(desiredState == State.ACTIVE)
+ {
+ try
+ {
+ start();
+ }
+ catch (JMException e)
+ {
+ throw new RuntimeException("Couldn't start JMX management", e);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Couldn't start JMX management", e);
+ }
+ return true;
+ }
+ else if(desiredState == State.STOPPED)
+ {
+ stop();
+ return true;
+ }
+ return false;
+ }
+
+ private void start() throws JMException, IOException
+ {
+ Port connectorPort = null;
+ Port registryPort = null;
+ Collection<Port> ports = _broker.getPorts();
+ for (Port port : ports)
+ {
+ if (State.QUIESCED.equals(port.getActualState()))
+ {
+ continue;
+ }
+
+ if(isRegistryPort(port))
+ {
+ registryPort = port;
+ }
+ else if(isConnectorPort(port))
+ {
+ connectorPort = port;
+ }
+ }
+ if(connectorPort == null)
+ {
+ throw new IllegalStateException("No JMX connector port found supporting protocol " + Protocol.JMX_RMI);
+ }
+ if(registryPort == null)
+ {
+ throw new IllegalStateException("No JMX RMI port found supporting protocol " + Protocol.RMI);
+ }
+
+ _objectRegistry = new JMXManagedObjectRegistry(_broker, connectorPort, registryPort, this);
+
+ _broker.addChangeListener(this);
+
+ synchronized (_children)
+ {
+ for(VirtualHost virtualHost : _broker.getVirtualHosts())
+ {
+ if(!_children.containsKey(virtualHost))
+ {
+ LOGGER.debug("Create MBean for virtual host:" + virtualHost.getName());
+ VirtualHostMBean mbean = new VirtualHostMBean(virtualHost, _objectRegistry);
+ LOGGER.debug("Check for additional MBeans for virtual host:" + virtualHost.getName());
+ createAdditionalMBeansFromProviders(virtualHost, mbean);
+ }
+ }
+ Collection<AuthenticationProvider> authenticationProviders = _broker.getAuthenticationProviders();
+ for (AuthenticationProvider authenticationProvider : authenticationProviders)
+ {
+ if(authenticationProvider instanceof PasswordCredentialManagingAuthenticationProvider)
+ {
+ UserManagementMBean mbean = new UserManagementMBean(
+ (PasswordCredentialManagingAuthenticationProvider) authenticationProvider,
+ _objectRegistry);
+ _children.put(authenticationProvider, mbean);
+ }
+ }
+ }
+ new Shutdown(_objectRegistry);
+ new ServerInformationMBean(_objectRegistry, _broker);
+ if (LoggingManagementFacade.getCurrentInstance() != null)
+ {
+ new LoggingManagementMBean(LoggingManagementFacade.getCurrentInstance(), _objectRegistry);
+ }
+ _objectRegistry.start();
+ }
+
+ private boolean isConnectorPort(Port port)
+ {
+ return port.getProtocols().contains(Protocol.JMX_RMI);
+ }
+
+ private boolean isRegistryPort(Port port)
+ {
+ return port.getProtocols().contains(Protocol.RMI);
+ }
+
+ private void stop()
+ {
+ synchronized (_children)
+ {
+ for(ConfiguredObject object : _children.keySet())
+ {
+ AMQManagedObject mbean = _children.get(object);
+ if (mbean instanceof ConfigurationChangeListener)
+ {
+ object.removeChangeListener((ConfigurationChangeListener)mbean);
+ }
+ try
+ {
+ mbean.unregister();
+ }
+ catch (JMException e)
+ {
+ LOGGER.error("Error unregistering mbean", e);
+ }
+ }
+ _children.clear();
+ }
+ _broker.removeChangeListener(this);
+ _objectRegistry.close();
+ }
+
+ @Override
+ public void stateChanged(ConfiguredObject object, State oldState, State newState)
+ {
+ // no-op
+ }
+
+ @Override
+ public void childAdded(ConfiguredObject object, ConfiguredObject child)
+ {
+ synchronized (_children)
+ {
+ try
+ {
+ AMQManagedObject mbean;
+ if(child instanceof VirtualHost)
+ {
+ VirtualHost vhostChild = (VirtualHost)child;
+ mbean = new VirtualHostMBean(vhostChild, _objectRegistry);
+ }
+ else if(child instanceof PasswordCredentialManagingAuthenticationProvider)
+ {
+ mbean = new UserManagementMBean((PasswordCredentialManagingAuthenticationProvider) child, _objectRegistry);
+ }
+ else
+ {
+ mbean = null;
+ }
+
+ if (mbean != null)
+ {
+ createAdditionalMBeansFromProviders(child, mbean);
+ }
+ }
+ catch(JMException e)
+ {
+ LOGGER.error("Error creating mbean", e);
+ // TODO - Implement error reporting on mbean creation
+ }
+ }
+ }
+
+ @Override
+ public void childRemoved(ConfiguredObject object, ConfiguredObject child)
+ {
+ // TODO - implement vhost removal (possibly just removing the instanceof check below)
+
+ synchronized (_children)
+ {
+ if(child instanceof PasswordCredentialManagingAuthenticationProvider)
+ {
+ AMQManagedObject mbean = _children.remove(child);
+ if(mbean != null)
+ {
+ try
+ {
+ mbean.unregister();
+ }
+ catch(JMException e)
+ {
+ LOGGER.error("Error creating mbean", e);
+ //TODO - report error on removing child MBean
+ }
+ }
+ }
+
+ }
+ }
+
+ @Override
+ public void attributeSet(ConfiguredObject object, String attributeName, Object oldAttributeValue, Object newAttributeValue)
+ {
+ // no-op
+ }
+
+ private void createAdditionalMBeansFromProviders(ConfiguredObject child, AMQManagedObject mbean) throws JMException
+ {
+ _children.put(child, mbean);
+
+ QpidServiceLoader<MBeanProvider> qpidServiceLoader = new QpidServiceLoader<MBeanProvider>();
+ for (MBeanProvider provider : qpidServiceLoader.instancesOf(MBeanProvider.class))
+ {
+ LOGGER.debug("Consulting mbean provider : " + provider + " for child : " + child);
+ if (provider.isChildManageableByMBean(child))
+ {
+ LOGGER.debug("Provider will create mbean ");
+ provider.createMBean(child, mbean);
+ // TODO track the mbeans that have been created on behalf of a child in a map, then
+ // if the child is ever removed, destroy these beans too.
+ }
+ }
+ }
+
+ /** Added for testing purposes */
+ Broker getBroker()
+ {
+ return _broker;
+ }
+
+ @Override
+ public String getName()
+ {
+ return (String)getAttribute(NAME);
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return AVAILABLE_ATTRIBUTES;
+ }
+
+}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementFactory.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementFactory.java
new file mode 100644
index 0000000000..c2186c372b
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.jmx;
+
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Plugin;
+import org.apache.qpid.server.plugin.PluginFactory;
+
+public class JMXManagementFactory implements PluginFactory
+{
+ private static final Logger LOGGER = Logger.getLogger(JMXManagementFactory.class);
+
+ @Override
+ public Plugin createInstance(UUID id, Map<String, Object> attributes, Broker broker)
+ {
+ if (JMXManagement.PLUGIN_TYPE.equals(attributes.get(PLUGIN_TYPE)))
+ {
+ return new JMXManagement(id, broker, attributes);
+ }
+ else
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Skipping registration of JMX plugin as JMX Management disabled in config.");
+ }
+ return null;
+ }
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java
deleted file mode 100644
index 7a232d2584..0000000000
--- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.server.jmx;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.ServiceLoader;
-
-import javax.management.JMException;
-import javax.management.StandardMBean;
-
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.jmx.mbeans.LoggingManagementMBean;
-import org.apache.qpid.server.jmx.mbeans.UserManagementMBean;
-import org.apache.qpid.server.jmx.mbeans.ConfigurationManagementMBean;
-import org.apache.qpid.server.jmx.mbeans.ServerInformationMBean;
-import org.apache.qpid.server.jmx.mbeans.Shutdown;
-import org.apache.qpid.server.jmx.mbeans.VirtualHostMBean;
-import org.apache.qpid.server.logging.log4j.LoggingFacade;
-import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.ConfigurationChangeListener;
-import org.apache.qpid.server.model.ConfiguredObject;
-import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
-import org.apache.qpid.server.model.State;
-import org.apache.qpid.server.model.VirtualHost;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-
-
-public class JMXService implements ConfigurationChangeListener
-{
- private static final ClassLoader BUNDLE_CLASSLOADER = JMXService.class.getClassLoader();
-
- private static final Logger LOGGER = Logger.getLogger(JMXService.class);
-
- private final Broker _broker;
- private final JMXManagedObjectRegistry _objectRegistry;
- private final Shutdown _shutdown;
- private final ServerInformationMBean _serverInfo;
- private final ConfigurationManagementMBean _configManagement;
- private final LoggingManagementMBean _loggingManagement;
-
- private final Map<ConfiguredObject, AMQManagedObject> _children = new HashMap<ConfiguredObject, AMQManagedObject>();
-
- public JMXService() throws AMQException, JMException
- {
- _broker = ApplicationRegistry.getInstance().getBroker();
- _objectRegistry = new JMXManagedObjectRegistry();
-
- _broker.addChangeListener(this);
- synchronized (_children)
- {
- for(VirtualHost virtualHost : _broker.getVirtualHosts())
- {
- if(!_children.containsKey(virtualHost))
- {
- _children.put(virtualHost, new VirtualHostMBean(virtualHost, _objectRegistry));
- }
- }
- }
- _shutdown = new Shutdown(_objectRegistry);
- _serverInfo = new ServerInformationMBean(_objectRegistry, _broker);
- _configManagement = new ConfigurationManagementMBean(_objectRegistry);
- _loggingManagement = new LoggingManagementMBean(LoggingFacade.getCurrentInstance(), _objectRegistry);
- }
-
- public void start() throws IOException, ConfigurationException
- {
- _objectRegistry.start();
- }
-
- public void close()
- {
- _broker.removeChangeListener(this);
-
- _objectRegistry.close();
- }
-
- public void stateChanged(ConfiguredObject object, State oldState, State newState)
- {
-
- }
-
- public void childAdded(ConfiguredObject object, ConfiguredObject child)
- {
- synchronized (_children)
- {
- try
- {
- AMQManagedObject mbean;
- if(child instanceof VirtualHost)
- {
- VirtualHost vhostChild = (VirtualHost)child;
- mbean = new VirtualHostMBean(vhostChild, _objectRegistry);
- }
- else if(child instanceof PasswordCredentialManagingAuthenticationProvider)
- {
- mbean = new UserManagementMBean((PasswordCredentialManagingAuthenticationProvider) child, _objectRegistry);
- }
- else
- {
- mbean = null;
- }
-
- if (mbean != null)
- {
- createAdditionalMBeansFromProviders(child, mbean);
- }
- }
- catch(JMException e)
- {
- LOGGER.error("Error creating mbean", e);
- // TODO - Implement error reporting on mbean creation
- }
- }
- }
-
-
- public void childRemoved(ConfiguredObject object, ConfiguredObject child)
- {
- // TODO - implement vhost removal (possibly just removing the instanceof check below)
-
- synchronized (_children)
- {
- if(child instanceof PasswordCredentialManagingAuthenticationProvider)
- {
- AMQManagedObject mbean = _children.remove(child);
- if(mbean != null)
- {
- try
- {
- mbean.unregister();
- }
- catch(JMException e)
- {
- LOGGER.error("Error creating mbean", e);
- //TODO - report error on removing child MBean
- }
- }
- }
-
- }
- }
-
- private void createAdditionalMBeansFromProviders(ConfiguredObject child, AMQManagedObject mbean) throws JMException
- {
- _children.put(child, mbean);
-
- for (Iterator<MBeanProvider> iterator = getMBeanProviderIterator(); iterator.hasNext();)
- {
- MBeanProvider provider = iterator.next();
- LOGGER.debug("Consulting mbean provider : " + provider + " for child : " + child);
- if (provider.isChildManageableByMBean(child))
- {
- LOGGER.debug("Provider will create mbean ");
- StandardMBean bean = provider.createMBean(child, mbean);
- // TODO track the mbeans that have been created on behalf of a child in a map, then
- // if the child is ever removed, destroy these beans too.
- }
- }
- }
-
- /**
- * Finds all classes implementing the {@link MBeanProvider} interface. This will find
- * <b>only</b> those classes which are visible to the classloader of this OSGI bundle.
- */
- private Iterator<MBeanProvider> getMBeanProviderIterator()
- {
- return ServiceLoader.load(MBeanProvider.class, BUNDLE_CLASSLOADER).iterator();
- }
-}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
index a2a0d2d093..8bc2afb176 100644
--- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
@@ -22,26 +22,22 @@ package org.apache.qpid.server.jmx;
import org.apache.log4j.Logger;
-import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.configuration.BrokerProperties;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.ManagementActor;
-import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
import javax.management.Attribute;
import javax.management.JMException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanServer;
-import javax.management.Notification;
-import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.RuntimeErrorException;
-import javax.management.remote.JMXConnectionNotification;
-import javax.management.remote.JMXPrincipal;
import javax.management.remote.MBeanServerForwarder;
import javax.security.auth.Subject;
import java.lang.reflect.InvocationHandler;
@@ -51,27 +47,32 @@ import java.lang.reflect.Proxy;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.util.Arrays;
-import java.util.Map;
-import java.util.Set;
/**
* This class can be used by the JMXConnectorServer as an InvocationHandler for the mbean operations. It delegates
* JMX access decisions to the SecurityPlugin.
*/
-public class MBeanInvocationHandlerImpl implements InvocationHandler, NotificationListener
+public class MBeanInvocationHandlerImpl implements InvocationHandler
{
private static final Logger _logger = Logger.getLogger(MBeanInvocationHandlerImpl.class);
- private final IApplicationRegistry _appRegistry = ApplicationRegistry.getInstance();
private final static String DELEGATE = "JMImplementation:type=MBeanServerDelegate";
private MBeanServer _mbs;
- private final ManagementActor _logActor = new ManagementActor(_appRegistry.getRootMessageLogger());
- private final boolean _managementRightsInferAllAccess =
- _appRegistry.getConfiguration().getManagementRightsInferAllAccess();
+ private final ManagementActor _logActor;
- public static MBeanServerForwarder newProxyInstance()
+ private final boolean _managementRightsInferAllAccess;
+ private final Broker _broker;
+
+ MBeanInvocationHandlerImpl(Broker broker)
+ {
+ _managementRightsInferAllAccess = Boolean.valueOf(System.getProperty(BrokerProperties.PROPERTY_MANAGEMENT_RIGHTS_INFER_ALL_ACCESS, "true"));
+ _broker = broker;
+ _logActor = new ManagementActor(broker.getRootMessageLogger());
+ }
+
+ public static MBeanServerForwarder newProxyInstance(Broker broker)
{
- final InvocationHandler handler = new MBeanInvocationHandlerImpl();
+ final InvocationHandler handler = new MBeanInvocationHandlerImpl(broker);
final Class<?>[] interfaces = new Class[] { MBeanServerForwarder.class };
Object proxy = Proxy.newProxyInstance(MBeanServerForwarder.class.getClassLoader(), interfaces, handler);
@@ -101,7 +102,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
{
ObjectName mbean = (ObjectName) args[0];
- if(!DefaultManagedObject.DOMAIN.equalsIgnoreCase(mbean.getDomain()))
+ if(!ManagedObject.DOMAIN.equalsIgnoreCase(mbean.getDomain()))
{
return true;
}
@@ -151,11 +152,13 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
return method.invoke(_mbs, args);
}
- // Retrieve JMXPrincipal from Subject
- Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
- if (principals == null || principals.isEmpty())
+ try
+ {
+ AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject);
+ }
+ catch(Exception e)
{
- throw new SecurityException("Access denied: no JMX principal");
+ throw new SecurityException("Access denied: no authenticated principal", e);
}
// Save the subject
@@ -211,11 +214,16 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
SecurityManager security;
if (vhost == null)
{
- security = _appRegistry.getSecurityManager();
+ security = _broker.getSecurityManager();
}
else
{
- security = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhost).getSecurityManager();
+ VirtualHost virtualHost = _broker.findVirtualHostByName(vhost);
+ if (virtualHost == null)
+ {
+ throw new IllegalArgumentException("Virtual host with name '" + vhost + "' is not found.");
+ }
+ security = virtualHost.getSecurityManager();
}
methodName = getMethodName(method, args);
@@ -360,50 +368,5 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
return (methodName.startsWith("query") || methodName.startsWith("get") || methodName.startsWith("is"));
}
- /**
- * Receives notifications from the MBeanServer.
- */
- public void handleNotification(final Notification notification, final Object handback)
- {
- assert notification instanceof JMXConnectionNotification;
-
- final String connectionId = ((JMXConnectionNotification) notification).getConnectionId();
- final String type = notification.getType();
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Notification connectionId : " + connectionId + " type : " + type
- + " Notification handback : " + handback);
- }
-
- // Normally JMXManagedObjectRegistry provides a Map as handback data containing a map
- // between connection id and username.
- String user = null;
- if (handback instanceof Map)
- {
- final Map<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));
- }
- }
}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java
index 83909dbe72..b80ddc7fac 100644
--- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java
@@ -21,17 +21,16 @@
package org.apache.qpid.server.jmx;
-import java.util.ServiceLoader;
-
import javax.management.JMException;
import javax.management.StandardMBean;
import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.plugin.QpidServiceLoader;
/**
* A provider of an mbean implementation.
*
- * Provider implementations are advertised as services and loaded via {@link ServiceLoader}.
+ * Provider implementations are advertised as services and loaded by a {@link QpidServiceLoader}.
*/
public interface MBeanProvider
{
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporter.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporter.java
new file mode 100644
index 0000000000..ae0574dc21
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporter.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.jmx;
+
+import static javax.management.remote.JMXConnectionNotification.CLOSED;
+import static javax.management.remote.JMXConnectionNotification.FAILED;
+import static javax.management.remote.JMXConnectionNotification.OPENED;
+
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.remote.JMXConnectionNotification;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.RootMessageLogger;
+import org.apache.qpid.server.logging.actors.ManagementActor;
+import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
+
+public class ManagementLogonLogoffReporter implements NotificationListener, NotificationFilter
+{
+ private static final Logger LOGGER = Logger.getLogger(ManagementLogonLogoffReporter.class);
+ private final RootMessageLogger _rootMessageLogger;
+ private final UsernameAccessor _usernameAccessor;
+
+ public ManagementLogonLogoffReporter(RootMessageLogger rootMessageLogger, UsernameAccessor usernameAccessor)
+ {
+ _rootMessageLogger = rootMessageLogger;
+ _usernameAccessor = usernameAccessor;
+ }
+
+ @Override
+ public void handleNotification(final Notification notification, final Object handback)
+ {
+ final String connectionId = ((JMXConnectionNotification) notification).getConnectionId();
+ final String type = notification.getType();
+
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Notification connectionId : " + connectionId + " type : " + type);
+ }
+
+ String user = _usernameAccessor.getUsernameForConnectionId(connectionId);
+
+ // If user is still null, fallback to an unordered list of Principals from the connection id.
+ if (user == null)
+ {
+ final String[] splitConnectionId = connectionId.split(" ");
+ user = splitConnectionId[1];
+ }
+
+ // use a separate instance of actor as subject is not set on connect/disconnect
+ // we need to pass principal name explicitly into log actor
+ LogActor logActor = new ManagementActor(_rootMessageLogger, user);
+ if (JMXConnectionNotification.OPENED.equals(type))
+ {
+ logActor.message(ManagementConsoleMessages.OPEN(user));
+ }
+ else if (JMXConnectionNotification.CLOSED.equals(type) ||
+ JMXConnectionNotification.FAILED.equals(type))
+ {
+ logActor.message(ManagementConsoleMessages.CLOSE(user));
+ }
+ }
+
+ @Override
+ public boolean isNotificationEnabled(Notification notification)
+ {
+ return notification instanceof JMXConnectionNotification && isLogonTypeEvent(notification);
+ }
+
+ private boolean isLogonTypeEvent(Notification notification)
+ {
+ final String type = notification.getType();
+ return CLOSED.equals(type) || FAILED.equals(type) || OPENED.equals(type);
+ }
+
+}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameAccessor.java
index 84a66232ce..0cbb0d2687 100644
--- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameAccessor.java
@@ -15,25 +15,12 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
+ *
*/
-package org.apache.qpid.systest.management.jmx;
-
-import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.tools.security.Passwd;
+package org.apache.qpid.server.jmx;
-public class UserManagementWithBase64MD5PasswordsTest extends UserManagementTest
+public interface UsernameAccessor
{
- @Override
- protected Passwd createPasswordEncodingUtility()
- {
- return new Passwd();
- }
-
- @Override
- protected Class<? extends PrincipalDatabase> getPrincipalDatabaseImplClass()
- {
- return Base64MD5PasswordFilePrincipalDatabase.class;
- }
+ public String getUsernameForConnectionId(String connectionId);
}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameCachingRMIJRMPServer.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameCachingRMIJRMPServer.java
new file mode 100644
index 0000000000..838e9e5664
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameCachingRMIJRMPServer.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.jmx;
+
+import static javax.management.remote.JMXConnectionNotification.CLOSED;
+import static javax.management.remote.JMXConnectionNotification.FAILED;
+
+import java.io.IOException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.remote.JMXConnectionNotification;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.rmi.RMIConnection;
+import javax.management.remote.rmi.RMIJRMPServerImpl;
+import javax.security.auth.Subject;
+
+import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
+
+/**
+ * An implementation of RMIJRMPServerImpl that caches the usernames of users as they log-on
+ * and makes the same available via {@link UsernameAccessor#getUsernameForConnectionId(String)}.
+ *
+ * Caller is responsible for installing this object as a {@link NotificationListener} of the
+ * {@link JMXConnectorServer} so the cache entries are removed as the clients disconnect.
+ *
+ */
+public class UsernameCachingRMIJRMPServer extends RMIJRMPServerImpl implements NotificationListener, NotificationFilter, UsernameAccessor
+{
+ // ConnectionId is guaranteed to be unique per client connection, according to the JMX spec.
+ private final Map<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
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java
deleted file mode 100644
index beffb4eaa9..0000000000
--- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.jmx.mbeans;
-
-import org.apache.qpid.management.common.mbeans.ConfigurationManagement;
-import org.apache.qpid.server.jmx.AMQManagedObject;
-import org.apache.qpid.server.jmx.ManagedObject;
-import org.apache.qpid.server.jmx.ManagedObjectRegistry;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-
-import javax.management.JMException;
-import javax.management.NotCompliantMBeanException;
-
-public class ConfigurationManagementMBean extends AMQManagedObject implements ConfigurationManagement
-{
-
- public ConfigurationManagementMBean(ManagedObjectRegistry registry) throws JMException
- {
- super(ConfigurationManagement.class, ConfigurationManagement.TYPE, registry);
- register();
- }
-
- public String getObjectInstanceName()
- {
- return ConfigurationManagement.TYPE;
- }
-
- public void reloadSecurityConfiguration() throws Exception
- {
- ApplicationRegistry.getInstance().getConfiguration().reparseConfigFileSecuritySections();
- }
-
- @Override
- public ManagedObject getParentObject()
- {
- return null;
- }
-}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java
index 0dac8ebe37..d6f4b5d8c9 100644
--- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java
@@ -26,7 +26,7 @@ import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
import org.apache.qpid.server.jmx.AMQManagedObject;
import org.apache.qpid.server.jmx.ManagedObject;
import org.apache.qpid.server.jmx.ManagedObjectRegistry;
-import org.apache.qpid.server.logging.log4j.LoggingFacade;
+import org.apache.qpid.server.logging.log4j.LoggingManagementFacade;
import org.apache.qpid.server.logging.log4j.LoggingFacadeException;
import javax.management.JMException;
@@ -55,7 +55,8 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
private static final TabularType LOGGER_LEVEL_TABULAR_TYE;
private static final CompositeType LOGGER_LEVEL_COMPOSITE_TYPE;
- private final LoggingFacade _configurator;
+ private final LoggingManagementFacade _loggingManagementFacade;
+ private final String[] _allAvailableLogLevels;
static
{
@@ -77,12 +78,13 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
throw new ExceptionInInitializerError(e);
}
}
-
- public LoggingManagementMBean(LoggingFacade configurator, ManagedObjectRegistry registry) throws JMException
+
+ public LoggingManagementMBean(LoggingManagementFacade loggingManagementFacade, ManagedObjectRegistry registry) throws JMException
{
super(LoggingManagement.class, LoggingManagement.TYPE, registry);
register();
- _configurator = configurator;
+ _loggingManagementFacade = loggingManagementFacade;
+ _allAvailableLogLevels = buildAllAvailableLoggerLevelsWithInheritedPsuedoLogLevel(_loggingManagementFacade);
}
@Override
@@ -100,30 +102,26 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
@Override
public Integer getLog4jLogWatchInterval()
{
- return _configurator.getLog4jLogWatchInterval();
+ return _loggingManagementFacade.getLog4jLogWatchInterval();
}
@Override
public String[] getAvailableLoggerLevels()
{
- List<String> levels = _configurator.getAvailableLoggerLevels();
- List<String> mbeanLevels = new ArrayList<String>(levels);
- mbeanLevels.add(INHERITED_PSUEDO_LOG_LEVEL);
-
- return mbeanLevels.toArray(new String[mbeanLevels.size()]);
+ return _allAvailableLogLevels;
}
@Override
public TabularData viewEffectiveRuntimeLoggerLevels()
{
- Map<String, String> levels = _configurator.retrieveRuntimeLoggersLevels();
+ Map<String, String> levels = _loggingManagementFacade.retrieveRuntimeLoggersLevels();
return createTabularDataFromLevelsMap(levels);
}
@Override
public String getRuntimeRootLoggerLevel()
{
- return _configurator.retrieveRuntimeRootLoggerLevel();
+ return _loggingManagementFacade.retrieveRuntimeRootLoggerLevel();
}
@Override
@@ -139,7 +137,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
return false;
}
- _configurator.setRuntimeRootLoggerLevel(level);
+ _loggingManagementFacade.setRuntimeRootLoggerLevel(level);
return true;
}
@@ -159,7 +157,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
try
{
- _configurator.setRuntimeLoggerLevel(logger, validatedLevel);
+ _loggingManagementFacade.setRuntimeLoggerLevel(logger, validatedLevel);
}
catch (LoggingFacadeException e)
{
@@ -175,7 +173,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
Map<String,String> levels;
try
{
- levels = _configurator.retrieveConfigFileLoggersLevels();
+ levels = _loggingManagementFacade.retrieveConfigFileLoggersLevels();
}
catch (LoggingFacadeException e)
{
@@ -191,7 +189,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
{
try
{
- return _configurator.retrieveConfigFileRootLoggerLevel().toUpperCase();
+ return _loggingManagementFacade.retrieveConfigFileRootLoggerLevel().toUpperCase();
}
catch (LoggingFacadeException e)
{
@@ -216,7 +214,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
try
{
- _configurator.setConfigFileLoggerLevel(logger, validatedLevel);
+ _loggingManagementFacade.setConfigFileLoggerLevel(logger, validatedLevel);
}
catch (LoggingFacadeException e)
{
@@ -241,7 +239,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
try
{
- _configurator.setConfigFileRootLoggerLevel(level);
+ _loggingManagementFacade.setConfigFileRootLoggerLevel(level);
return true;
}
catch (LoggingFacadeException e)
@@ -257,7 +255,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
try
{
- _configurator.reload();
+ _loggingManagementFacade.reload();
}
catch (LoggingFacadeException e)
{
@@ -283,9 +281,8 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
private void validateLevelNotAllowingInherited(String level)
{
- final List<String> availableLoggerLevels = _configurator.getAvailableLoggerLevels();
- if (!availableLoggerLevels.contains(level)
- && !availableLoggerLevels.contains(String.valueOf(level).toUpperCase()))
+ final List<String> availableLoggerLevels = _loggingManagementFacade.getAvailableLoggerLevels();
+ if (level == null || !availableLoggerLevels.contains(level.toUpperCase()))
{
throw new IllegalArgumentException(level + " not known");
}
@@ -305,7 +302,6 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
return loggerLevelList;
}
-
private CompositeData createRow(String loggerName, String level)
{
Object[] itemData = {loggerName, level.toUpperCase()};
@@ -321,4 +317,13 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM
throw new RuntimeException(ode);
}
}
+
+ private String[] buildAllAvailableLoggerLevelsWithInheritedPsuedoLogLevel(LoggingManagementFacade loggingManagementFacade)
+ {
+ List<String> levels = loggingManagementFacade.getAvailableLoggerLevels();
+ List<String> mbeanLevels = new ArrayList<String>(levels);
+ mbeanLevels.add(INHERITED_PSUEDO_LOG_LEVEL);
+
+ return mbeanLevels.toArray(new String[mbeanLevels.size()]);
+ }
}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java
index 5c8b0f7194..94fac218ff 100644
--- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java
@@ -513,7 +513,6 @@ public class QueueMBean extends AMQManagedObject implements ManagedQueue, QueueN
{
_queue.visit(new QueueEntryVisitor()
{
-
public boolean visit(final QueueEntry entry)
{
final ServerMessage message = entry.getMessage();
@@ -525,11 +524,9 @@ public class QueueMBean extends AMQManagedObject implements ManagedQueue, QueueN
&& (messageId <= toMessageId))
{
txn.dequeue(entry);
- return true;
}
- return false;
}
- return true;
+ return false;
}
});
}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java
index 6990a40dee..51dea92775 100644
--- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java
@@ -65,7 +65,7 @@ public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtual
_managerMBean = new VirtualHostManagerMBean(this);
}
- private void initQueues() throws JMException
+ private void initQueues()
{
synchronized (_children)
{
@@ -73,13 +73,20 @@ public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtual
{
if(!_children.containsKey(queue))
{
- _children.put(queue, new QueueMBean(queue, this));
+ try
+ {
+ _children.put(queue, new QueueMBean(queue, this));
+ }
+ catch(Exception e)
+ {
+ LOGGER.error("Cannot create queue mbean for queue " + queue.getName(), e);
+ }
}
}
}
}
- private void initExchanges() throws JMException
+ private void initExchanges()
{
synchronized (_children)
{
@@ -87,13 +94,20 @@ public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtual
{
if(!_children.containsKey(exchange))
{
- _children.put(exchange, new ExchangeMBean(exchange, this));
+ try
+ {
+ _children.put(exchange, new ExchangeMBean(exchange, this));
+ }
+ catch(Exception e)
+ {
+ LOGGER.error("Cannot create exchange mbean for exchange " + exchange.getName(), e);
+ }
}
}
}
}
- private void initConnections() throws JMException
+ private void initConnections()
{
synchronized (_children)
{
@@ -101,7 +115,14 @@ public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtual
{
if(!_children.containsKey(conn))
{
- _children.put(conn, new ConnectionMBean(conn, this));
+ try
+ {
+ _children.put(conn, new ConnectionMBean(conn, this));
+ }
+ catch(Exception e)
+ {
+ LOGGER.error("Cannot create connection mbean for connection " + conn.getName(), e);
+ }
}
}
}
@@ -119,7 +140,7 @@ public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtual
public void stateChanged(ConfiguredObject object, State oldState, State newState)
{
- // ignore
+ // no-op
}
public void childAdded(ConfiguredObject object, ConfiguredObject child)
@@ -208,4 +229,35 @@ public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtual
return queues;
}
+
+ @Override
+ public void unregister() throws JMException
+ {
+ synchronized (_children)
+ {
+ for (AMQManagedObject mbean : _children.values())
+ {
+ if(mbean != null)
+ {
+ try
+ {
+ mbean.unregister();
+ }
+ catch(JMException e)
+ {
+ LOGGER.error("Failed to remove mbean for child : " + mbean, e);
+ }
+ }
+ }
+ _children.clear();
+ }
+ _managerMBean.unregister();
+ }
+
+ @Override
+ public void attributeSet(ConfiguredObject object, String attributeName, Object oldAttributeValue, Object newAttributeValue)
+ {
+ // no-op
+ }
+
}
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java
index b3dbbc424a..67ac1bdc7c 100644
--- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java
@@ -229,10 +229,9 @@ public class VirtualHostManagerMBean extends AbstractStatisticsGatheringMBean<Vi
return getObjectNameForSingleInstanceMBean();
}
- public synchronized boolean isStatisticsEnabled()
+ public boolean isStatisticsEnabled()
{
- updateStats();
- return false; //TODO - implement isStatisticsEnabled
+ return true;
}
}
diff --git a/java/broker-plugins/management-jmx/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.PluginFactory b/java/broker-plugins/management-jmx/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.PluginFactory
new file mode 100644
index 0000000000..8fa778269e
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.PluginFactory
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+org.apache.qpid.server.jmx.JMXManagementFactory
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/JMXManagementFactoryTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/JMXManagementFactoryTest.java
new file mode 100644
index 0000000000..5af1369239
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/JMXManagementFactoryTest.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.jmx;
+
+import static org.mockito.Mockito.mock;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.plugin.PluginFactory;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class JMXManagementFactoryTest extends QpidTestCase
+{
+ private final JMXManagementFactory _jmxManagementFactory = new JMXManagementFactory();
+ private final Map<String, Object> _attributes = new HashMap<String, Object>();
+ private final Broker _broker = mock(Broker.class);
+ private UUID _id = UUID.randomUUID();
+
+ public void testJMXConfigured() throws Exception
+ {
+ _attributes.put(PluginFactory.PLUGIN_TYPE, JMXManagement.PLUGIN_TYPE);
+
+ JMXManagement jmxManagement = (JMXManagement) _jmxManagementFactory.createInstance(_id, _attributes, _broker);
+
+ assertNotNull(jmxManagement);
+ assertEquals("Unexpected plugin type", JMXManagement.PLUGIN_TYPE, jmxManagement.getAttribute(JMXManagementFactory.PLUGIN_TYPE));
+ assertEquals("Unexpected default mbean platform", JMXManagement.DEFAULT_USE_PLATFORM_MBEAN_SERVER, jmxManagement.getAttribute(JMXManagement.USE_PLATFORM_MBEAN_SERVER));
+ assertEquals("Unexpected default name", JMXManagement.DEFAULT_NAME, jmxManagement.getAttribute(JMXManagement.NAME));
+ }
+
+ public void testCreateInstanceReturnsNullWhenPluginTypeMissing()
+ {
+ assertNull(_jmxManagementFactory.createInstance(_id, _attributes, _broker));
+ }
+
+ public void testCreateInstanceReturnsNullWhenPluginTypeNotJmx()
+ {
+ _attributes.put(PluginFactory.PLUGIN_TYPE, "notJmx");
+ assertNull(_jmxManagementFactory.createInstance(_id, _attributes, _broker));
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogActorTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogActorTest.java
deleted file mode 100644
index c1df9afc5d..0000000000
--- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogActorTest.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.jmx;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.management.JMException;
-import javax.management.MBeanServerConnection;
-import javax.management.ObjectName;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXConnectorFactory;
-import javax.management.remote.JMXServiceURL;
-
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.XMLConfiguration;
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.security.Result;
-import org.apache.qpid.server.security.SecurityPlugin;
-import org.apache.qpid.server.security.access.ObjectProperties;
-import org.apache.qpid.server.security.access.ObjectType;
-import org.apache.qpid.server.security.access.Operation;
-import org.apache.qpid.server.util.TestApplicationRegistry;
-import org.apache.qpid.test.utils.QpidTestCase;
-
-public class ManagementLogActorTest extends QpidTestCase
-{
- private ApplicationRegistry _registry;
- private JMXManagedObjectRegistry _objectRegistry;
- private int _registryPort;
- private int _connectorPort;
- private TestPlugin _plugin;
-
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- _registryPort = findFreePort();
- _connectorPort = getNextAvailable(_registryPort + 1);
- XMLConfiguration config = new XMLConfiguration();
- config.addProperty(ServerConfiguration.MGMT_JMXPORT_REGISTRYSERVER, _registryPort + "");
- config.addProperty(ServerConfiguration.MGMT_JMXPORT_CONNECTORSERVER, _connectorPort + "");
- _registry = new TestApplicationRegistry(new ServerConfiguration(config));
- ApplicationRegistry.initialise(_registry);
-
- _plugin = new TestPlugin();
- _registry.getSecurityManager().addHostPlugin(_plugin);
-
- _objectRegistry = new JMXManagedObjectRegistry();
- new TestMBean(_objectRegistry);
- _objectRegistry.start();
- }
-
- public void tearDown() throws Exception
- {
- _objectRegistry.close();
- ApplicationRegistry.remove();
- super.tearDown();
- }
-
- public void testPrincipalInLogMessage() throws Throwable
- {
- Map<String, Object> environment = new HashMap<String, Object>();
- environment.put(JMXConnector.CREDENTIALS, new String[] { "admin", "admin" });
- String urlString = "service:jmx:rmi:///jndi/rmi://localhost:" + _registryPort + "/jmxrmi";
- JMXServiceURL url = new JMXServiceURL(urlString);
- JMXConnector jmxConnector = JMXConnectorFactory.connect(url, environment);
- MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection();
- ObjectName mbeanObject = new ObjectName("org.apache.qpid:type=TestMBean,name=test");
-
- String actorLogMessage = (String) mbsc.getAttribute(mbeanObject, "ActorLogMessage");
-
- assertTrue("Unexpected log principal in security plugin", _plugin.getLogMessage().startsWith("[mng:admin"));
- assertTrue("Unexpected log principal in MBean", actorLogMessage.startsWith("[mng:admin"));
- }
-
- public static class TestMBean extends DefaultManagedObject implements CurrentActorRetriever
- {
-
- public TestMBean(ManagedObjectRegistry registry) throws JMException
- {
- super(CurrentActorRetriever.class, "TestMBean", registry);
- register();
- }
-
- @Override
- public String getObjectInstanceName()
- {
- return "test";
- }
-
- @Override
- public ManagedObject getParentObject()
- {
- return null;
- }
-
- @Override
- public String getActorLogMessage()
- {
- return CurrentActor.get().getLogMessage();
- }
-
- }
-
- public static interface CurrentActorRetriever
- {
- String getActorLogMessage();
- }
-
- public static class TestPlugin implements SecurityPlugin
- {
- private String _logMessage;
-
- @Override
- public void configure(ConfigurationPlugin config) throws ConfigurationException
- {
- }
-
- @Override
- public Result getDefault()
- {
- return Result.ALLOWED;
- }
-
- @Override
- public Result access(ObjectType objectType, Object instance)
- {
- return Result.ALLOWED;
- }
-
- @Override
- public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties)
- {
- // set thread name to work around logic in MangementActor
- Thread.currentThread().setName("RMI TCP Connection(1)-" + System.currentTimeMillis());
- _logMessage = CurrentActor.get().getLogMessage();
- return Result.ALLOWED;
- }
-
- public String getLogMessage()
- {
- return _logMessage;
- }
-
- }
-
-}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporterTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporterTest.java
new file mode 100644
index 0000000000..ba9c2cdaa5
--- /dev/null
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporterTest.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.jmx;
+
+import static javax.management.remote.JMXConnectionNotification.OPENED;
+import static javax.management.remote.JMXConnectionNotification.CLOSED;
+import static javax.management.remote.JMXConnectionNotification.FAILED;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+
+import javax.management.remote.JMXConnectionNotification;
+
+import org.apache.qpid.server.logging.LogActor;
+import org.apache.qpid.server.logging.RootMessageLogger;
+
+import junit.framework.TestCase;
+
+public class ManagementLogonLogoffReporterTest extends TestCase
+{
+ private static final String TEST_JMX_UNIQUE_CONNECTION_ID = "jmxconnectionid1 jmxuser,group";
+ private static final String TEST_USER = "jmxuser";
+
+ private ManagementLogonLogoffReporter _reporter;
+ private UsernameAccessor _usernameAccessor;
+ private RootMessageLogger _rootMessageLogger;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ _usernameAccessor = mock(UsernameAccessor.class);
+ _rootMessageLogger = mock(RootMessageLogger.class);
+ // Enable messaging so we can valid the generated strings
+ when(_rootMessageLogger.isMessageEnabled(any(LogActor.class), anyString())).thenReturn(true);
+
+ _reporter = new ManagementLogonLogoffReporter(_rootMessageLogger, _usernameAccessor);
+ }
+
+ public void testOpenedNotification()
+ {
+ when(_usernameAccessor.getUsernameForConnectionId(TEST_JMX_UNIQUE_CONNECTION_ID)).thenReturn(TEST_USER);
+ JMXConnectionNotification openNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, OPENED);
+
+ _reporter.handleNotification(openNotification, null);
+
+ verify(_rootMessageLogger).rawMessage("[main] MNG-1007 : Open : User jmxuser", "qpid.message.managementconsole.open");
+ }
+
+ public void testClosedNotification()
+ {
+ when(_usernameAccessor.getUsernameForConnectionId(TEST_JMX_UNIQUE_CONNECTION_ID)).thenReturn(TEST_USER);
+ JMXConnectionNotification closeNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, CLOSED);
+
+ _reporter.handleNotification(closeNotification, null);
+
+ verify(_rootMessageLogger).rawMessage("[main] MNG-1008 : Close : User jmxuser", "qpid.message.managementconsole.close");
+ }
+
+ public void tesNotifiedForLogOnTypeEvents()
+ {
+ JMXConnectionNotification openNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, OPENED);
+ JMXConnectionNotification closeNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, CLOSED);
+ JMXConnectionNotification failedNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, FAILED);
+
+ assertTrue(_reporter.isNotificationEnabled(openNotification));
+ assertTrue(_reporter.isNotificationEnabled(closeNotification));
+ assertTrue(_reporter.isNotificationEnabled(failedNotification));
+
+ JMXConnectionNotification otherNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, "other");
+ assertFalse(_reporter.isNotificationEnabled(otherNotification));
+ }
+
+ private JMXConnectionNotification createMockNotification(String connectionId, String notificationType)
+ {
+ JMXConnectionNotification notification = mock(JMXConnectionNotification.class);
+ when(notification.getConnectionId()).thenReturn(connectionId);
+ when(notification.getType()).thenReturn(notificationType);
+ return notification;
+ }
+}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java
index ae1be5db00..0f33e78d03 100644
--- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java
+++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java
@@ -39,7 +39,7 @@ import junit.framework.TestCase;
import org.apache.qpid.management.common.mbeans.LoggingManagement;
import org.apache.qpid.server.jmx.ManagedObjectRegistry;
-import org.apache.qpid.server.logging.log4j.LoggingFacade;
+import org.apache.qpid.server.logging.log4j.LoggingManagementFacade;
public class LoggingManagementMBeanTest extends TestCase
{
@@ -47,13 +47,13 @@ public class LoggingManagementMBeanTest extends TestCase
private static final String TEST_LEVEL2 = "LEVEL2";
private LoggingManagementMBean _loggingMBean;
- private LoggingFacade _mockLoggingFacade;
+ private LoggingManagementFacade _mockLoggingFacade;
private ManagedObjectRegistry _mockManagedObjectRegistry;
@Override
protected void setUp() throws Exception
{
- _mockLoggingFacade = mock(LoggingFacade.class);
+ _mockLoggingFacade = mock(LoggingManagementFacade.class);
final List<String> listOfLevels = new ArrayList<String>()
{{
add(TEST_LEVEL1);
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java
deleted file mode 100644
index 7473a4d3e7..0000000000
--- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.qpid.systest.management.jmx;
-
-import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedExchange;
-import org.apache.qpid.test.utils.JMXTestUtils;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-/**
- * Tests the JMX API for the Managed Broker.
- *
- */
-public class BrokerManagementTest extends QpidBrokerTestCase
-{
- private static final String VIRTUAL_HOST = "test";
-
- /**
- * JMX helper.
- */
- private JMXTestUtils _jmxUtils;
- private ManagedBroker _managedBroker;
-
- public void setUp() throws Exception
- {
- _jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
- super.setUp();
- _jmxUtils.open();
- _managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST);
- }
-
- public void tearDown() throws Exception
- {
- if (_jmxUtils != null)
- {
- _jmxUtils.close();
- }
- super.tearDown();
- }
-
- /**
- * Tests queue creation/deletion also verifying the automatic binding to the default exchange.
- */
- public void testCreateQueueAndDeletion() throws Exception
- {
- final String queueName = getTestQueueName();
- final ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString());
-
- // Check that bind does not exist before queue creation
- assertFalse("Binding to " + queueName + " should not exist in default exchange before queue creation",
- defaultExchange.bindings().containsKey(new String[] {queueName}));
-
- _managedBroker.createNewQueue(queueName, "testowner", true);
-
- // Ensure the queue exists
- assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName));
- assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName));
-
- // Now verify that the default exchange has been bound.
- assertTrue("Binding to " + queueName + " should exist in default exchange after queue creation",
- defaultExchange.bindings().containsKey(new String[] {queueName}));
-
- // Now delete the queue
- _managedBroker.deleteQueue(queueName);
-
- // Finally ensure that the binding has been removed.
- assertFalse("Binding to " + queueName + " should not exist in default exchange after queue deletion",
- defaultExchange.bindings().containsKey(new String[] {queueName}));
- }
-
- /**
- * Tests exchange creation/deletion via JMX API.
- */
- public void testCreateExchangeAndUnregister() throws Exception
- {
- String exchangeName = getTestName();
- _managedBroker.createNewExchange(exchangeName, "topic", true);
-
- ManagedExchange exchange = _jmxUtils.getManagedExchange(exchangeName);
- assertNotNull("Exchange should exist", exchange);
-
- _managedBroker.unregisterExchange(exchangeName);
- }
-
- /**
- * Tests that it is disallowed to unregister the default exchange.
- */
- public void testUnregisterOfDefaultExchangeDisallowed() throws Exception
- {
- String defaultExchangeName = ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString();
-
- try
- {
- _managedBroker.unregisterExchange(defaultExchangeName);
- fail("Exception not thrown");
- }
- catch (UnsupportedOperationException e)
- {
- // PASS
- assertEquals("'<<default>>' is a reserved exchange and can't be deleted", e.getMessage());
- }
- final ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(defaultExchangeName);
- assertNotNull("Exchange should exist", defaultExchange);
- }
-
-}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java
deleted file mode 100644
index 28d7bf4aed..0000000000
--- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.qpid.systest.management.jmx;
-
-import java.io.IOException;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.jms.Connection;
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.Queue;
-import javax.jms.Session;
-import javax.management.JMException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularData;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.qpid.common.QpidProperties;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.test.utils.JMXTestUtils;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-public class ConnectionManagementTest extends QpidBrokerTestCase
-{
- private static final String VIRTUAL_HOST_NAME = "test";
-
- private JMXTestUtils _jmxUtils;
- private Connection _connection;
-
- public void setUp() throws Exception
- {
- _jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp(); // modifies broker config therefore must be done before super.setUp()
- super.setUp();
- _jmxUtils.open();
- }
-
- public void tearDown() throws Exception
- {
- try
- {
- if (_jmxUtils != null)
- {
- _jmxUtils.close();
- }
- }
- finally
- {
- super.tearDown();
- }
- }
-
- public void testNumberOfManagedConnectionsMatchesNumberOfClientConnections() throws Exception
- {
- assertEquals("Expected no managed connections", 0, getManagedConnections().size());
-
- _connection = getConnection();
- assertEquals("Expected one managed connection", 1, getManagedConnections().size());
-
- _connection.close();
- assertEquals("Expected no managed connections after client connection closed", 0, getManagedConnections().size());
- }
-
- public void testGetAttributes() throws Exception
- {
- _connection = getConnection();
- final ManagedConnection mBean = getConnectionMBean();
-
- checkAuthorisedId(mBean);
- checkClientVersion(mBean);
- checkClientId(mBean);
- }
-
- public void testNonTransactedSession() throws Exception
- {
- _connection = getConnection();
-
- boolean transactional = false;
- boolean flowBlocked = false;
-
- _connection.createSession(transactional, Session.AUTO_ACKNOWLEDGE);
-
- final ManagedConnection mBean = getConnectionMBean();
- final CompositeDataSupport row = getTheOneChannelRow(mBean);
- assertChannelRowData(row, 0, transactional, flowBlocked);
- }
-
- public void testTransactedSessionWithUnackMessages() throws Exception
- {
- _connection = getConnection();
- _connection.start();
-
- boolean transactional = true;
- int numberOfMessages = 2;
- final Session session = _connection.createSession(transactional, Session.SESSION_TRANSACTED);
- final Destination destination = session.createQueue(getTestQueueName());
- final MessageConsumer consumer = session.createConsumer(destination);
-
- sendMessage(session, destination, numberOfMessages);
- receiveMessagesWithoutCommit(consumer, numberOfMessages);
-
- final ManagedConnection mBean = getConnectionMBean();
- final CompositeDataSupport row = getTheOneChannelRow(mBean);
- boolean flowBlocked = false;
- assertChannelRowData(row, numberOfMessages, transactional, flowBlocked);
-
- // check that commit advances the lastIoTime
- final Date initialLastIOTime = mBean.getLastIoTime();
- session.commit();
- assertTrue("commit should have caused last IO time to advance", mBean.getLastIoTime().after(initialLastIOTime));
-
- // check that channels() now returns one session with no unacknowledged messages
- final CompositeDataSupport rowAfterCommit = getTheOneChannelRow(mBean);
- final Number unackCountAfterCommit = (Number) rowAfterCommit.get(ManagedConnection.UNACKED_COUNT);
- assertEquals("Unexpected number of unacknowledged messages", 0, unackCountAfterCommit);
- }
-
-
- public void testProducerFlowBlocked() throws Exception
- {
- _connection = getConnection();
- _connection.start();
-
- String queueName = getTestQueueName();
- Session session = _connection.createSession(true, Session.SESSION_TRANSACTED);
- Queue queue = session.createQueue(queueName);
- createQueueOnBroker(session, queue);
-
- ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
- managedQueue.setFlowResumeCapacity(DEFAULT_MESSAGE_SIZE * 2l);
- managedQueue.setCapacity(DEFAULT_MESSAGE_SIZE * 3l);
-
- final ManagedConnection managedConnection = getConnectionMBean();
-
- // Check that producer flow is not block before test
- final CompositeDataSupport rowBeforeSend = getTheOneChannelRow(managedConnection);
- assertFlowBlocked(rowBeforeSend, false);
-
-
- // Check that producer flow does not become block too soon
- sendMessage(session, queue, 3);
- final CompositeDataSupport rowBeforeFull = getTheOneChannelRow(managedConnection);
- assertFlowBlocked(rowBeforeFull, false);
-
- // Fourth message will over-fill the queue (but as we are not sending more messages, client thread wont't block)
- sendMessage(session, queue, 1);
- final CompositeDataSupport rowAfterFull = getTheOneChannelRow(managedConnection);
- assertFlowBlocked(rowAfterFull, true);
-
- // Consume two to bring the queue down to the resume capacity
- MessageConsumer consumer = session.createConsumer(queue);
- assertNotNull("Could not receive first message", consumer.receive(1000));
- assertNotNull("Could not receive second message", consumer.receive(1000));
- session.commit();
-
- // Check that producer flow is no longer blocked
- final CompositeDataSupport rowAfterReceive = getTheOneChannelRow(managedConnection);
- assertFlowBlocked(rowAfterReceive, false);
- }
-
- private void createQueueOnBroker(Session session, Destination destination) throws JMSException
- {
- session.createConsumer(destination).close(); // Create a consumer only to cause queue creation
- }
-
- private void assertChannelRowData(final CompositeData row, int unacknowledgedMessages, boolean isTransactional, boolean flowBlocked)
- {
- assertNotNull(row);
- assertEquals("Unexpected transactional flag", isTransactional, row.get(ManagedConnection.TRANSACTIONAL));
- assertEquals("Unexpected unacknowledged message count", unacknowledgedMessages, row.get(ManagedConnection.UNACKED_COUNT));
- assertEquals("Unexpected flow blocked", flowBlocked, row.get(ManagedConnection.FLOW_BLOCKED));
- }
-
- private void assertFlowBlocked(final CompositeData row, boolean flowBlocked)
- {
- assertNotNull(row);
- assertEquals("Unexpected flow blocked", flowBlocked, row.get(ManagedConnection.FLOW_BLOCKED));
- }
-
- private void checkAuthorisedId(ManagedConnection mBean) throws Exception
- {
- assertEquals("Unexpected authorized id", GUEST_USERNAME, mBean.getAuthorizedId());
- }
-
- private void checkClientVersion(ManagedConnection mBean) throws Exception
- {
- String expectedVersion = QpidProperties.getReleaseVersion();
- assertTrue(StringUtils.isNotBlank(expectedVersion));
-
- assertEquals("Unexpected version", expectedVersion, mBean.getVersion());
- }
-
- private void checkClientId(ManagedConnection mBean) throws Exception
- {
- String expectedClientId = _connection.getClientID();
- assertTrue(StringUtils.isNotBlank(expectedClientId));
-
- assertEquals("Unexpected ClientId", expectedClientId, mBean.getClientId());
- }
-
- private ManagedConnection getConnectionMBean()
- {
- List<ManagedConnection> connections = getManagedConnections();
- assertNotNull("Connection MBean is not found", connections);
- assertEquals("Unexpected number of connection mbeans", 1, connections.size());
- final ManagedConnection mBean = connections.get(0);
- assertNotNull("Connection MBean is null", mBean);
- return mBean;
- }
-
- private List<ManagedConnection> getManagedConnections()
- {
- return _jmxUtils.getManagedConnections(VIRTUAL_HOST_NAME);
- }
-
- private CompositeDataSupport getTheOneChannelRow(final ManagedConnection mBean) throws Exception
- {
- TabularData channelsData = getChannelsDataWithRetry(mBean);
-
- assertEquals("Unexpected number of rows in channel table", 1, channelsData.size());
-
- @SuppressWarnings("unchecked")
- final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) channelsData.values().iterator();
- final CompositeDataSupport row = rowItr.next();
- return row;
- }
-
- private void receiveMessagesWithoutCommit(final MessageConsumer consumer, int numberOfMessages) throws Exception
- {
- for (int i = 0; i < numberOfMessages; i++)
- {
- final Message m = consumer.receive(1000l);
- assertNotNull("Message " + i + " is not received", m);
- }
- }
-
- private TabularData getChannelsDataWithRetry(final ManagedConnection mBean)
- throws IOException, JMException
- {
- TabularData channelsData = mBean.channels();
- int retries = 0;
- while(channelsData.size() == 0 && retries < 5)
- {
- sleep();
- channelsData = mBean.channels();
- retries++;
- }
- return channelsData;
- }
-
- private void sleep()
- {
- try
- {
- Thread.sleep(50);
- }
- catch (InterruptedException ie)
- {
- Thread.currentThread().interrupt();
- }
- }}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java
deleted file mode 100644
index ac6730638e..0000000000
--- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.qpid.systest.management.jmx;
-
-import java.io.File;
-import java.util.List;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularData;
-
-import org.apache.qpid.management.common.mbeans.LoggingManagement;
-import org.apache.qpid.server.jmx.mbeans.LoggingManagementMBeanTest;
-import org.apache.qpid.server.logging.log4j.LoggingFacadeTest;
-import org.apache.qpid.test.utils.JMXTestUtils;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-import org.apache.qpid.util.FileUtils;
-import org.apache.qpid.util.LogMonitor;
-
-/**
- * System test for Logging Management. <b>These tests rely on value set within
- * test-profiles/log4j-test.xml</b>.
- *
- * @see LoggingManagementMBeanTest
- * @see LoggingFacadeTest
- *
- */
-public class LoggingManagementTest extends QpidBrokerTestCase
-{
- private JMXTestUtils _jmxUtils;
- private LoggingManagement _loggingManagement;
- private LogMonitor _monitor;
-
- public void setUp() throws Exception
- {
- _jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
-
- // System test normally run with log for4j test config from beneath test-profiles. We need to
- // copy it as some of our tests write to this file.
-
- File tmpLogFile = File.createTempFile("log4j" + "." + getName(), ".xml");
- tmpLogFile.deleteOnExit();
- FileUtils.copy(_logConfigFile, tmpLogFile);
-
- _logConfigFile = tmpLogFile;
-
- super.setUp();
- _jmxUtils.open();
-
- _loggingManagement = _jmxUtils.getLoggingManagement();
- _monitor = new LogMonitor(_outputFile);
- }
-
- public void tearDown() throws Exception
- {
- try
- {
- if (_jmxUtils != null)
- {
- _jmxUtils.close();
- }
- }
- finally
- {
- super.tearDown();
- }
- }
-
- public void testViewEffectiveRuntimeLoggerLevels() throws Exception
- {
- final String qpidMainLogger = "org.apache.qpid";
-
- TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels();
- final CompositeData row = table.get(new String[] {qpidMainLogger} );
- assertChannelRow(row, qpidMainLogger, "DEBUG");
- }
-
- public void testViewConfigFileLoggerLevels() throws Exception
- {
- final String operationalLoggingLogger = "qpid.message";
-
- TabularData table = _loggingManagement.viewConfigFileLoggerLevels();
- final CompositeData row = table.get(new String[] {operationalLoggingLogger} );
- assertChannelRow(row, operationalLoggingLogger, "INFO");
- }
-
- public void testTurnOffOrgApacheQpidAtRuntime() throws Exception
- {
- final String logger = "org.apache.qpid";
- _monitor.markDiscardPoint();
- _loggingManagement.setRuntimeLoggerLevel(logger, "OFF");
-
- List<String> matches = _monitor.findMatches("Setting level to OFF for logger 'org.apache.qpid'");
- assertEquals(1, matches.size());
-
- TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels();
- final CompositeData row1 = table.get(new String[] {logger} );
- assertChannelRow(row1, logger, "OFF");
- }
-
- public void testChangesToConfigFileBecomeEffectiveAfterReload() throws Exception
- {
- final String operationalLoggingLogger = "qpid.message";
- assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO");
-
- _monitor.markDiscardPoint();
- _loggingManagement.setConfigFileLoggerLevel(operationalLoggingLogger, "OFF");
-
- List<String> matches = _monitor.findMatches("Setting level to OFF for logger 'qpid.message'");
- assertEquals(1, matches.size());
-
- assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO");
-
- _loggingManagement.reloadConfigFile();
-
- assertEffectiveLoggingLevel(operationalLoggingLogger, "OFF");
- }
-
- private void assertEffectiveLoggingLevel(String operationalLoggingLogger, String expectedLevel)
- {
- TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels();
- final CompositeData row1 = table.get(new String[] {operationalLoggingLogger} );
- assertChannelRow(row1, operationalLoggingLogger, expectedLevel);
- }
-
- private void assertChannelRow(final CompositeData row, String logger, String level)
- {
- assertNotNull("No row for " + logger, row);
- assertEquals("Unexpected logger name", logger, row.get(LoggingManagement.LOGGER_NAME));
- assertEquals("Unexpected level", level, row.get(LoggingManagement.LOGGER_LEVEL));
- }
-
-}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java
deleted file mode 100644
index 47b38381c5..0000000000
--- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.systest.management.jmx;
-
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-import org.apache.qpid.management.common.mbeans.ManagedExchange;
-import org.apache.qpid.server.logging.AbstractTestLogging;
-import org.apache.qpid.server.logging.subjects.AbstractTestLogSubject;
-import org.apache.qpid.test.utils.JMXTestUtils;
-
-import javax.jms.Connection;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.management.JMException;
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Test class to test if any change in the broker JMX code is affesting the management console
- * There are some hardcoding of management feature names and parameter names to create a customized
- * look in the console.
- */
-public class ManagementActorLoggingTest extends AbstractTestLogging
-{
- private JMXTestUtils _jmxUtils;
- private boolean _closed = false;
-
- @Override
- public void setUp() throws Exception
- {
- _jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
- super.setUp();
- _jmxUtils.open();
- }
-
- @Override
- public void tearDown() throws Exception
- {
- if(!_closed)
- {
- _jmxUtils.close();
- }
- super.tearDown();
- }
-
- /**
- * Description:
- * When a connected client has its connection closed via the Management Console this will be logged as a CON-1002 message.
- * Input:
- *
- * 1. Running Broker
- * 2. Connected Client
- * 3. Connection is closed via Management Console
- * Output:
- *
- * <date> CON-1002 : Close
- *
- * Validation Steps:
- * 4. The CON ID is correct
- * 5. This must be the last CON message for the Connection
- * 6. It must be preceded by a CON-1001 for this Connection
- *
- * @throws Exception - {@see ManagedConnection.closeConnection and #getConnection}
- * @throws java.io.IOException - if there is a problem reseting the log monitor
- */
- public void testConnectionCloseViaManagement() throws IOException, Exception
- {
- //Create a connection to the broker
- Connection connection = getConnection();
-
- // Monitor the connection for an exception being thrown
- // this should be a DisconnectionException but it is not this tests
- // job to valiate that. Only use the exception as a synchronisation
- // to check the log file for the Close message
- final CountDownLatch exceptionReceived = new CountDownLatch(1);
- connection.setExceptionListener(new ExceptionListener()
- {
- public void onException(JMSException e)
- {
- //Failover being attempted.
- exceptionReceived.countDown();
- }
- });
-
- //Remove the connection close from any 0-10 connections
- _monitor.markDiscardPoint();
-
- // Get a managedConnection
- ManagedConnection mangedConnection = _jmxUtils.getManagedObject(ManagedConnection.class, "org.apache.qpid:type=VirtualHost.Connection,*");
-
- //Close the connection
- mangedConnection.closeConnection();
-
- //Wait for the connection to close
- assertTrue("Timed out waiting for conneciton to report close",
- exceptionReceived.await(2, TimeUnit.SECONDS));
-
- //Validate results
- List<String> results = waitAndFindMatches("CON-1002");
-
- assertEquals("Unexpected Connection Close count", 1, results.size());
- }
-
- /**
- * Description:
- * Exchange creation is possible from the Management Console.
- * When an exchanged is created in this way then a EXH-1001 create message
- * is expected to be logged.
- * Input:
- *
- * 1. Running broker
- * 2. Connected Management Console
- * 3. Exchange Created via Management Console
- * Output:
- *
- * EXH-1001 : Create : [Durable] Type:<value> Name:<value>
- *
- * Validation Steps:
- * 4. The EXH ID is correct
- * 5. The correct tags are present in the message based on the create options
- *
- * @throws java.io.IOException - if there is a problem reseting the log monitor
- * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue}
- */
- public void testCreateExchangeDirectTransientViaManagementConsole() throws IOException, JMException
- {
- _monitor.markDiscardPoint();
-
- _jmxUtils.createExchange("test", getName(), "direct", false);
-
- // Validate
-
- //1 - ID is correct
- List<String> results = waitAndFindMatches("EXH-1001");
-
- assertEquals("More than one exchange creation found", 1, results.size());
-
- String log = getLogMessage(results, 0);
-
- // Validate correct exchange name
- assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName()));
-
- // Validate it was a management actor.
- String actor = fromActor(log);
- assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
- }
-
- public void testCreateExchangeTopicTransientViaManagementConsole() throws IOException, JMException
- {
- //Remove any previous exchange declares
- _monitor.markDiscardPoint();
-
- _jmxUtils.createExchange("test", getName(), "topic", false);
-
- // Validate
-
- //1 - ID is correct
- List<String> results = waitAndFindMatches("EXH-1001");
-
- assertEquals("More than one exchange creation found", 1, results.size());
-
- String log = getLogMessage(results, 0);
-
- // Validate correct exchange name
- assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName()));
-
- // Validate it was a management actor.
- String actor = fromActor(log);
- assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
-
- }
-
- public void testCreateExchangeFanoutTransientViaManagementConsole() throws IOException, JMException
- {
- //Remove any previous exchange declares
- _monitor.markDiscardPoint();
-
- _jmxUtils.createExchange("test", getName(), "fanout", false);
-
- // Validate
-
- //1 - ID is correct
- List<String> results = waitAndFindMatches("EXH-1001");
-
- assertEquals("More than one exchange creation found", 1, results.size());
-
- String log = getLogMessage(results, 0);
-
- // Validate correct exchange name
- assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName()));
-
- // Validate it was a management actor.
- String actor = fromActor(log);
- assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
-
- }
-
- public void testCreateExchangeHeadersTransientViaManagementConsole() throws IOException, JMException
- {
- //Remove any previous exchange declares
- _monitor.markDiscardPoint();
-
- _jmxUtils.createExchange("test", getName(), "headers", false);
-
- // Validate
-
- //1 - ID is correct
- List<String> results = waitAndFindMatches("EXH-1001");
-
- assertEquals("More than one exchange creation found", 1, results.size());
-
- String log = getLogMessage(results, 0);
-
- // Validate correct exchange name
- assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName()));
-
- // Validate it was a management actor.
- String actor = fromActor(log);
- assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
-
- }
-
- /**
- * Description:
- * Queue creation is possible from the Management Console. When a queue is created in this way then a QUE-1001 create message is expected to be logged.
- * Input:
- *
- * 1. Running broker
- * 2. Connected Management Console
- * 3. Queue Created via Management Console
- * Output:
- *
- * <date> QUE-1001 : Create : Transient Owner:<name>
- *
- * Validation Steps:
- * 4. The QUE ID is correct
- * 5. The correct tags are present in the message based on the create options
- *
- * @throws java.io.IOException - if there is a problem reseting the log monitor
- * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue}
- */
- public void testCreateQueueTransientViaManagementConsole() throws IOException, JMException
- {
- //Remove any previous queue declares
- _monitor.markDiscardPoint();
-
- _jmxUtils.createQueue("test", getName(), null, false);
-
- // Validate
-
- List<String> results = waitAndFindMatches("QUE-1001");
-
- assertEquals("More than one queue creation found", 1, results.size());
-
- String log = getLogMessage(results, 0);
-
- // Validate correct queue name
- String subject = fromSubject(log);
- assertEquals("Incorrect queue name created", getName(), AbstractTestLogSubject.getSlice("qu", subject));
-
- // Validate it was a management actor.
- String actor = fromActor(log);
- assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
- }
-
- /**
- * Description:
- * The ManagementConsole can be used to delete a queue. When this is done a QUE-1002 Deleted message must be logged.
- * Input:
- *
- * 1. Running Broker
- * 2. Queue created on the broker with no subscribers
- * 3. Management Console connected
- * 4. Queue is deleted via Management Console
- * Output:
- *
- * <date> QUE-1002 : Deleted
- *
- * Validation Steps:
- * 5. The QUE ID is correct
- *
- * @throws java.io.IOException - if there is a problem reseting the log monitor
- * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue}
- */
- public void testQueueDeleteViaManagementConsole() throws IOException, JMException
- {
- //Remove any previous queue declares
- _monitor.markDiscardPoint();
-
- _jmxUtils.createQueue("test", getName(), null, false);
-
- ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test");
-
- managedBroker.deleteQueue(getName());
-
- List<String> results = waitAndFindMatches("QUE-1002");
-
- assertEquals("More than one queue deletion found", 1, results.size());
-
- String log = getLog(results.get(0));
-
- // Validate correct binding
- String subject = fromSubject(log);
- assertEquals("Incorrect queue named in delete", getName(), AbstractTestLogSubject.getSlice("qu", subject));
-
- // Validate it was a management actor.
- String actor = fromActor(log);
- assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
-
- }
-
- /**
- * Description:
- * The binding of a Queue and an Exchange is done via a Binding. When this Binding is created via the Management Console a BND-1001 Create message will be logged.
- * Input:
- *
- * 1. Running Broker
- * 2. Connected Management Console
- * 3. Use Management Console to perform binding
- * Output:
- *
- * <date> BND-1001 : Create
- *
- * Validation Steps:
- * 4. The BND ID is correct
- * 5. This will be the first message for the given binding
- *
- * @throws java.io.IOException - if there is a problem reseting the log monitor
- * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.createNewBinding}
- */
- public void testBindingCreateOnDirectViaManagementConsole() throws IOException, JMException
- {
- //Remove any previous queue declares
- _monitor.markDiscardPoint();
-
- _jmxUtils.createQueue("test", getName(), null, false);
-
- ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.direct");
-
- managedExchange.createNewBinding(getName(), getName());
-
- List<String> results = waitAndFindMatches("BND-1001");
-
- assertEquals("Unexpected number of bindings logged", 2, results.size());
-
- String log = getLogMessage(results, 0);
-
- // Validate correct binding
- String subject = fromSubject(log);
- assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject));
- assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject));
-
- // Validate it was a management actor.
- String actor = fromActor(log);
- assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
- }
-
- public void testBindingCreateOnTopicViaManagementConsole() throws IOException, JMException
- {
- //Remove any previous queue declares
- _monitor.markDiscardPoint();
-
- _jmxUtils.createQueue("test", getName(), null, false);
-
- ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.topic");
-
- managedExchange.createNewBinding(getName(), getName());
-
- List<String> results = waitAndFindMatches("BND-1001");
-
- assertEquals("Unexpected number of bindings logged", 2, results.size());
-
- String log = getLogMessage(results, 0);
-
- // Validate correct binding
- String subject = fromSubject(log);
- assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject));
- assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject));
-
- // Validate it was a management actor.
- String actor = fromActor(log);
- assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
- }
-
- public void testBindingCreateOnFanoutViaManagementConsole() throws IOException, JMException
- {
- //Remove any previous queue declares
- _monitor.markDiscardPoint();
-
- _jmxUtils.createQueue("test", getName(), null, false);
-
- ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.fanout");
-
- managedExchange.createNewBinding(getName(), getName());
-
- List<String> results = waitAndFindMatches("BND-1001");
-
- assertEquals("Unexpected number of bindings logged", 2, results.size());
-
- String log = getLogMessage(results, 0);
-
- // Validate correct binding
- String subject = fromSubject(log);
- assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject));
- assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject));
-
- // Validate it was a management actor.
- String actor = fromActor(log);
- assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
- }
-
- /**
- * Description:
- * Bindings can be deleted so that a queue can be rebound with a different set of values. This can be performed via the Management Console
- * Input:
- *
- * 1. Running Broker
- * 2. Management Console connected
- * 3. Management Console is used to perform unbind.
- * Output:
- *
- * <date> BND-1002 : Deleted
- *
- * Validation Steps:
- * 4. The BND ID is correct
- * 5. There must have been a BND-1001 Create message first.
- * 6. This will be the last message for the given binding
- *
- * @throws java.io.IOException - if there is a problem reseting the log monitor or an issue with the JMX Connection
- * @throws javax.management.JMException - {@see #createExchange and ManagedBroker.unregisterExchange}
- */
- public void testUnRegisterExchangeViaManagementConsole() throws IOException, JMException
- {
- //Remove any previous queue declares
- _monitor.markDiscardPoint();
-
- _jmxUtils.createExchange("test", getName(), "direct", false);
-
- ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test");
-
- managedBroker.unregisterExchange(getName());
-
- List<String> results = waitAndFindMatches("EXH-1002");
-
- assertEquals("More than one exchange deletion found", 1, results.size());
-
- String log = getLog(results.get(0));
-
- // Validate correct binding
- String subject = fromSubject(log);
- assertEquals("Incorrect exchange named in delete", "direct/" + getName(), AbstractTestLogSubject.getSlice("ex", subject));
-
- // Validate it was a management actor.
- String actor = fromActor(log);
- assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
- }
-
-}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
deleted file mode 100644
index 6100d5a23e..0000000000
--- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.systest.management.jmx;
-
-
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.logging.AbstractTestLogging;
-import org.apache.qpid.test.utils.JMXTestUtils;
-import org.apache.qpid.util.LogMonitor;
-
-import java.io.File;
-import java.util.List;
-
-/**
- * Management Console Test Suite
- *
- * The Management Console test suite validates that the follow log messages as specified in the Functional Specification.
- *
- * This suite of tests validate that the management console messages occur correctly and according to the following format:
- *
- * MNG-1001 : Startup
- * MNG-1002 : Starting : <service> : Listening on port <Port>
- * MNG-1003 : Shutting down : <service> : port <Port>
- * MNG-1004 : Ready
- * MNG-1005 : Stopped
- * MNG-1006 : Using SSL Keystore : <path>
- * MNG-1007 : Open : User <username>
- * MNG-1008 : Close : User <username>
- */
-public class ManagementLoggingTest extends AbstractTestLogging
-{
- private static final String MNG_PREFIX = "MNG-";
-
- public void setUp() throws Exception
- {
- setLogMessagePrefix();
-
- // We either do this here or have a null check in tearDown.
- // As when this test is run against profiles other than java it will NPE
- _monitor = new LogMonitor(_outputFile);
- //We explicitly do not call super.setUp as starting up the broker is
- //part of the test case.
-
- }
-
- /**
- * Description:
- * Using the startup configuration validate that the management startup
- * message is logged correctly.
- * Input:
- * Standard configuration with management enabled
- * Output:
- *
- * <date> MNG-1001 : Startup
- *
- * Constraints:
- * This is the FIRST message logged by MNG
- * Validation Steps:
- *
- * 1. The BRK ID is correct
- * 2. This is the FIRST message logged by MNG
- */
- public void testManagementStartupEnabled() throws Exception
- {
- // This test only works on java brokers
- if (isJavaBroker())
- {
- startBrokerAndCreateMonitor(true, false);
-
- // Ensure we have received the MNG log msg.
- waitForMessage("MNG-1001");
-
- List<String> results = findMatches(MNG_PREFIX);
- // Validation
-
- assertTrue("MNGer message not logged", results.size() > 0);
-
- String log = getLogMessage(results, 0);
-
- //1
- validateMessageID("MNG-1001", log);
-
- //2
- //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J)
- results = findMatches("MNG-1001");
- assertEquals("Unexpected startup message count.",
- 2, results.size());
-
- //3
- assertEquals("Startup log message is not 'Startup'.", "Startup",
- getMessageString(log));
- }
- }
-
- /**
- * Description:
- * Verify that when management is disabled in the configuration file the
- * startup message is not logged.
- * Input:
- * Standard configuration with management disabled
- * Output:
- * NO MNG messages
- * Validation Steps:
- *
- * 1. Validate that no MNG messages are produced.
- */
- public void testManagementStartupDisabled() throws Exception
- {
- if (isJavaBroker())
- {
- startBrokerAndCreateMonitor(false, false);
-
- List<String> results = findMatches(MNG_PREFIX);
- // Validation
-
- assertEquals("MNGer messages logged", 0, results.size());
- }
- }
-
- /**
- * The two MNG-1002 messages are logged at the same time so lets test them
- * at the same time.
- *
- * Description:
- * Using the default configuration validate that the RMI Registry socket is
- * correctly reported as being opened
- *
- * Input:
- * The default configuration file
- * Output:
- *
- * <date> MESSAGE MNG-1002 : Starting : RMI Registry : Listening on port 8999
- *
- * Constraints:
- * The RMI ConnectorServer and Registry log messages do not have a prescribed order
- * Validation Steps:
- *
- * 1. The MNG ID is correct
- * 2. The specified port is the correct '8999'
- *
- * Description:
- * Using the default configuration validate that the RMI ConnectorServer
- * socket is correctly reported as being opened
- *
- * Input:
- * The default configuration file
- * Output:
- *
- * <date> MESSAGE MNG-1002 : Starting : RMI ConnectorServer : Listening on port 9099
- *
- * Constraints:
- * The RMI ConnectorServer and Registry log messages do not have a prescribed order
- * Validation Steps:
- *
- * 1. The MNG ID is correct
- * 2. The specified port is the correct '9099'
- */
- public void testManagementStartupRMIEntries() throws Exception
- {
- if (isJavaBroker())
- {
- startBrokerAndCreateMonitor(true, false);
-
- List<String> results = waitAndFindMatches("MNG-1002");
- // Validation
-
- //There will be 4 startup messages (two via SystemOut, and two via Log4J)
- assertEquals("Unexpected MNG-1002 message count", 4, results.size());
-
- String log = getLogMessage(results, 0);
-
- //1
- validateMessageID("MNG-1002", log);
-
- //Check the RMI Registry port is as expected
- int mPort = getManagementPort(getPort());
- assertTrue("RMI Registry port not as expected(" + mPort + ").:" + getMessageString(log),
- getMessageString(log).endsWith(String.valueOf(mPort)));
-
- log = getLogMessage(results, 2);
-
- //1
- validateMessageID("MNG-1002", log);
-
- // We expect the RMI Registry port (the defined 'management port') to be
- // 100 lower than the JMX RMIConnector Server Port (the actual JMX server)
- int jmxPort = mPort + ServerConfiguration.JMXPORT_CONNECTORSERVER_OFFSET;
- assertTrue("JMX RMIConnectorServer port not as expected(" + jmxPort + ").:" + getMessageString(log),
- getMessageString(log).endsWith(String.valueOf(jmxPort)));
- }
- }
-
- /**
- * Description:
- * Using the default configuration with SSL enabled for the management port the SSL Keystore path should be reported via MNG-1006
- * Input:
- * Management SSL enabled default configuration.
- * Output:
- *
- * <date> MESSAGE MNG-1006 : Using SSL Keystore : test_resources/ssl/keystore.jks
- *
- * Validation Steps:
- *
- * 1. The MNG ID is correct
- * 2. The keystore path is as specified in the configuration
- */
- public void testManagementStartupSSLKeystore() throws Exception
- {
- if (isJavaBroker())
- {
- startBrokerAndCreateMonitor(true, true);
-
- List<String> results = waitAndFindMatches("MNG-1006");
-
- assertTrue("MNGer message not logged", results.size() > 0);
-
- String log = getLogMessage(results, 0);
-
- //1
- validateMessageID("MNG-1006", log);
-
- // Validate we only have two MNG-1002 (one via stdout, one via log4j)
- results = findMatches("MNG-1006");
- assertEquals("Upexpected SSL Keystore message count",
- 2, results.size());
-
- // Validate the keystore path is as expected
- assertTrue("SSL Keystore entry expected.:" + getMessageString(log),
- getMessageString(log).endsWith(new File(getConfigurationStringProperty("management.ssl.keyStorePath")).getName()));
- }
- }
-
- /**
- * Description: Tests the management connection open/close are logged correctly.
- *
- * Output:
- *
- * <date> MESSAGE MNG-1007 : Open : User <username>
- * <date> MESSAGE MNG-1008 : Close : User <username>
- *
- * Validation Steps:
- *
- * 1. The MNG ID is correct
- * 2. The message and username are correct
- */
- public void testManagementUserOpenClose() throws Exception
- {
- if (isJavaBroker())
- {
- startBrokerAndCreateMonitor(true, false);
-
- final JMXTestUtils jmxUtils = new JMXTestUtils(this);
- List<String> openResults = null;
- List<String> closeResults = null;
- try
- {
- jmxUtils.setUp();
- jmxUtils.open();
- openResults = waitAndFindMatches("MNG-1007");
- }
- finally
- {
- if (jmxUtils != null)
- {
- jmxUtils.close();
- closeResults = waitAndFindMatches("MNG-1008");
- }
- }
-
- assertNotNull("Management Open results null", openResults.size());
- assertEquals("Management Open logged unexpected number of times", 1, openResults.size());
-
- assertNotNull("Management Close results null", closeResults.size());
- assertEquals("Management Close logged unexpected number of times", 1, closeResults.size());
-
- final String openMessage = getMessageString(getLogMessage(openResults, 0));
- assertTrue("Unexpected open message " + openMessage, openMessage.endsWith("Open : User admin"));
- final String closeMessage = getMessageString(getLogMessage(closeResults, 0));
- assertTrue("Unexpected close message " + closeMessage, closeMessage.endsWith("Close : User admin"));
- }
- }
-
- private void startBrokerAndCreateMonitor(boolean managementEnabled, boolean useManagementSSL) throws Exception
- {
- //Ensure management is on
- setConfigurationProperty("management.enabled", String.valueOf(managementEnabled));
-
- if(useManagementSSL)
- {
- // This test requires we have an ssl connection
- setConfigurationProperty("management.ssl.enabled", "true");
- }
-
- startBroker();
-
- // Now we can create the monitor as _outputFile will now be defined
- _monitor = new LogMonitor(_outputFile);
- }
-}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
deleted file mode 100644
index 79d04b239e..0000000000
--- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
+++ /dev/null
@@ -1,696 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.qpid.systest.management.jmx;
-
-import org.apache.commons.lang.time.FastDateFormat;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.configuration.ClientProperties;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.server.queue.AMQQueueFactory;
-import org.apache.qpid.server.queue.NotificationCheckTest;
-import org.apache.qpid.server.queue.SimpleAMQQueueTest;
-import org.apache.qpid.test.client.destination.AddressBasedDestinationTest;
-import org.apache.qpid.test.utils.JMXTestUtils;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-import javax.jms.Connection;
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageListener;
-import javax.jms.Queue;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-import javax.management.Notification;
-import javax.management.NotificationListener;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularData;
-import javax.naming.NamingException;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Tests the JMX API for the Managed Queue.
- *
- */
-public class QueueManagementTest extends QpidBrokerTestCase
-{
-
- private static final Logger LOGGER = Logger.getLogger(QueueManagementTest.class);
-
- private static final String VIRTUAL_HOST = "test";
- private static final String TEST_QUEUE_DESCRIPTION = "my description";
-
- private JMXTestUtils _jmxUtils;
- private Connection _connection;
- private Session _session;
-
- private String _sourceQueueName;
- private String _destinationQueueName;
- private Destination _sourceQueue;
- private Destination _destinationQueue;
- private ManagedQueue _managedSourceQueue;
- private ManagedQueue _managedDestinationQueue;
-
- public void setUp() throws Exception
- {
- _jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
-
- super.setUp();
- _sourceQueueName = getTestQueueName() + "_src";
- _destinationQueueName = getTestQueueName() + "_dest";
-
- createConnectionAndSession();
-
- _sourceQueue = _session.createQueue(_sourceQueueName);
- _destinationQueue = _session.createQueue(_destinationQueueName);
- createQueueOnBroker(_sourceQueue);
- createQueueOnBroker(_destinationQueue);
-
- _jmxUtils.open();
-
- createManagementInterfacesForQueues();
- }
-
- public void tearDown() throws Exception
- {
- if (_jmxUtils != null)
- {
- _jmxUtils.close();
- }
- super.tearDown();
- }
-
- public void testQueueAttributes() throws Exception
- {
- Queue queue = _session.createQueue(getTestQueueName());
- createQueueOnBroker(queue);
-
- final String queueName = queue.getQueueName();
-
- final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
- assertEquals("Unexpected name", queueName, managedQueue.getName());
- assertEquals("Unexpected queue type", "standard", managedQueue.getQueueType());
- }
-
- public void testExclusiveQueueHasJmsClientIdAsOwner() throws Exception
- {
- Queue tmpQueue = _session.createTemporaryQueue();
-
- final String queueName = tmpQueue.getQueueName();
-
- final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
- assertNotNull(_connection.getClientID());
- assertEquals("Unexpected owner", _connection.getClientID(), managedQueue.getOwner());
- }
-
- public void testNonExclusiveQueueHasNoOwner() throws Exception
- {
- Queue nonExclusiveQueue = _session.createQueue(getTestQueueName());
- createQueueOnBroker(nonExclusiveQueue);
-
- final String queueName = nonExclusiveQueue.getQueueName();
-
- final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
- assertNull("Unexpected owner", managedQueue.getOwner());
- }
-
- public void testSetNewQueueDescriptionOnExistingQueue() throws Exception
- {
- Queue queue = _session.createQueue(getTestQueueName());
- createQueueOnBroker(queue);
-
- final String queueName = queue.getQueueName();
-
- final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
- assertNull("Unexpected description", managedQueue.getDescription());
-
- managedQueue.setDescription(TEST_QUEUE_DESCRIPTION);
- assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription());
- }
-
- public void testNewQueueWithDescription() throws Exception
- {
- String queueName = getTestQueueName();
- Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION);
- ((AMQSession<?, ?>)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments);
-
- final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
- assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription());
- }
-
- /**
- * Requires persistent store.
- */
- public void testQueueDescriptionSurvivesRestart() throws Exception
- {
- String queueName = getTestQueueName();
- Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION);
-
- ((AMQSession<?, ?>)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments);
-
- ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
- assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription());
-
- restartBroker();
-
- managedQueue = _jmxUtils.getManagedQueue(queueName);
- assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription());
- }
-
- /**
- * Tests queue creation with {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument. Also tests
- * that the attribute is exposed correctly through {@link ManagedQueue#getMaximumDeliveryCount()}.
- */
- public void testCreateQueueWithMaximumDeliveryCountSet() throws Exception
- {
- final String queueName = getName();
- final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST);
-
- final Integer deliveryCount = 1;
- final Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, (Object)deliveryCount);
- managedBroker.createNewQueue(queueName, null, true, arguments);
-
- // Ensure the queue exists
- assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName("test", queueName));
- assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName));
-
- final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
- assertEquals("Unexpected maximum delivery count", deliveryCount, managedQueue.getMaximumDeliveryCount());
- }
-
- /**
- * Requires 0-10 as relies on ADDR addresses.
- * @see AddressBasedDestinationTest for the testing of message routing to the alternate exchange
- */
- public void testGetSetAlternateExchange() throws Exception
- {
- String queueName = getTestQueueName();
- String altExchange = "amq.fanout";
- String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange);
- Queue queue = _session.createQueue(addrWithAltExch);
-
- createQueueOnBroker(queue);
-
- final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
- assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange());
-
- String newAltExch = "amq.topic";
- managedQueue.setAlternateExchange(newAltExch);
- assertEquals("Unexpected alternate exchange after set", newAltExch, managedQueue.getAlternateExchange());
- }
-
- /**
- * Requires 0-10 as relies on ADDR addresses.
- */
- public void testRemoveAlternateExchange() throws Exception
- {
- String queueName = getTestQueueName();
- String altExchange = "amq.fanout";
- String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange);
- Queue queue = _session.createQueue(addrWithAltExch);
-
- createQueueOnBroker(queue);
-
- final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
- assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange());
-
- managedQueue.setAlternateExchange("");
- assertNull("Unexpected alternate exchange after set", managedQueue.getAlternateExchange());
- }
-
- /**
- * Requires persistent store
- * Requires 0-10 as relies on ADDR addresses.
- */
- public void testAlternateExchangeSurvivesRestart() throws Exception
- {
- String nonMandatoryExchangeName = "exch" + getName();
-
- final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST);
- managedBroker.createNewExchange(nonMandatoryExchangeName, "fanout", true);
-
- String queueName1 = getTestQueueName() + "1";
- String altExchange1 = "amq.fanout";
- String addr1WithAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName1, altExchange1);
- Queue queue1 = _session.createQueue(addr1WithAltExch);
-
- String queueName2 = getTestQueueName() + "2";
- String addr2WithoutAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue}}", queueName2);
- Queue queue2 = _session.createQueue(addr2WithoutAltExch);
-
- createQueueOnBroker(queue1);
- createQueueOnBroker(queue2);
-
- ManagedQueue managedQueue1 = _jmxUtils.getManagedQueue(queueName1);
- assertEquals("Newly created queue1 does not have expected alternate exchange", altExchange1, managedQueue1.getAlternateExchange());
-
- ManagedQueue managedQueue2 = _jmxUtils.getManagedQueue(queueName2);
- assertNull("Newly created queue2 does not have expected alternate exchange", managedQueue2.getAlternateExchange());
-
- String altExchange2 = nonMandatoryExchangeName;
- managedQueue2.setAlternateExchange(altExchange2);
-
- restartBroker();
-
- managedQueue1 = _jmxUtils.getManagedQueue(queueName1);
- assertEquals("Queue1 does not have expected alternate exchange after restart", altExchange1, managedQueue1.getAlternateExchange());
-
- managedQueue2 = _jmxUtils.getManagedQueue(queueName2);
- assertEquals("Queue2 does not have expected updated alternate exchange after restart", altExchange2, managedQueue2.getAlternateExchange());
- }
-
- /**
- * Tests the ability to receive queue alerts as JMX notifications.
- *
- * @see NotificationCheckTest
- * @see SimpleAMQQueueTest#testNotificationFiredAsync()
- * @see SimpleAMQQueueTest#testNotificationFiredOnEnqueue()
- */
- public void testQueueNotification() throws Exception
- {
- final String queueName = getName();
- final long maximumMessageCount = 3;
-
- Queue queue = _session.createQueue(queueName);
- createQueueOnBroker(queue);
-
- ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
- managedQueue.setMaximumMessageCount(maximumMessageCount);
-
- RecordingNotificationListener listener = new RecordingNotificationListener(1);
-
- _jmxUtils.addNotificationListener(_jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName), listener, null, null);
-
- // Send two messages - this should *not* trigger the notification
- sendMessage(_session, queue, 2);
-
- assertEquals("Premature notification received", 0, listener.getNumberOfNotificationsReceived());
-
- // A further message should trigger the message count alert
- sendMessage(_session, queue, 1);
-
- listener.awaitExpectedNotifications(5, TimeUnit.SECONDS);
-
- assertEquals("Unexpected number of JMX notifications received", 1, listener.getNumberOfNotificationsReceived());
-
- Notification notification = listener.getLastNotification();
- assertEquals("Unexpected notification message", "MESSAGE_COUNT_ALERT 3: Maximum count on queue threshold (3) breached.", notification.getMessage());
- }
-
- /**
- * Tests {@link ManagedQueue#viewMessages(long, long)} interface.
- */
- public void testViewSingleMessage() throws Exception
- {
- final List<Message> sentMessages = sendMessage(_session, _sourceQueue, 1);
- syncSession(_session);
- final Message sentMessage = sentMessages.get(0);
-
- assertEquals("Unexpected queue depth", 1, _managedSourceQueue.getMessageCount().intValue());
-
- // Check the contents of the message
- final TabularData tab = _managedSourceQueue.viewMessages(1l, 1l);
- assertEquals("Unexpected number of rows in table", 1, tab.size());
- final Iterator<CompositeData> rowItr = (Iterator<CompositeData>) tab.values().iterator();
-
- final CompositeData row1 = rowItr.next();
- assertNotNull("Message should have AMQ message id", row1.get(ManagedQueue.MSG_AMQ_ID));
- assertEquals("Unexpected queue position", 1l, row1.get(ManagedQueue.MSG_QUEUE_POS));
- assertEquals("Unexpected redelivered flag", Boolean.FALSE, row1.get(ManagedQueue.MSG_REDELIVERED));
-
- // Check the contents of header (encoded in a string array)
- final String[] headerArray = (String[]) row1.get(ManagedQueue.MSG_HEADER);
- assertNotNull("Expected message header array", headerArray);
- final Map<String, String> headers = headerArrayToMap(headerArray);
-
- final String expectedJMSMessageID = isBroker010() ? sentMessage.getJMSMessageID().replace("ID:", "") : sentMessage.getJMSMessageID();
- final String expectedFormattedJMSTimestamp = FastDateFormat.getInstance(ManagedQueue.JMSTIMESTAMP_DATETIME_FORMAT).format(sentMessage.getJMSTimestamp());
- assertEquals("Unexpected JMSMessageID within header", expectedJMSMessageID, headers.get("JMSMessageID"));
- assertEquals("Unexpected JMSPriority within header", String.valueOf(sentMessage.getJMSPriority()), headers.get("JMSPriority"));
- assertEquals("Unexpected JMSTimestamp within header", expectedFormattedJMSTimestamp, headers.get("JMSTimestamp"));
- }
-
- /**
- * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface.
- */
- public void testMoveMessagesBetweenQueues() throws Exception
- {
- final int numberOfMessagesToSend = 10;
-
- sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
- syncSession(_session);
- assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
-
- // Move first three messages to destination
- long fromMessageId = amqMessagesIds.get(0);
- long toMessageId = amqMessagesIds.get(2);
- _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
-
- assertEquals("Unexpected queue depth on destination queue after first move", 3, _managedDestinationQueue.getMessageCount().intValue());
- assertEquals("Unexpected queue depth on source queue after first move", 7, _managedSourceQueue.getMessageCount().intValue());
-
- // Now move a further two messages to destination
- fromMessageId = amqMessagesIds.get(7);
- toMessageId = amqMessagesIds.get(8);
- _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
- assertEquals("Unexpected queue depth on destination queue after second move", 5, _managedDestinationQueue.getMessageCount().intValue());
- assertEquals("Unexpected queue depth on source queue after second move", 5, _managedSourceQueue.getMessageCount().intValue());
-
- assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8);
- }
-
- /**
- * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface.
- */
- public void testCopyMessagesBetweenQueues() throws Exception
- {
- final int numberOfMessagesToSend = 10;
- sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
- syncSession(_session);
- assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
-
- // Copy first three messages to destination
- long fromMessageId = amqMessagesIds.get(0);
- long toMessageId = amqMessagesIds.get(2);
- _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName);
-
- assertEquals("Unexpected queue depth on destination queue after first copy", 3, _managedDestinationQueue.getMessageCount().intValue());
- assertEquals("Unexpected queue depth on source queue after first copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- // Now copy a further two messages to destination
- fromMessageId = amqMessagesIds.get(7);
- toMessageId = amqMessagesIds.get(8);
- _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName);
- assertEquals("Unexpected queue depth on destination queue after second copy", 5, _managedDestinationQueue.getMessageCount().intValue());
- assertEquals("Unexpected queue depth on source queue after second copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8);
- }
-
- public void testMoveMessagesBetweenQueuesWithActiveConsumerOnSourceQueue() throws Exception
- {
- setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString());
- Connection asyncConnection = getConnection();
- asyncConnection.start();
-
- final int numberOfMessagesToSend = 50;
- sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
- syncSession(_session);
- assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
-
- long fromMessageId = amqMessagesIds.get(0);
- long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1);
-
- CountDownLatch consumerReadToHalfwayLatch = new CountDownLatch(numberOfMessagesToSend / 2);
- AtomicInteger totalConsumed = new AtomicInteger(0);
- startAsyncConsumerOn(_sourceQueue, asyncConnection, consumerReadToHalfwayLatch, totalConsumed);
-
- boolean halfwayPointReached = consumerReadToHalfwayLatch.await(5000, TimeUnit.MILLISECONDS);
- assertTrue("Did not read half of messages within time allowed", halfwayPointReached);
-
- _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
-
- asyncConnection.stop();
-
- // The exact number of messages moved will be non deterministic, as the number of messages processed
- // by the consumer cannot be predicted. There is also the possibility that a message can remain
- // on the source queue. This situation will arise if a message has been acquired by the consumer, but not
- // yet delivered to the client application (i.e. MessageListener#onMessage()) when the Connection#stop() occurs.
- //
- // The number of messages moved + the number consumed + any messages remaining on source should
- // *always* be equal to the number we originally sent.
-
- int numberOfMessagesReadByConsumer = totalConsumed.intValue();
- int numberOfMessagesOnDestinationQueue = _managedDestinationQueue.getMessageCount().intValue();
- int numberOfMessagesRemainingOnSourceQueue = _managedSourceQueue.getMessageCount().intValue();
-
- LOGGER.debug("Async consumer read : " + numberOfMessagesReadByConsumer
- + " Number of messages moved to destination : " + numberOfMessagesOnDestinationQueue
- + " Number of messages remaining on source : " + numberOfMessagesRemainingOnSourceQueue);
- assertEquals("Unexpected number of messages after move", numberOfMessagesToSend, numberOfMessagesReadByConsumer + numberOfMessagesOnDestinationQueue + numberOfMessagesRemainingOnSourceQueue);
- }
-
- public void testMoveMessagesBetweenQueuesWithActiveConsumerOnDestinationQueue() throws Exception
- {
- setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString());
- Connection asyncConnection = getConnection();
- asyncConnection.start();
-
- final int numberOfMessagesToSend = 50;
- sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
- syncSession(_session);
- assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
- long fromMessageId = amqMessagesIds.get(0);
- long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1);
-
- AtomicInteger totalConsumed = new AtomicInteger(0);
- CountDownLatch allMessagesConsumedLatch = new CountDownLatch(numberOfMessagesToSend);
- startAsyncConsumerOn(_destinationQueue, asyncConnection, allMessagesConsumedLatch, totalConsumed);
-
- _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
-
- allMessagesConsumedLatch.await(5000, TimeUnit.MILLISECONDS);
- assertEquals("Did not consume all messages from destination queue", numberOfMessagesToSend, totalConsumed.intValue());
- }
-
- /**
- * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface.
- */
- public void testMoveMessageBetweenQueuesWithBrokerRestart() throws Exception
- {
- final int numberOfMessagesToSend = 1;
-
- sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
- syncSession(_session);
- assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- restartBroker();
-
- createManagementInterfacesForQueues();
- createConnectionAndSession();
-
- List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
-
- // Move messages to destination
- long messageId = amqMessagesIds.get(0);
- _managedSourceQueue.moveMessages(messageId, messageId, _destinationQueueName);
-
- assertEquals("Unexpected queue depth on destination queue after move", 1, _managedDestinationQueue.getMessageCount().intValue());
- assertEquals("Unexpected queue depth on source queue after move", 0, _managedSourceQueue.getMessageCount().intValue());
-
- assertMessageIndicesOn(_destinationQueue, 0);
- }
-
- /**
- * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface.
- */
- public void testCopyMessageBetweenQueuesWithBrokerRestart() throws Exception
- {
- final int numberOfMessagesToSend = 1;
-
- sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
- syncSession(_session);
- assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
-
- restartBroker();
-
- createManagementInterfacesForQueues();
- createConnectionAndSession();
-
- List<Long> amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
-
- // Move messages to destination
- long messageId = amqMessagesIds.get(0);
- _managedSourceQueue.copyMessages(messageId, messageId, _destinationQueueName);
-
- assertEquals("Unexpected queue depth on destination queue after copy", 1, _managedDestinationQueue.getMessageCount().intValue());
- assertEquals("Unexpected queue depth on source queue after copy", 1, _managedSourceQueue.getMessageCount().intValue());
-
- assertMessageIndicesOn(_destinationQueue, 0);
- }
-
- @Override
- public Message createNextMessage(Session session, int messageNumber) throws JMSException
- {
- Message message = session.createTextMessage(getContentForMessageNumber(messageNumber));
- message.setIntProperty(INDEX, messageNumber);
- return message;
- }
-
- private void startAsyncConsumerOn(Destination queue, Connection asyncConnection,
- final CountDownLatch requiredNumberOfMessagesRead, final AtomicInteger totalConsumed) throws Exception
- {
- Session session = asyncConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- MessageConsumer consumer = session.createConsumer(queue);
- consumer.setMessageListener(new MessageListener()
- {
-
- @Override
- public void onMessage(Message arg0)
- {
- totalConsumed.incrementAndGet();
- requiredNumberOfMessagesRead.countDown();
- }
- });
- }
-
- private void assertMessageIndicesOn(Destination queue, int... expectedIndices) throws Exception
- {
- MessageConsumer consumer = _session.createConsumer(queue);
-
- for (int i : expectedIndices)
- {
- TextMessage message = (TextMessage)consumer.receive(1000);
- assertNotNull("Expected message with index " + i, message);
- assertEquals("Expected message with index " + i, i, message.getIntProperty(INDEX));
- assertEquals("Expected message content", getContentForMessageNumber(i), message.getText());
- }
-
- assertNull("Unexpected message encountered", consumer.receive(1000));
- }
-
- private List<Long> getAMQMessageIdsOn(ManagedQueue managedQueue, long startIndex, long endIndex) throws Exception
- {
- final SortedSet<Long> messageIds = new TreeSet<Long>();
-
- final TabularData tab = managedQueue.viewMessages(startIndex, endIndex);
- final Iterator<CompositeData> rowItr = (Iterator<CompositeData>) tab.values().iterator();
- while(rowItr.hasNext())
- {
- final CompositeData row = rowItr.next();
- long amqMessageId = (Long)row.get(ManagedQueue.MSG_AMQ_ID);
- messageIds.add(amqMessageId);
- }
-
- return new ArrayList<Long>(messageIds);
- }
-
- /**
- *
- * Utility method to convert array of Strings in the form x = y into a
- * map with key/value x =&gt; y.
- *
- */
- private Map<String,String> headerArrayToMap(final String[] headerArray)
- {
- final Map<String, String> headerMap = new HashMap<String, String>();
- final List<String> headerList = Arrays.asList(headerArray);
- for (Iterator<String> iterator = headerList.iterator(); iterator.hasNext();)
- {
- final String nameValuePair = iterator.next();
- final String[] nameValue = nameValuePair.split(" *= *", 2);
- headerMap.put(nameValue[0], nameValue[1]);
- }
- return headerMap;
- }
-
- private void createQueueOnBroker(Destination destination) throws JMSException
- {
- _session.createConsumer(destination).close(); // Create a consumer only to cause queue creation
- }
-
- private void syncSession(Session session) throws Exception
- {
- ((AMQSession<?,?>)session).sync();
- }
-
- private void createConnectionAndSession() throws JMSException,
- NamingException
- {
- _connection = getConnection();
- _connection.start();
- _session = _connection.createSession(true, Session.SESSION_TRANSACTED);
- }
-
- private void createManagementInterfacesForQueues()
- {
- _managedSourceQueue = _jmxUtils.getManagedQueue(_sourceQueueName);
- _managedDestinationQueue = _jmxUtils.getManagedQueue(_destinationQueueName);
- }
-
- private String getContentForMessageNumber(int msgCount)
- {
- return "Message count " + msgCount;
- }
-
- private final class RecordingNotificationListener implements NotificationListener
- {
- private final CountDownLatch _notificationReceivedLatch;
- private final AtomicInteger _numberOfNotifications;
- private final AtomicReference<Notification> _lastNotification;
-
- private RecordingNotificationListener(int expectedNumberOfNotifications)
- {
- _notificationReceivedLatch = new CountDownLatch(expectedNumberOfNotifications);
- _numberOfNotifications = new AtomicInteger(0);
- _lastNotification = new AtomicReference<Notification>();
- }
-
- @Override
- public void handleNotification(Notification notification, Object handback)
- {
- _lastNotification.set(notification);
- _numberOfNotifications.incrementAndGet();
- _notificationReceivedLatch.countDown();
- }
-
- public int getNumberOfNotificationsReceived()
- {
- return _numberOfNotifications.get();
- }
-
- public Notification getLastNotification()
- {
- return _lastNotification.get();
- }
-
- public void awaitExpectedNotifications(long timeout, TimeUnit timeunit) throws InterruptedException
- {
- _notificationReceivedLatch.await(timeout, timeunit);
- }
- }
-
-}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java
deleted file mode 100644
index c3fff94923..0000000000
--- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.systest.management.jmx;
-
-import java.util.List;
-
-import javax.jms.Connection;
-import javax.jms.MessageConsumer;
-import javax.jms.Queue;
-import javax.jms.Session;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-import org.apache.qpid.management.common.mbeans.ServerInformation;
-import org.apache.qpid.test.utils.JMXTestUtils;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-public class StatisticsTest extends QpidBrokerTestCase
-{
- private static final String TEST_USER = "admin";
- private static final String TEST_PASSWORD = "admin";
- private static final int MESSAGE_COUNT_TEST = 5;
- private static final int MESSAGE_COUNT_DEV = 9;
-
- private JMXTestUtils _jmxUtils;
- private Connection _test1, _dev;
- private Session _testSession, _developmentSession;
- private Queue _developmentQueue, _testQueue;
- protected String _brokerUrl;
-
- @Override
- public void setUp() throws Exception
- {
- _jmxUtils = new JMXTestUtils(this, TEST_USER, TEST_PASSWORD);
- _jmxUtils.setUp();
-
- super.setUp();
-
- _brokerUrl = getBroker().toString();
- _test1 = new AMQConnection(_brokerUrl, TEST_USER, TEST_PASSWORD, "clientid", "test");
- _dev = new AMQConnection(_brokerUrl, TEST_USER, TEST_PASSWORD, "clientid", "development");
- _test1.start();
- _dev.start();
-
- _testSession = _test1.createSession(true, Session.SESSION_TRANSACTED);
- _developmentSession = _dev.createSession(true, Session.SESSION_TRANSACTED);
-
- _developmentQueue = _developmentSession.createQueue(getTestQueueName());
- _testQueue = _testSession.createQueue(getTestQueueName());
-
- //Create queues by opening and closing consumers
- final MessageConsumer testConsumer = _testSession.createConsumer(_testQueue);
- testConsumer.close();
- final MessageConsumer developmentConsumer = _developmentSession.createConsumer(_developmentQueue);
- developmentConsumer.close();
-
- _jmxUtils.open();
- }
-
- @Override
- public void tearDown() throws Exception
- {
- _jmxUtils.close();
-
- super.tearDown();
- }
-
- public void testInitialStatisticValues() throws Exception
- {
- //Check initial values
- checkSingleConnectionOnVHostStatistics("test", 0, 0, 0, 0);
- checkVHostStatistics("test", 0, 0, 0, 0);
- checkSingleConnectionOnVHostStatistics("development", 0, 0, 0, 0);
- checkVHostStatistics("development", 0, 0, 0, 0);
- checkBrokerStatistics(0, 0, 0, 0);
- }
-
- public void testSendOnSingleVHost() throws Exception
- {
- sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST);
-
- //Check values
- checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
- checkVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
- checkSingleConnectionOnVHostStatistics("development", 0, 0, 0, 0);
- checkVHostStatistics("development", 0, 0, 0, 0);
- checkBrokerStatistics(MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
- }
-
- public void testSendOnTwoVHosts() throws Exception
- {
- sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST);
- sendMessagesAndSync(_developmentSession, _developmentQueue, MESSAGE_COUNT_DEV);
-
- //Check values
- checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
- checkVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
- checkSingleConnectionOnVHostStatistics("development", MESSAGE_COUNT_DEV, 0, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, 0);
- checkVHostStatistics("development", MESSAGE_COUNT_DEV, 0, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, 0);
- checkBrokerStatistics(MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, 0, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE, 0);
- }
-
- public void testSendAndConsumeOnSingleVHost() throws Exception
- {
- sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST);
- consumeMessages(_testSession, _testQueue, MESSAGE_COUNT_TEST);
-
- //Check values
- checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
- checkVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
- checkSingleConnectionOnVHostStatistics("development", 0, 0, 0, 0);
- checkVHostStatistics("development", 0, 0, 0, 0);
- checkBrokerStatistics(MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
- }
-
- public void testSendAndConsumeOnTwoVHosts() throws Exception
- {
- sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST);
- sendMessagesAndSync(_developmentSession, _developmentQueue, MESSAGE_COUNT_DEV);
- consumeMessages(_testSession, _testQueue, MESSAGE_COUNT_TEST);
- consumeMessages(_developmentSession, _developmentQueue, MESSAGE_COUNT_DEV);
-
- //Check values
- checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
- checkVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
- checkSingleConnectionOnVHostStatistics("development", MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE);
- checkVHostStatistics("development", MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE);
- checkBrokerStatistics(MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE);
- }
-
- private void sendMessagesAndSync(Session session, Queue queue, int numberOfMessages) throws Exception
- {
- //Send messages via connection on and sync
- sendMessage(session, queue, numberOfMessages);
- ((AMQSession<?,?>)session).sync();
- }
-
- private void consumeMessages(Session session, Queue queue, int numberOfMessages) throws Exception
- {
- //consume the messages on the virtual host
- final MessageConsumer consumer = session.createConsumer(queue);
- for (int i = 0 ; i < numberOfMessages ; i++)
- {
- assertNotNull("an expected message was not received", consumer.receive(1500));
- }
- session.commit();
- consumer.close();
- }
-
- private void checkSingleConnectionOnVHostStatistics(String vHostName, long messagesSent, long messagesReceived, long dataSent, long dataReceived)
- {
- List<ManagedConnection> managedConnections = _jmxUtils.getManagedConnections(vHostName);
- assertEquals(1, managedConnections.size());
-
- ManagedConnection managedConnection = managedConnections.get(0);
-
- assertEquals(messagesSent, managedConnection.getTotalMessagesReceived());
- assertEquals(messagesReceived, managedConnection.getTotalMessagesDelivered());
-
- assertEquals(dataSent, managedConnection.getTotalDataReceived());
- assertEquals(dataReceived, managedConnection.getTotalDataDelivered());
- }
-
- private void checkVHostStatistics(String vHostName, long messagesSent, long messagesReceived, long dataSent, long dataReceived)
- {
- ManagedBroker vhost = _jmxUtils.getManagedBroker(vHostName);
-
- assertEquals(messagesSent, vhost.getTotalMessagesReceived());
- assertEquals(messagesReceived, vhost.getTotalMessagesDelivered());
-
- assertEquals(dataSent, vhost.getTotalDataReceived());
- assertEquals(dataReceived, vhost.getTotalDataDelivered());
- }
-
- private void checkBrokerStatistics(long messagesSent, long messagesReceived, long dataSent, long dataReceived)
- {
- ServerInformation broker = _jmxUtils.getServerInformation();
-
- assertEquals(messagesSent, broker.getTotalMessagesReceived());
- assertEquals(messagesReceived, broker.getTotalMessagesDelivered());
-
- assertEquals(dataSent, broker.getTotalDataReceived());
- assertEquals(dataReceived, broker.getTotalDataDelivered());
- }
-}
diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java
deleted file mode 100644
index 62b1b554a9..0000000000
--- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.qpid.systest.management.jmx;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-
-import javax.jms.Connection;
-import javax.jms.JMSException;
-
-import org.apache.qpid.management.common.mbeans.UserManagement;
-import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.test.utils.JMXTestUtils;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-import org.apache.qpid.tools.security.Passwd;
-
-/**
- * System test for User Management.
- *
- */
-public class UserManagementTest extends QpidBrokerTestCase
-{
- private static final String TEST_NEWPASSWORD = "newpassword";
- private static final String TEST_PASSWORD = "password";
- private JMXTestUtils _jmxUtils;
- private String _testUserName;
- private File _passwordFile;
- private UserManagement _userManagement;
- private Passwd _passwd;
-
- public void setUp() throws Exception
- {
- _passwd = createPasswordEncodingUtility();
- _passwordFile = createTemporaryPasswordFileWithJmxAdminUser();
-
- setConfigurationProperty("security.pd-auth-manager.principal-database.class", getPrincipalDatabaseImplClass().getName());
- setConfigurationProperty("security.pd-auth-manager.principal-database.attributes.attribute.name", "passwordFile");
- setConfigurationProperty("security.pd-auth-manager.principal-database.attributes.attribute.value", _passwordFile.getAbsolutePath());
-
- _jmxUtils = new JMXTestUtils(this);
- _jmxUtils.setUp();
-
- super.setUp();
- _jmxUtils.open();
-
- _testUserName = getTestName() + System.currentTimeMillis();
-
- _userManagement = _jmxUtils.getUserManagement();
- }
-
-
- public void tearDown() throws Exception
- {
- try
- {
- if (_jmxUtils != null)
- {
- _jmxUtils.close();
- }
- }
- finally
- {
- super.tearDown();
- }
- }
-
- public void testCreateUser() throws Exception
- {
- final int initialNumberOfUsers = _userManagement.viewUsers().size();
- assertFileDoesNotContainsPasswordForUser(_testUserName);
-
- boolean success = _userManagement.createUser(_testUserName, TEST_PASSWORD);
- assertTrue("Should have been able to create new user " + _testUserName, success);
- assertEquals("Unexpected number of users after add", initialNumberOfUsers + 1, _userManagement.viewUsers().size());
-
- assertFileContainsPasswordForUser(_testUserName);
- }
-
- public void testJmsLoginForNewUser() throws Exception
- {
- assertJmsConnectionFails(_testUserName, TEST_PASSWORD);
- testCreateUser();
-
- assertJmsConnectionSucceeds(_testUserName, TEST_PASSWORD);
- }
-
- public void testDeleteUser() throws Exception
- {
- final int initialNumberOfUsers = _userManagement.viewUsers().size();
-
- testCreateUser();
-
- boolean success = _userManagement.deleteUser(_testUserName);
- assertTrue("Should have been able to delete new user " + _testUserName, success);
- assertEquals("Unexpected number of users after delete", initialNumberOfUsers, _userManagement.viewUsers().size());
- assertFileDoesNotContainsPasswordForUser(_testUserName);
- }
-
- public void testJmsLoginNotPossibleForDeletedUser() throws Exception
- {
- testDeleteUser();
-
- assertJmsConnectionFails(_testUserName, TEST_PASSWORD);
- }
-
- public void testSetPassword() throws Exception
- {
- testCreateUser();
-
- _userManagement.setPassword(_testUserName, TEST_NEWPASSWORD);
-
- assertFileContainsPasswordForUser(_testUserName);
- }
-
- public void testJmsLoginForPasswordChangedUser() throws Exception
- {
- testSetPassword();
-
- assertJmsConnectionSucceeds(_testUserName, TEST_NEWPASSWORD);
- assertJmsConnectionFails(_testUserName, TEST_PASSWORD);
- }
-
- public void testReload() throws Exception
- {
- writePasswordFile(_passwordFile, JMXTestUtils.DEFAULT_USERID, JMXTestUtils.DEFAULT_PASSWORD, _testUserName, TEST_PASSWORD);
-
- assertJmsConnectionFails(_testUserName, TEST_PASSWORD);
-
- _userManagement.reloadData();
-
- assertJmsConnectionSucceeds(_testUserName, TEST_PASSWORD);
- }
-
- protected Passwd createPasswordEncodingUtility()
- {
- return new Passwd()
- {
- @Override
- public String getOutput(String username, String password)
- {
- return username + ":" + password;
- }
- };
- }
-
- protected Class<? extends PrincipalDatabase> getPrincipalDatabaseImplClass()
- {
- return PlainPasswordFilePrincipalDatabase.class;
- }
-
- private File createTemporaryPasswordFileWithJmxAdminUser() throws Exception
- {
- File passwordFile = File.createTempFile("passwd", "pwd");
- passwordFile.deleteOnExit();
- writePasswordFile(passwordFile, JMXTestUtils.DEFAULT_USERID, JMXTestUtils.DEFAULT_PASSWORD);
- return passwordFile;
- }
-
- private void writePasswordFile(File passwordFile, String... userNamePasswordPairs) throws Exception
- {
- FileWriter writer = null;
- try
- {
- writer = new FileWriter(passwordFile);
- for (int i = 0; i < userNamePasswordPairs.length; i=i+2)
- {
- String username = userNamePasswordPairs[i];
- String password = userNamePasswordPairs[i+1];
- writer.append(_passwd.getOutput(username, password) + "\n");
- }
- }
- finally
- {
- writer.close();
- }
- }
-
-
- private void assertFileContainsPasswordForUser(String username) throws IOException
- {
- assertTrue("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username));
- }
-
- private void assertFileDoesNotContainsPasswordForUser(String username) throws IOException
- {
- assertFalse("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username));
- }
-
- private boolean passwordFileContainsUser(String username) throws IOException
- {
- BufferedReader reader = null;
- try
- {
- reader = new BufferedReader(new FileReader(_passwordFile));
- String line = reader.readLine();
- while(line != null)
- {
- if (line.startsWith(username))
- {
- return true;
- }
- line = reader.readLine();
- }
-
- return false;
- }
- finally
- {
- reader.close();
- }
- }
-
- private void assertJmsConnectionSucceeds(String username, String password) throws Exception
- {
- Connection connection = getConnection(username, password);
- assertNotNull(connection);
- }
-
- private void assertJmsConnectionFails(String username, String password) throws Exception
- {
- try
- {
- getConnection(username, password);
- fail("Exception not thrown");
- }
- catch (JMSException e)
- {
- // PASS
- }
- }
-}