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 */ ConnectorServer(JMXServiceURL serviceURL, String name)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 */ ConnectorServer(JMXServiceURL svcUrl, Map<String,?> environment, String name)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 doStart()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 doStop()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 */ startRegistry(String hostPath)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 stopRegistry()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