View Javadoc

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