package com.onaro.sanscreen.client.jmxframework; import java.io.IOException; import java.lang.management.ManagementFactory; import java.net.BindException; import java.rmi.registry.LocateRegistry; import java.rmi.server.ExportException; import java.util.LinkedList; import java.util.List; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; import javax.naming.NameAlreadyBoundException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.onaro.commons.prefs.PreferencesWrapper; import com.onaro.sanscreen.client.jmxframework.service.ShutdownService; /** * Singleton class. Responsible of managing the life cycle of all the mbean services. * * * @since 05/01/2008 * @author john.cohen */ public final class JmxServiceManager { /** * Key to search the registry. The value of this key will be the port number to use, otherwise the default value will * be used instead. {@link #DEFAULT_RMI_PORT} */ private static final String JMX_PORT_KEY = "jmx_port"; //$NON-NLS-1$ /** * Logger of this class */ private static final Logger logger = LogManager.getLogger(JmxServiceManager.class); /** * List of available services. */ private static List services; static{ services = new LinkedList(); services.add(new ShutdownService()); } /** * Singleton instance created by a private constructor. */ private static JmxServiceManager INSTANCE = new JmxServiceManager(); public static JmxServiceManager getInstance(){ return INSTANCE; } /** * Private Constructor. */ private JmxServiceManager() { try { final int rmiPort = retrieveRMIPort(); startRMIRegistry(rmiPort); // Create an RMI connector and start it, Port Number will be stored // in the Registry of the Machine JMXServiceURL url = new JMXServiceURL(JmxServiceManagerConstants.JMX_BASE_URL + "localhost:" + rmiPort + JmxServiceManagerConstants.GUI_PATH); //$NON-NLS-1$ JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, ManagementFactory.getPlatformMBeanServer()); cs.start(); } catch (IOException e) { if (e.getCause() != null && e.getCause() instanceof NameAlreadyBoundException) { logger.warn("An OnCommand Insight client JMX Service is already registered on this machine. JMX Service will not be available for this SANscreen Client instance."); //$NON-NLS-1$ } else { logger.error("Failed to start jmx service - " + e.getMessage(), e); //$NON-NLS-1$ } } catch (Exception e) { logger.error("Failed to start jmx service - " + e.getMessage(), e); //$NON-NLS-1$ } } /** * Retrieves the port number used for the RMI registry. If the JMX_PORT_KEY doesn't exist * then write the DEFAULT_RMI_PORT into the registry. * * This method is public only so that the UTs can access it. * * @return rmi port associated to the JMX */ private static int retrieveRMIPort() { int rmiPort; PreferencesWrapper prefs = FrameworkPref.getJmxClient(); try{ rmiPort = prefs.getInt(JMX_PORT_KEY); }catch (Exception e){ // The "key" doesn't exist yet. Apply default value. prefs.putInt(JMX_PORT_KEY, JmxServiceManagerConstants.DEFAULT_RMI_PORT); rmiPort = JmxServiceManagerConstants.DEFAULT_RMI_PORT; } return rmiPort; } /** * Loops through all the services being managed and starts them one by one. */ public void start(){ for (FrameworkService service: services){ service.start(); } } /** * Starts RMI Registry in this JVM if its not already running. * @param rmiPort */ private void startRMIRegistry(final int rmiPort) { try { LocateRegistry.createRegistry(rmiPort); } catch (ExportException e) { if (e.getCause() != null && e.getCause() instanceof BindException) { // This means the RMI port is already bound, most likely there's another instance of the client running // do nothing return; } else { logger.error("Failed to start RMI Registry in port: [" + rmiPort + "]: ", e); //$NON-NLS-1$ //$NON-NLS-2$ } } catch (Exception e) { // It could be that RMI Registry is not running in this JVM // Let's try to create one. logger.error("Failed to start RMI Registry in port: [" + rmiPort + "]:", e); //$NON-NLS-1$ //$NON-NLS-2$ return; } } }