Home | History | Annotate | Download | only in jmx
      1 //
      2 //  ========================================================================
      3 //  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
      4 //  ------------------------------------------------------------------------
      5 //  All rights reserved. This program and the accompanying materials
      6 //  are made available under the terms of the Eclipse Public License v1.0
      7 //  and Apache License v2.0 which accompanies this distribution.
      8 //
      9 //      The Eclipse Public License is available at
     10 //      http://www.eclipse.org/legal/epl-v10.html
     11 //
     12 //      The Apache License v2.0 is available at
     13 //      http://www.opensource.org/licenses/apache2.0.php
     14 //
     15 //  You may elect to redistribute this code under either of these licenses.
     16 //  ========================================================================
     17 //
     18 
     19 package org.eclipse.jetty.jmx;
     20 
     21 import java.lang.management.ManagementFactory;
     22 import java.net.InetAddress;
     23 import java.net.ServerSocket;
     24 import java.rmi.registry.LocateRegistry;
     25 import java.rmi.registry.Registry;
     26 import java.rmi.server.UnicastRemoteObject;
     27 import java.util.Map;
     28 
     29 import javax.management.MBeanServer;
     30 import javax.management.ObjectName;
     31 import javax.management.remote.JMXConnectorServer;
     32 import javax.management.remote.JMXConnectorServerFactory;
     33 import javax.management.remote.JMXServiceURL;
     34 
     35 import org.eclipse.jetty.util.component.AbstractLifeCycle;
     36 import org.eclipse.jetty.util.log.Log;
     37 import org.eclipse.jetty.util.log.Logger;
     38 import org.eclipse.jetty.util.thread.ShutdownThread;
     39 
     40 
     41 /* ------------------------------------------------------------ */
     42 /**
     43  * AbstractLifeCycle wrapper for JMXConnector Server
     44  */
     45 public class ConnectorServer extends AbstractLifeCycle
     46 {
     47     private static final Logger LOG = Log.getLogger(ConnectorServer.class);
     48 
     49     JMXConnectorServer _connectorServer;
     50     Registry _registry;
     51 
     52     /* ------------------------------------------------------------ */
     53     /**
     54      * Constructs connector server
     55      *
     56      * @param serviceURL the address of the new connector server.
     57      * The actual address of the new connector server, as returned
     58      * by its getAddress method, will not necessarily be exactly the same.
     59      * @param name object name string to be assigned to connector server bean
     60      * @throws Exception
     61      */
     62     public ConnectorServer(JMXServiceURL serviceURL, String name)
     63         throws Exception
     64     {
     65         this(serviceURL, null, name);
     66     }
     67 
     68     /* ------------------------------------------------------------ */
     69     /**
     70      * Constructs connector server
     71      *
     72      * @param svcUrl the address of the new connector server.
     73      * The actual address of the new connector server, as returned
     74      * by its getAddress method, will not necessarily be exactly the same.
     75      * @param environment  a set of attributes to control the new connector
     76      * server's behavior. This parameter can be null. Keys in this map must
     77      * be Strings. The appropriate type of each associated value depends on
     78      * the attribute. The contents of environment are not changed by this call.
     79      * @param name object name string to be assigned to connector server bean
     80      * @throws Exception
     81      */
     82     public ConnectorServer(JMXServiceURL svcUrl, Map<String,?> environment, String name)
     83          throws Exception
     84     {
     85     	String urlPath = svcUrl.getURLPath();
     86     	int idx = urlPath.indexOf("rmi://");
     87     	if (idx > 0)
     88     	{
     89     	    String hostPort = urlPath.substring(idx+6, urlPath.indexOf('/', idx+6));
     90     	    String regHostPort = startRegistry(hostPort);
     91     	    if (regHostPort != null) {
     92     	        urlPath = urlPath.replace(hostPort,regHostPort);
     93     	        svcUrl = new JMXServiceURL(svcUrl.getProtocol(), svcUrl.getHost(), svcUrl.getPort(), urlPath);
     94     	    }
     95     	}
     96         MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
     97         _connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(svcUrl, environment, mbeanServer);
     98         mbeanServer.registerMBean(_connectorServer,new ObjectName(name));
     99     }
    100 
    101 	/* ------------------------------------------------------------ */
    102     /**
    103      * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
    104      */
    105     @Override
    106     public void doStart()
    107         throws Exception
    108     {
    109         _connectorServer.start();
    110         ShutdownThread.register(0, this);
    111 
    112         LOG.info("JMX Remote URL: {}", _connectorServer.getAddress().toString());
    113     }
    114 
    115     /* ------------------------------------------------------------ */
    116     /**
    117      * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
    118      */
    119     @Override
    120     public void doStop()
    121         throws Exception
    122     {
    123         ShutdownThread.deregister(this);
    124         _connectorServer.stop();
    125         stopRegistry();
    126     }
    127 
    128     /**
    129      * Check that local RMI registry is used, and ensure it is started. If local RMI registry is being used and not started, start it.
    130      *
    131      * @param hostPath
    132      *            hostname and port number of RMI registry
    133      * @throws Exception
    134      */
    135     private String startRegistry(String hostPath) throws Exception
    136     {
    137         int rmiPort = 1099; // default RMI registry port
    138         String rmiHost = hostPath;
    139 
    140         int idx = hostPath.indexOf(':');
    141         if (idx > 0)
    142         {
    143             rmiPort = Integer.parseInt(hostPath.substring(idx + 1));
    144             rmiHost = hostPath.substring(0,idx);
    145         }
    146 
    147         // Verify that local registry is being used
    148         InetAddress hostAddress = InetAddress.getByName(rmiHost);
    149         if(hostAddress.isLoopbackAddress())
    150         {
    151             if (rmiPort == 0)
    152             {
    153                 ServerSocket socket = new ServerSocket(0);
    154                 rmiPort = socket.getLocalPort();
    155                 socket.close();
    156             }
    157             else
    158             {
    159                 try
    160                 {
    161                     // Check if a local registry is already running
    162                     LocateRegistry.getRegistry(rmiPort).list();
    163                     return null;
    164                 }
    165                 catch (Exception ex)
    166                 {
    167                     LOG.ignore(ex);
    168                 }
    169             }
    170 
    171             _registry = LocateRegistry.createRegistry(rmiPort);
    172             Thread.sleep(1000);
    173 
    174             rmiHost = InetAddress.getLocalHost().getCanonicalHostName();
    175             return rmiHost + ':' + Integer.toString(rmiPort);
    176         }
    177 
    178         return null;
    179     }
    180 
    181     private void stopRegistry()
    182     {
    183         if (_registry != null)
    184         {
    185             try
    186             {
    187                 UnicastRemoteObject.unexportObject(_registry,true);
    188             }
    189             catch (Exception ex)
    190             {
    191                 LOG.ignore(ex);
    192             }
    193         }
    194     }
    195 }
    196