blob: a00772a6940d84e28ccf0f854f2a66eb8c0d024e [file] [log] [blame]
Jake Slack03928ae2014-05-13 18:41:56 -07001//
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
19package org.eclipse.jetty.jmx;
20
21import java.lang.management.ManagementFactory;
22import java.net.InetAddress;
23import java.net.ServerSocket;
24import java.rmi.registry.LocateRegistry;
25import java.rmi.registry.Registry;
26import java.rmi.server.UnicastRemoteObject;
27import java.util.Map;
28
29import javax.management.MBeanServer;
30import javax.management.ObjectName;
31import javax.management.remote.JMXConnectorServer;
32import javax.management.remote.JMXConnectorServerFactory;
33import javax.management.remote.JMXServiceURL;
34
35import org.eclipse.jetty.util.component.AbstractLifeCycle;
36import org.eclipse.jetty.util.log.Log;
37import org.eclipse.jetty.util.log.Logger;
38import org.eclipse.jetty.util.thread.ShutdownThread;
39
40
41/* ------------------------------------------------------------ */
42/**
43 * AbstractLifeCycle wrapper for JMXConnector Server
44 */
45public 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}