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 }