001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.jmxremoting;
018
019 import java.io.IOException;
020 import java.net.InetSocketAddress;
021 import java.util.HashMap;
022 import java.util.Map;
023
024 import javax.management.MBeanServer;
025 import javax.management.NotificationFilterSupport;
026 import javax.management.remote.JMXConnectionNotification;
027 import javax.management.remote.JMXConnectorServer;
028 import javax.management.remote.JMXConnectorServerFactory;
029 import javax.management.remote.JMXServiceURL;
030
031 import org.apache.commons.logging.Log;
032 import org.apache.commons.logging.LogFactory;
033 import org.apache.geronimo.gbean.GBeanInfo;
034 import org.apache.geronimo.gbean.GBeanInfoBuilder;
035 import org.apache.geronimo.gbean.GBeanLifecycle;
036 import org.apache.geronimo.system.jmx.MBeanServerReference;
037
038 /**
039 * A connector that supports the server side of JSR 160 JMX Remoting.
040 *
041 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
042 */
043 public class JMXConnector implements JMXConnectorInfo, GBeanLifecycle {
044 protected final MBeanServer mbeanServer;
045 protected final Log log;
046 protected final ClassLoader classLoader;
047 protected String applicationConfigName;
048
049 protected String protocol;
050 protected String host;
051 protected int port = -1;
052 protected String urlPath;
053
054 protected JMXConnectorServer server;
055 protected JMXServiceURL jmxServiceURL;
056
057 // todo remove this as soon as Geronimo supports factory beans
058 public JMXConnector(MBeanServerReference mbeanServerReference, String objectName, ClassLoader classLoader) {
059 this(mbeanServerReference.getMBeanServer(), objectName, classLoader);
060 }
061
062 /**
063 * Constructor for creating the connector. The ClassLoader must be
064 * able to load all the LoginModules used in the JAAS login
065 *
066 * @param mbeanServer the mbean server
067 * @param objectName this connector's object name
068 * @param classLoader the classLoader used to create this connector
069 */
070 public JMXConnector(MBeanServer mbeanServer, String objectName, ClassLoader classLoader) {
071 this.mbeanServer = mbeanServer;
072 this.classLoader = classLoader;
073 log = LogFactory.getLog(objectName);
074 }
075
076 /**
077 * Return the name of the JAAS Application Configuration Entry this
078 * connector uses to authenticate users. If null, users are not
079 * be authenticated (not recommended).
080 *
081 * @return the authentication configuration name
082 */
083 public String getApplicationConfigName() {
084 return applicationConfigName;
085 }
086
087 /**
088 * Set the name of the JAAS Application Configuration Entry this
089 * connector should use to authenticate users. If null, users will not
090 * be authenticated (not recommended).
091 *
092 * @param applicationConfigName the authentication configuration name
093 */
094 public void setApplicationConfigName(String applicationConfigName) {
095 this.applicationConfigName = applicationConfigName;
096 }
097
098 /**
099 * Every connector must specify a property of type InetSocketAddress
100 * because we use that to identify the network services to print a list
101 * during startup. However, this can be read-only since the host and port
102 * are set in the url attribute.
103 */
104 public InetSocketAddress getListenAddress() {
105 return new InetSocketAddress(getHost(), getPort());
106 }
107
108 /**
109 * Gets the protocol to use for the connection.
110 * @return the protocol to use for the connection
111 */
112 public String getProtocol() {
113 return protocol;
114 }
115
116 /**
117 * Sets the protocol to use for the connection.
118 * @param protocol the protocol to use for the connection
119 */
120 public void setProtocol(String protocol) {
121 this.protocol = protocol;
122 }
123
124 /**
125 * Gets the JMX host for this connector.
126 *
127 * @return the JMX host for this connector
128 */
129 public String getHost() {
130 return host;
131 }
132
133 /**
134 * Sets the JMX host for this connector.
135 * @param host the JMX host for this connector
136 */
137 public void setHost(String host) {
138 this.host = host;
139 }
140
141 /**
142 * Gets the JMX port for this connector.
143 *
144 * @return the JMX port for this connector
145 */
146 public int getPort() {
147 return port;
148 }
149
150 /**
151 * Sets the JMX port for this connector.
152 * @param port the JMX port for this connector
153 */
154 public void setPort(int port) {
155 this.port = port;
156 }
157
158 /**
159 * Gets the path within the target server to look for the connection. This is commonly
160 * /jndi/rmi://localhost:1099/JMXConnector
161 * @return the path used to loacate the connector on the target server
162 */
163 public String getUrlPath() {
164 return urlPath;
165 }
166
167 /**
168 * Sets the path within the target server to look for the connection. This is commonly
169 * /jndi/rmi://localhost:1099/JMXConnector
170 * @param urlPath the path used to loacate the connector on the target server
171 */
172 public void setUrlPath(String urlPath) {
173 this.urlPath = urlPath;
174 }
175
176 public void doStart() throws Exception {
177 jmxServiceURL = new JMXServiceURL(protocol, host, port, urlPath);
178 Authenticator authenticator = null;
179 Map env = new HashMap();
180 if (applicationConfigName != null) {
181 authenticator = new Authenticator(applicationConfigName, classLoader);
182 env.put(JMXConnectorServer.AUTHENTICATOR, authenticator);
183 } else {
184 log.warn("Starting unauthenticating JMXConnector for " + jmxServiceURL);
185 }
186 server = JMXConnectorServerFactory.newJMXConnectorServer(jmxServiceURL, env, mbeanServer);
187 NotificationFilterSupport filter = new NotificationFilterSupport();
188 filter.enableType(JMXConnectionNotification.OPENED);
189 filter.enableType(JMXConnectionNotification.CLOSED);
190 filter.enableType(JMXConnectionNotification.FAILED);
191 server.addNotificationListener(authenticator, filter, null);
192 server.start();
193 log.debug("Started JMXConnector " + server.getAddress());
194 }
195
196 public void doStop() throws Exception {
197 try {
198 server.stop();
199 } catch (IOException e) {
200 // java.io.IOException is expected.
201 } catch (Exception e) {
202 // Otherwise, something bad happened. Rethrow the exception.
203 throw e;
204 } finally {
205 server = null;
206 log.debug("Stopped JMXConnector " + jmxServiceURL);
207 }
208 }
209
210 public void doFail() {
211 try {
212 doStop();
213 log.warn("Failure in JMXConnector " + jmxServiceURL);
214 } catch (Exception e) {
215 log.warn("Error stopping JMXConnector after failure", e);
216 }
217 }
218
219 public static final GBeanInfo GBEAN_INFO;
220
221 static {
222 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic("JMX Remoting Connector", JMXConnector.class);
223 infoFactory.addReference("MBeanServerReference", MBeanServerReference.class);
224 infoFactory.addAttribute("objectName", String.class, false);
225 infoFactory.addAttribute("classLoader", ClassLoader.class, false);
226
227 infoFactory.addAttribute("protocol", String.class, true, true);
228 infoFactory.addAttribute("host", String.class, true, true);
229 infoFactory.addAttribute("port", int.class, true, true);
230 infoFactory.addAttribute("urlPath", String.class, true, true);
231 infoFactory.addAttribute("applicationConfigName", String.class, true, true);
232
233 infoFactory.addInterface(JMXConnectorInfo.class);
234
235 infoFactory.setConstructor(new String[]{"MBeanServerReference", "objectName", "classLoader"});
236 GBEAN_INFO = infoFactory.getBeanInfo();
237 }
238
239 public static GBeanInfo getGBeanInfo() {
240 return GBEAN_INFO;
241 }
242 }