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.net.InetSocketAddress;
020 import java.util.HashMap;
021 import java.util.Map;
022
023 import javax.management.MBeanServer;
024 import javax.management.NotificationFilterSupport;
025 import javax.management.remote.JMXConnectionNotification;
026 import javax.management.remote.JMXConnectorServer;
027 import javax.management.remote.JMXConnectorServerFactory;
028 import javax.management.remote.JMXServiceURL;
029
030 import org.apache.commons.logging.Log;
031 import org.apache.commons.logging.LogFactory;
032 import org.apache.geronimo.gbean.GBeanInfo;
033 import org.apache.geronimo.gbean.GBeanInfoBuilder;
034 import org.apache.geronimo.gbean.GBeanLifecycle;
035 import org.apache.geronimo.system.jmx.MBeanServerReference;
036
037 /**
038 * A Connector that supports the server sideof JSR 160 JMX Remoting.
039 *
040 * @version $Rev: 555111 $ $Date: 2007-07-10 19:25:31 -0400 (Tue, 10 Jul 2007) $
041 */
042 public class JMXConnector implements JMXConnectorInfo, GBeanLifecycle {
043 private final MBeanServer mbeanServer;
044 private final Log log;
045 private final ClassLoader classLoader;
046 private String applicationConfigName;
047 private Authenticator authenticator;
048
049 private String protocol;
050 private String host;
051 private int port = -1;
052 private String urlPath;
053
054 private JMXConnectorServer server;
055 private 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 Map env = new HashMap();
179 if (applicationConfigName != null) {
180 authenticator = new Authenticator(applicationConfigName, classLoader);
181 env.put(JMXConnectorServer.AUTHENTICATOR, authenticator);
182 } else {
183 log.warn("Starting unauthenticating JMXConnector for " + jmxServiceURL);
184 }
185 server = JMXConnectorServerFactory.newJMXConnectorServer(jmxServiceURL, env, mbeanServer);
186 NotificationFilterSupport filter = new NotificationFilterSupport();
187 filter.enableType(JMXConnectionNotification.OPENED);
188 filter.enableType(JMXConnectionNotification.CLOSED);
189 filter.enableType(JMXConnectionNotification.FAILED);
190 server.addNotificationListener(authenticator, filter, null);
191 server.start();
192 log.debug("Started JMXConnector " + server.getAddress());
193 }
194
195 public void doStop() throws Exception {
196 try {
197 server.stop();
198 } catch (java.io.IOException e) {
199 // java.io.IOException is expected.
200 } catch (Exception e) {
201 // Otherwise, something bad happened. Rethrow the exception.
202 throw e;
203 }
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 }