Java tutorial
/** * VMware Continuent Tungsten Replicator * Copyright (C) 2015 VMware, Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Initial developer(s): Robert Hodges * Contributor(s): Edward Archibald, Stephane Giron */ package com.continuent.tungsten.common.jmx; import java.io.IOException; import java.lang.management.ManagementFactory; import java.net.InetAddress; import java.net.UnknownHostException; import java.rmi.NoSuchObjectException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; import java.text.MessageFormat; import java.util.HashMap; import javax.management.InstanceNotFoundException; import javax.management.MBeanInfo; import javax.management.MBeanServer; import javax.management.MBeanServerConnection; import javax.management.MBeanServerInvocationHandler; import javax.management.MBeanServerNotification; import javax.management.Notification; import javax.management.NotificationListener; import javax.management.ObjectName; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; import javax.management.remote.rmi.RMIConnectorServer; import javax.net.ssl.SSLHandshakeException; import javax.rmi.ssl.SslRMIClientSocketFactory; import javax.rmi.ssl.SslRMIServerSocketFactory; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import com.continuent.tungsten.common.config.cluster.ConfigurationException; import com.continuent.tungsten.common.security.AuthenticationInfo; import com.continuent.tungsten.common.security.PasswordManager; import com.continuent.tungsten.common.security.PasswordManager.ClientApplicationType; import com.continuent.tungsten.common.security.RealmJMXAuthenticator; import com.continuent.tungsten.common.security.SecurityHelper; /** * Encapsulates JMX server start/stop and provides static utility methods to * register MBeans on the server side as well as get proxies for them on the * client side. * * @author <a href="mailto:robert.hodges@continuent.com">Robert Hodges</a> * @version 1.0 */ public class JmxManager implements NotificationListener { private static final Logger logger = Logger.getLogger(JmxManager.class); // RMI registry and connector server we are managing. protected Registry rmiRegistry; protected JMXConnectorServer jmxConnectorServer; // JMX server parameters. private final String host; private final int registryPort; private final int beanPort; private final String serviceName; public final static String CREATE_MBEAN_HELPER = "createHelper"; // Authentication and Encryption parameters private volatile AuthenticationInfo authenticationInfo = null; public JmxManager(String host, int beanPort, int registryPort, String serviceName) { this(host, beanPort, registryPort, serviceName, null); } /** * Creates an instance to manage a JMX service * * @param host The host name or IP to use * @param beanPort The port used for JMX beans * @param registryPort The JMX server RMI registryPort * @param serviceName The JMX service name * @param authInfo Authentication information from security.properties or * null if no security settings are available */ public JmxManager(String host, int beanPort, int registryPort, String serviceName, AuthenticationInfo authInfo) { this.host = host; this.beanPort = beanPort; this.registryPort = registryPort; this.serviceName = serviceName; this.authenticationInfo = authInfo; // Load security information from security.properties // Load password from file // CONT-1069 if (authenticationInfo == null) { try { authenticationInfo = SecurityHelper.loadAuthenticationInformation(); // Sets the username and password in the authenticationInfo. // This will be used as credentials when connecting // Password is provided "as is" (potentially encrypted) and will // be decrypted by the server if needed if (authenticationInfo.isAuthenticationNeeded()) { PasswordManager passwordManager = new PasswordManager(authenticationInfo, ClientApplicationType.RMI_JMX); String goodPassword = passwordManager .getEncryptedPasswordForUser(authenticationInfo.getUsername()); authenticationInfo.setPassword(goodPassword); } } catch (ConfigurationException e) { logger.error(MessageFormat .format("Could not get security information. Will use default values: {0}", e)); } } } /** * Creates an instance to manage a JMX service * * @param host The host name or IP to use * @param registryPort The JMX server RMI registryPort * @param serviceName The JMX service name */ public JmxManager(String host, int registryPort, String serviceName) { this(host, registryPort + 1, registryPort, serviceName); } /** * Creates an instance to manage a JMX service Called when using * authentication (and) encryption * * @see <a href= * "http://download.java.net/jdk8/docs/technotes/guides/jmx/tutorial/security.html"> * JMX Tutorial on Security</a> * @param host * @param registryPort * @param serviceName * @param authInfo */ public JmxManager(String host, int registryPort, String serviceName, AuthenticationInfo authInfo) { this(host, registryPort + 1, registryPort, serviceName, authInfo); } /** * Starts the JXM server. */ public synchronized void start() { createRegistry(registryPort); startJmxConnector(); } /** * Stops the JXM server. */ public synchronized void stop() { stopRMI(); stopJmxConnector(); } protected Registry locateDefaultRegistry() { Registry registry = null; try { registry = LocateRegistry.getRegistry(); } catch (Exception r) { throw new ServerRuntimeException(String.format( "Unable to locate the default registry on registryPort 1099, reason='%s'", r.getMessage())); } return registry; } /** * Starts the rmi registry. */ protected void createRegistry(int port) { // Create a registry if we don't already have one. if (rmiRegistry == null) { try { if (logger.isDebugEnabled()) { logger.debug("Starting RMI registry on registryPort: " + port); } rmiRegistry = LocateRegistry.createRegistry(port); } catch (Throwable e) { throw new ServerRuntimeException("Unable to start rmi registry on registryPort: " + port, e); } } } /** * Deallocates the RMI registry. */ protected void stopRMI() { if (rmiRegistry != null) { try { UnicastRemoteObject.unexportObject(rmiRegistry, true); } catch (NoSuchObjectException e) { logger.warn("Unexpected error while shutting down RMI registry", e); } rmiRegistry = null; } } /** * Starts the JMX connector for the server. */ protected void startJmxConnector() { String serviceAddress = null; try { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); serviceAddress = generateServiceAddress(host, beanPort, registryPort, serviceName); JMXServiceURL address = new JMXServiceURL(serviceAddress); // --- Define security attributes --- HashMap<String, Object> env = new HashMap<String, Object>(); // --- Authentication based on password and access files--- if (authenticationInfo != null && authenticationInfo.isAuthenticationNeeded()) { if (authenticationInfo.isUseTungstenAuthenticationRealm()) env.put(JMXConnectorServer.AUTHENTICATOR, new RealmJMXAuthenticator(authenticationInfo)); else env.put("jmx.remote.x.password.file", authenticationInfo.getPasswordFileLocation()); env.put("jmx.remote.x.access.file", authenticationInfo.getAccessFileLocation()); } // --- SSL encryption --- if (authenticationInfo != null && authenticationInfo.isEncryptionNeeded()) { // Keystore System.setProperty("javax.net.ssl.keyStore", authenticationInfo.getKeystoreLocation()); System.setProperty("javax.net.ssl.keyStorePassword", authenticationInfo.getKeystorePassword()); /** * Configure SSL. Protocols and ciphers are set in * securityHelper.setSecurityProperties and used by * SslRMIClientSocketFactory */ try { String[] protocolArray = authenticationInfo.getEnabledProtocols().toArray(new String[0]); String[] allowedCipherSuites = authenticationInfo.getEnabledCipherSuites() .toArray(new String[0]); String[] cipherArray; if (protocolArray.length == 0) protocolArray = null; if (allowedCipherSuites.length == 0) cipherArray = null; else { // Ensure we choose an allowed cipher suite. cipherArray = authenticationInfo.getJvmEnabledCipherSuites().toArray(new String[0]); if (cipherArray.length == 0) { // We don't have any cipher suites in common. This // is not good! String message = "Unable to find approved ciphers in the supported cipher suites on this JVM"; StringBuffer sb = new StringBuffer(message).append("\n"); sb.append(String.format("JVM supported cipher suites: %s\n", StringUtils.join(SecurityHelper.getJvmSupportedCiphers()))); sb.append(String.format("Approved cipher suites from security.properties: %s\n", StringUtils.join(allowedCipherSuites))); logger.error(sb.toString()); throw new RuntimeException(message); } } logger.info("Setting allowed JMX server protocols: " + StringUtils.join(protocolArray, ",")); logger.info("Setting allowed JMX server ciphers: " + StringUtils.join(cipherArray, ",")); SslRMIClientSocketFactory csf = new SslRMIClientSocketFactory(); SslRMIServerSocketFactory ssf = new SslRMIServerSocketFactory(cipherArray, protocolArray, false); env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, csf); env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, ssf); } catch (IllegalArgumentException ie) { logger.warn("Some of the protocols or ciphers are not supported. " + ie.getMessage()); throw new RuntimeException(ie.getLocalizedMessage(), ie); } } env.put(RMIConnectorServer.JNDI_REBIND_ATTRIBUTE, "true"); JMXConnectorServer connector = JMXConnectorServerFactory.newJMXConnectorServer(address, env, mbs); connector.start(); logger.info(MessageFormat.format("JMXConnector: security.properties={0}", (authenticationInfo != null) ? authenticationInfo.getParentPropertiesFileLocation() : "No security.properties file found !...")); if (authenticationInfo != null) logger.info(authenticationInfo.toString()); logger.info(String.format("JMXConnector started at address %s", serviceAddress)); jmxConnectorServer = connector; } catch (Throwable e) { throw new ServerRuntimeException( MessageFormat.format("Unable to create RMI listener: {0} -> {1}", getServiceProps(), e), e); } } private String getServiceProps() { return ("RMI {host=" + host + ", registryPort=" + registryPort + ", service=" + serviceName + "}"); } /** * Stops the JMX connector if it is running. */ protected void stopJmxConnector() { // Shut down the JMX server. try { if (jmxConnectorServer != null) jmxConnectorServer.stop(); } catch (IOException e) { logger.warn("Unexpected error while shutting down JMX server", e); } } /** * Server helper method to register a JMX MBean. MBeans are registered by a * combination of their MBean interface and the custom mbeanName argument. * The mbeanName permits multiple mBeans to be registered under the same * name. * * @param mbean The MBean instance that should be registered * @param mbeanInterface The MBean interface this instance implements * @param mbeanName A custom name for this MBean * @throws ServerRuntimeException */ public static void registerMBean(Object mbean, Class<?> mbeanInterface, String mbeanName, boolean ignored) { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); try { if (logger.isDebugEnabled()) logger.debug("Registering mbean: " + mbean.getClass()); ObjectName name = generateMBeanObjectName(mbeanInterface.getName(), mbeanName); if (mbs.isRegistered(name)) mbs.unregisterMBean(name); mbs.registerMBean(mbean, name); } catch (Exception e) { throw new ServerRuntimeException("Unable to register mbean: class=" + mbean.getClass() + " interface=" + mbeanInterface + " name=" + mbeanName, e); } } /** * Server helper method to register a JMX MBean. MBeans are registered by a * combination of their MBean interface and the custom mbeanName argument. * The mbeanName permits multiple mBeans to be registered under the same * name. * * @param mbean The MBean instance that should be registered * @param mbeanClass The base class for the mbean * @throws ServerRuntimeException */ public static void registerMBean(Object mbean, Class<?> mbeanClass) { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); try { if (logger.isDebugEnabled()) logger.debug("Registering mbean: " + mbean.getClass()); ObjectName name = generateMBeanObjectName(mbeanClass); if (mbs.isRegistered(name)) mbs.unregisterMBean(name); mbs.registerMBean(mbean, name); } catch (Exception e) { throw new ServerRuntimeException( String.format("Unable to register mbean for class %s because '%s'", mbeanClass.getName(), e), e); } } /** * Server helper method to register a JMX MBean. MBeans are registered by a * combination of their MBean interface and the custom mbeanName argument. * The mbeanName permits multiple mBeans to be registered under the same * name. * * @param mbeanInterface The MBean interface this instance implements * @param mbeanName A custom name for this MBean * @throws ServerRuntimeException */ public static void unregisterMBean(Class<?> mbeanInterface, String mbeanName) { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); try { ObjectName name = generateMBeanObjectName(mbeanInterface.getName(), mbeanName); if (mbs.isRegistered(name)) { logger.info("Unregistering mbean: " + name.toString()); mbs.unregisterMBean(name); } else { logger.warn("Ignoring attempt to unregister unknown mbean: " + name.toString()); } } catch (Exception e) { throw new ServerRuntimeException( "Unable to unregister mbean: interface=" + mbeanInterface + " name=" + mbeanName, e); } } /** * Server helper method to register a JMX MBean. MBeans are registered by a * combination of their MBean interface and the custom mbeanName argument. * The mbeanName permits multiple mBeans to be registered under the same * name. * * @param mbeanInterface The MBean interface this instance implements * @throws ServerRuntimeException */ public static void unregisterMBean(Class<?> mbeanInterface) { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); try { ObjectName name = generateMBeanObjectName(mbeanInterface); if (mbs.isRegistered(name)) { logger.info("Unregistering mbean: " + name.toString()); mbs.unregisterMBean(name); } else { logger.warn("Ignoring attempt to unregister unknown mbean: " + name.toString()); } } catch (Exception e) { throw new ServerRuntimeException("Unable to unregister mbean: interface=" + mbeanInterface, e); } } /** * Client helper method to return an RMI connection on the server whose * properties are the same as this manager instance. * * @return a connection to the server */ public JMXConnector getLocalRMIConnector() { String serviceAddress = null; try { // --- Define security attributes --- HashMap<String, Object> env = new HashMap<String, Object>(); // --- Authentication based on password and access files--- if (authenticationInfo != null && authenticationInfo.isAuthenticationNeeded()) { // Build credentials String[] credentials; if (authenticationInfo.isUseTungstenAuthenticationRealm()) credentials = new String[] { authenticationInfo.getUsername(), authenticationInfo.getDecryptedPassword(), AuthenticationInfo.TUNGSTEN_AUTHENTICATION_REALM }; else credentials = new String[] { authenticationInfo.getUsername(), authenticationInfo.getDecryptedPassword() }; env.put("jmx.remote.credentials", credentials); } // --- SSL --- if (authenticationInfo != null && authenticationInfo.isEncryptionNeeded()) { // Truststore System.setProperty("javax.net.ssl.trustStore", authenticationInfo.getTruststoreLocation()); System.setProperty("javax.net.ssl.trustStorePassword", authenticationInfo.getTruststorePassword()); } serviceAddress = generateServiceAddress(host, beanPort, registryPort, serviceName); JMXServiceURL address = new JMXServiceURL(serviceAddress); JMXConnector connector = JMXConnectorFactory.connect(address, env); return connector; } catch (Exception e) { // --- Try to get more details on the connection problem // String errorMessage = String // .format("Cannot establish a connection with component '%s' at // address %s:%d\n", // serviceName, host, registryPort); String errorMessage = MessageFormat.format( "Cannot establish a connection with component {0} at address {1}:{2}\n{3}", serviceName, host, registryPort, e); String errorReason = null; AssertionError assertionError = null; // Authentication required by server if (e instanceof SecurityException) { errorReason = String.format("Reason=%s\n", e.toString()); assertionError = new AssertionError("Authentication required by server"); } // Encryption required by server else if (e.getCause() instanceof SSLHandshakeException) { errorReason = String .format("Reason=" + "javax.net.ssl.SSLHandshakeException: Server requires SSL.\n"); assertionError = new AssertionError("Encryption required by server"); } else if (e instanceof ConfigurationException) { errorMessage = e.getMessage(); assertionError = new AssertionError("Configuration error"); } // Other IOException else if (e instanceof IOException) { errorMessage = String.format("A component of type '%s' at address %s:%d is not available.\n %s\n", serviceName, host, registryPort, e); errorReason = "Check to be sure that the service is running.\n"; } if (logger.isDebugEnabled()) { logger.debug(String.format(errorMessage + errorReason), e); } throw new ServerRuntimeException(String.format(errorMessage + errorReason), (assertionError != null) ? assertionError : e); } } /** * Client helper method to connector to a JMX manager. */ public static JMXConnector getRMIConnector(String host, int port, String beanServiceName) { JmxManager jmxMgr = new JmxManager(host, port, beanServiceName); return jmxMgr.getLocalRMIConnector(); } /** * Client helper method to obtain a proxy that implements the given * interface by forwarding its methods through the given MBean server to the * named MBean. * * @param clientConnection the MBean server to forward to * @param mbeanClass The MBean interface this instance implements * @param mbeanName A custom name for this MBean * @param notificationBroadcaster If true make the returned proxy implement * NotificationEmitter by forwarding its methods via connection * @return An MBean proxy */ public static Object getMBeanProxy(JMXConnector clientConnection, Class<?> mbeanClass, String mbeanName, boolean notificationBroadcaster, boolean ignored) { try { ObjectName objectName = generateMBeanObjectName(mbeanClass.getName(), mbeanName); return MBeanServerInvocationHandler.newProxyInstance(clientConnection.getMBeanServerConnection(), objectName, mbeanClass, notificationBroadcaster); } catch (Exception e) { throw new ServerRuntimeException("Unable to get proxy connection to bean", e); } } /** * Client helper method to obtain a proxy that implements the given * interface by forwarding its methods through the given MBean server to the * named MBean. * * @param clientConnection the MBean server to forward to * @param mbeanClass The class for which an MBean exists * @param notificationBroadcaster If true make the returned proxy implement * NotificationEmitter by forwarding its methods via connection * @return An MBean proxy */ public static Object getMBeanProxy(JMXConnector clientConnection, Class<?> mbeanClass, boolean notificationBroadcaster) { String mbeanInterfaceClassName = mbeanClass.getName() + "MBean"; Class<?> mbeanInterfaceClass = null; try { mbeanInterfaceClass = Class.forName(mbeanInterfaceClassName); } catch (ClassNotFoundException c) { throw new ServerRuntimeException(String.format( "Cannot get an RMI proxy for class %s because the interface class %s was not found", mbeanClass.getName(), mbeanInterfaceClassName)); } try { ObjectName objectName = generateMBeanObjectName(mbeanClass); return MBeanServerInvocationHandler.newProxyInstance(clientConnection.getMBeanServerConnection(), objectName, mbeanInterfaceClass, notificationBroadcaster); } catch (Exception e) { throw new ServerRuntimeException( String.format("Cannot get an RMI proxy for class %s because of this exception: %s", mbeanClass.getName(), e), e); } } /** * Client helper method to obtain a proxy that implements the given * interface by forwarding its methods through the given MBean server to the * named MBean. * * @param clientConnection the MBean server to forward to * @param mbeanClass The MBean interface this instance implements * @param mbeanName A custom name for this MBean * @param notificationBroadcaster If true make the returned proxy implement * NotificationEmitter by forwarding its methods via connection * @return An MBean proxy */ public static Object getMBeanProxy(JMXConnector clientConnection, Class<?> mbeanClass, Class<?> mbeanInterface, String mbeanName, boolean notificationBroadcaster, boolean ignored) { try { ObjectName objectName = generateMBeanObjectName(mbeanClass.getName(), mbeanName); return MBeanServerInvocationHandler.newProxyInstance(clientConnection.getMBeanServerConnection(), objectName, mbeanInterface, notificationBroadcaster); } catch (Exception e) { throw new ServerRuntimeException("Unable to get proxy connection to bean", e); } } /** * Attach NotificationListener that can be used to listen notifications * emitted by MBean server. * * @param jmxConnector The MBean server connector. * @param mbeanInterface The MBean interface this instance implements. * @param mbeanName A custom name for the MBean. * @param notificationListener User provided NotificationListener instance. * @throws InstanceNotFoundException * @throws Exception */ static public void addNotificationListener(JMXConnector jmxConnector, Class<?> mbeanInterface, String mbeanName, NotificationListener notificationListener, boolean ignored) throws InstanceNotFoundException, Exception { MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection(); ObjectName objectName = generateMBeanObjectName(mbeanInterface.getName(), mbeanName); mbsc.addNotificationListener(objectName, notificationListener, null, null); } public static MBeanServerConnection getServerConnection(JMXConnector jmxConnector) throws Exception { return jmxConnector.getMBeanServerConnection(); } /** * Attach NotificationListener that can be used to listen notifications * emitted by MBean server. * * @param jmxConnector The MBean server connector. * @param mbeanClass The class for which an MBean exists. * @param notificationListener User provided NotificationListener instance. * @throws InstanceNotFoundException * @throws Exception */ static public void addNotificationListener(JMXConnector jmxConnector, Class<?> mbeanClass, NotificationListener notificationListener) throws InstanceNotFoundException, Exception { MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection(); ObjectName objectName = generateMBeanObjectName(mbeanClass); mbsc.addNotificationListener(objectName, notificationListener, null, null); } /** * Remove NotificationListener from this MBean. * * @param jmxConnector The MBean server connector. * @param mbeanInterface The MBean interface this instance implements. * @param mbeanName A custom name for the MBean. * @param notificationListener Previously added NotificationListener * instance. * @throws Exception */ static public void removeNotificationListener(JMXConnector jmxConnector, Class<?> mbeanInterface, String mbeanName, NotificationListener notificationListener, boolean ignored) throws Exception { MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection(); ObjectName objectName = generateMBeanObjectName(mbeanInterface.getName(), mbeanName); mbsc.removeNotificationListener(objectName, notificationListener); } /** * Remove NotificationListener from this MBean. * * @param jmxConnector The MBean server connector. * @param mbeanClass The class for which an MBean exists. * @param notificationListener Previously added NotificationListener * instance. * @throws Exception */ static public void removeNotificationListener(JMXConnector jmxConnector, Class<?> mbeanClass, NotificationListener notificationListener) throws Exception { MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection(); ObjectName objectName = generateMBeanObjectName(mbeanClass); mbsc.removeNotificationListener(objectName, notificationListener); } // Create a service address.addNotificationListener private static String generateServiceAddress(String host, int beanPort, int registryPort, String serviceName) { String serviceAddress = null; if (beanPort == -1) { serviceAddress = String.format("service:jmx:rmi:///jndi/rmi://%s:%d/%s", host, registryPort, serviceName); } else { serviceAddress = String.format("service:jmx:rmi://%s:%d/jndi/rmi://%s:%d/%s", host, beanPort, host, registryPort, serviceName); } if (logger.isDebugEnabled()) { logger.debug("Service address for mbean is: " + serviceAddress); } return serviceAddress; } // Create an MBean name. public static ObjectName generateMBeanObjectName(Class<?> mbeanClass) throws Exception { String className = mbeanClass.getName(); String type = className; String domain = "default"; int lastPeriod = className.lastIndexOf('.'); if (lastPeriod != -1) { domain = className.substring(0, lastPeriod); type = className.substring(className.lastIndexOf('.') + 1); } String name = String.format("%s:type=%s", domain, type); ObjectName objName = new ObjectName(name); if (logger.isDebugEnabled()) { logger.debug("ObjectName is: " + objName.toString()); } return objName; } // Create an MBean name. public static ObjectName generateMBeanObjectName(String mbeanName, String typeName) throws Exception { ObjectName name = new ObjectName(mbeanName + ":type=" + typeName); if (logger.isDebugEnabled()) { logger.debug("ObjectName is: " + name.toString()); } return name; } public void handleNotification(Notification notification, Object handback) { ObjectName objectName = ((MBeanServerNotification) notification).getMBeanName(); if (logger.isDebugEnabled()) { logger.debug(String.format("MBean Added to the MBean server at %s:%d, ObjectName=%s", host, registryPort, objectName)); } } public static DynamicMBeanHelper createHelper(Class<?> mbeanClass) throws Exception { ObjectName mbeanName = generateMBeanObjectName(mbeanClass); MBeanInfo info = ManagementFactory.getPlatformMBeanServer().getMBeanInfo(mbeanName); DynamicMBeanHelper helper = new DynamicMBeanHelper(mbeanClass, mbeanName, info); return helper; } /** * Get the hostname from the local host. Returns the IP address, in textual * form, if no hostname can be found. * * @return the hostname for the local host */ public static String getHostName() { String hostName = null; try { hostName = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { // Intentionally blank } return hostName; } public Registry getRegistry() { if (rmiRegistry == null) rmiRegistry = locateDefaultRegistry(); return rmiRegistry; } public int getBeanPort() { return beanPort; } public static DynamicMBeanHelper createHelper(Class<?> mbeanClass, String alias) throws Exception { ObjectName mbeanName = generateMBeanObjectName(mbeanClass.getName(), alias); // ObjectName mbeanName = generateMBeanObjectName(mbeanClass); MBeanInfo info = ManagementFactory.getPlatformMBeanServer().getMBeanInfo(mbeanName); DynamicMBeanHelper helper = new DynamicMBeanHelper(mbeanClass, mbeanName, info); return helper; } }