1 25 package org.objectweb.jonas.jmx; 26 27 import java.io.IOException ; 28 import java.lang.reflect.Method ; 29 import java.net.URI ; 30 import java.util.ArrayList ; 31 import java.util.HashMap ; 32 import java.util.Iterator ; 33 import java.util.Map ; 34 import java.util.Properties ; 35 36 import javax.management.InstanceNotFoundException ; 37 import javax.management.JMException ; 38 import javax.management.ListenerNotFoundException ; 39 import javax.management.MBeanServerConnection ; 40 import javax.management.MBeanServerNotification ; 41 import javax.management.Notification ; 42 import javax.management.NotificationListener ; 43 import javax.management.ObjectName ; 44 import javax.management.remote.JMXConnector ; 45 import javax.management.remote.JMXConnectorFactory ; 46 import javax.management.remote.JMXConnectorServer ; 47 import javax.management.remote.JMXConnectorServerFactory ; 48 import javax.management.remote.JMXServiceURL ; 49 import javax.naming.Context ; 50 import javax.naming.InitialContext ; 51 import javax.naming.NamingException ; 52 53 import org.objectweb.carol.rmi.util.PortNumber; 54 import org.objectweb.carol.util.configuration.CarolDefaultValues; 55 import org.objectweb.carol.util.configuration.ConfigurationRepository; 56 import org.objectweb.carol.util.configuration.ProtocolConfiguration; 57 58 import org.objectweb.jonas.common.Log; 59 import org.objectweb.jonas.discovery.DiscEvent; 60 import org.objectweb.jonas.service.JonasAlreadyStartedException; 61 import org.objectweb.jonas.service.ServiceException; 62 63 import org.objectweb.util.monolog.api.BasicLevel; 64 import org.objectweb.util.monolog.api.Logger; 65 66 74 75 public class JmxServiceImpl extends AbsJmxServiceImpl implements NotificationListener { 76 77 80 private static final String MX4J_COMMONS_LOGGER_CLASSNAME = "mx4j.log.CommonsLogger"; 81 82 85 private static final String MX4J_LOG_CLASSNAME = "mx4j.log.Log"; 86 87 90 private static final String MX4J_LOGGER_CLASS = "mx4j.log.Logger"; 91 92 97 private String rmiConnectorName = null; 98 99 102 public String getRmiConnectorName() { 103 return this.rmiConnectorName; 104 } 105 106 109 private static final String JRMP = "jrmp"; 110 113 private static final String IIOP = "iiop"; 114 117 private static final String JEREMIE = "jeremie"; 118 121 private static final String CMI = "cmi"; 122 128 private JMXConnectorServer [] connectorServers = null; 129 130 133 private JMXServiceURL [] connectorServerURLs = null; 134 135 139 private Map managedServersToUrls = null; 140 143 private Map managedServersToConnectors = null; 144 147 private Map managedServersToConnections = null; 148 149 152 private static Logger logger = Log.getLogger(Log.JONAS_JMX_PREFIX); 153 private static Logger loggerDomain = Log.getLogger(Log.JONAS_DOMAIN_MANAGEMENT_PREFIX); 154 159 public void doInit(Context ctx) throws ServiceException { 160 Class mx4jCommonsLoggerClass = null; 163 try { 164 mx4jCommonsLoggerClass = Thread.currentThread().getContextClassLoader().loadClass(MX4J_COMMONS_LOGGER_CLASSNAME); 165 if (logger.isLoggable(BasicLevel.DEBUG)) { 166 logger.log(BasicLevel.DEBUG, "Class " + MX4J_COMMONS_LOGGER_CLASSNAME + " founded"); 167 } 168 Object o = mx4jCommonsLoggerClass.newInstance(); 169 170 171 172 Class clazz = Thread.currentThread().getContextClassLoader().loadClass(MX4J_LOG_CLASSNAME); 174 Class mx4jLoggerClass = Thread.currentThread().getContextClassLoader().loadClass(MX4J_LOGGER_CLASS); 175 176 177 Method m = clazz.getMethod("redirectTo", new Class [] {mx4jLoggerClass}); 179 m.invoke(clazz, new Object [] {o}); 180 if (logger.isLoggable(BasicLevel.DEBUG)) { 181 logger.log(BasicLevel.DEBUG, "MX4J logging redirected to the Jakarta commons logger"); 182 } 183 } catch (ClassNotFoundException cnfe) { 184 if (logger.isLoggable(BasicLevel.DEBUG)) { 185 logger.log(BasicLevel.DEBUG, "Class " + MX4J_COMMONS_LOGGER_CLASSNAME + " not found: " + cnfe); 186 } 187 } catch (Exception e) { 188 if (logger.isLoggable(BasicLevel.WARN)) { 189 logger.log(BasicLevel.WARN, "Problem with " + MX4J_COMMONS_LOGGER_CLASSNAME + " instance creation " + e); 190 } 191 } 192 super.doInit(ctx); 193 } 194 199 public void doStart() throws ServiceException { 200 String serverName = getJonasServerName(); 201 try { 202 RMIConnector rmiConnector = new RMIConnectorImpl(getJmxServer()); 205 InitialContext ictx = new InitialContext (); 207 rmiConnectorName = "RMIConnector_" + serverName; 208 ictx.rebind(rmiConnectorName, rmiConnector); 209 ictx.close(); 210 211 int nbProtocols = ConfigurationRepository.getActiveConfigurationsNumber(); 218 connectorServerURLs = new JMXServiceURL [nbProtocols]; 219 connectorServers = new JMXConnectorServer [nbProtocols]; 220 ProtocolConfiguration[] protocolConfigurations = ConfigurationRepository.getConfigurations(); 222 String serviceURL = null; 223 for (int i = 0; i < protocolConfigurations.length; i++) { 224 String carolProtocol = protocolConfigurations[i].getName(); 225 String providerUrl = protocolConfigurations[i].getProviderURL(); 226 URI carolURL = new URI (providerUrl); 227 String host = carolURL.getHost(); 228 String port = String.valueOf(carolURL.getPort()); 229 String scheme = carolURL.getScheme(); 230 String ictxFactory = protocolConfigurations[i].getProtocol().getInitialContextFactoryClassName(); 231 Properties props = new Properties (); 232 if (scheme.equals("rmi")) { 233 String myName = "jrmpconnector_" + serverName; 235 serviceURL = "service:jmx:rmi://" + host; 236 int jrmpExportedPort = 0; 237 String propertyName = CarolDefaultValues.SERVER_JRMP_PORT; 239 Properties p = ConfigurationRepository.getProperties(); 240 if (p != null) { 241 jrmpExportedPort = PortNumber.strToint(p.getProperty(propertyName, "0"), propertyName); 242 } 243 if (jrmpExportedPort > 0) { 244 serviceURL += ":" + jrmpExportedPort; 245 } 246 serviceURL += "/jndi/rmi://" 247 + host + ":" + port + "/" 248 + myName; 249 250 props.put(Context.INITIAL_CONTEXT_FACTORY, ictxFactory); 251 props.put(Context.PROVIDER_URL, providerUrl); 252 } else if (scheme.equals("jrmi")) { String myName = "jeremieconnector_" + serverName; 254 serviceURL = "service:jmx:rmi://" + host; 255 int jeremieExportedPort = 0; 256 String propertyName = CarolDefaultValues.SERVER_JEREMIE_PORT; 258 Properties p = ConfigurationRepository.getProperties(); 259 if (p != null) { 260 jeremieExportedPort = PortNumber.strToint(p.getProperty(propertyName, "0"), propertyName); 261 jeremieExportedPort++; 263 } 264 if (jeremieExportedPort > 1024) { 265 serviceURL += ":" + jeremieExportedPort; 266 } 267 serviceURL += "/jndi/jrmi://" 268 + host + ":" + port + "/" 269 + myName; 270 271 props.put(Context.INITIAL_CONTEXT_FACTORY, ictxFactory); 272 props.put(Context.PROVIDER_URL, providerUrl); 273 } else if (scheme.equals("cmi")) { 274 String myName = "cmiconnector_" + serverName; 276 serviceURL = "service:jmx:rmi://" + host 277 + "/jndi/cmi://" 278 + host + ":" + port + "/" 279 + myName; 280 props.put(Context.INITIAL_CONTEXT_FACTORY, ictxFactory); 281 props.put(Context.PROVIDER_URL, providerUrl); 282 } else if (scheme.equals("iiop")) { 283 String myName = "iiopconnector_" + serverName; 285 287 serviceURL = "service:jmx:iiop://" + host 288 + "/jndi/iiop://" 289 + host + ":" + port + "/" 290 + myName; 291 292 props.put("java.naming.corba.orb", new InitialContext ().lookup("java:comp/ORB")); 293 } else { 294 connectorServerURLs[i] = null; 296 continue; 297 } 298 299 JMXServiceURL url = new JMXServiceURL (serviceURL); 300 JMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, (Map ) props, null); 302 connectorServers[i] = connectorServer; 303 String connectorObjectName = "connector_" + carolProtocol; 305 ObjectName connectorServerName = JonasObjectName.jmxConnectorServer(scheme, connectorObjectName); 306 getJmxServer().registerMBean(connectorServer, connectorServerName); 307 try { 309 connectorServer.start(); 310 connectorServerURLs[i] = connectorServer.getAddress(); 311 } catch (IllegalArgumentException e) { 312 throw e; 313 } 314 } 315 } catch (javax.naming.NameAlreadyBoundException ne) { 316 if (logger.isLoggable(BasicLevel.DEBUG)) { 317 logger.log(BasicLevel.DEBUG, "Cannot start JMX service " + ne); 318 } 319 throw new JonasAlreadyStartedException(); 320 } catch (Exception e) { 321 if (logger.isLoggable(BasicLevel.DEBUG)) { 322 logger.log(BasicLevel.DEBUG, "Cannot start JMX service " + e); 323 } 324 throw new ServiceException("Cannot start JMX service", e); 325 } 326 327 try { 330 ObjectName delegate = ObjectName.getInstance("JMImplementation:type=MBeanServerDelegate"); 331 getJmxServer().addNotificationListener(delegate, this, null, null); 332 } catch (JMException me) { 333 if (logger.isLoggable(BasicLevel.DEBUG)) { 334 logger.log(BasicLevel.DEBUG, 335 "JMX service could not be added as notification listener for MBeanServerNotifications " 336 + "related to the REGISTRATION or UNREGISTRETION of JOnAS management MBeans"); 337 } 338 } 339 managedServersToConnectors = new HashMap (); 341 managedServersToConnections = new HashMap (); 342 managedServersToUrls = new HashMap (); 343 } 344 347 public void doStop() { 348 try { 349 InitialContext ictx = new InitialContext (); 350 ictx.unbind("RMIConnector_" + getJonasServerName()); 351 ictx.close(); 352 353 for (int i = 0; i < connectorServers.length; i++) { 357 connectorServers[i].stop(); 358 } 359 } catch (Exception e) { 360 logger.log(BasicLevel.ERROR, "Cannot Unbind Jmx RMI Connector" + e); 361 } 362 ObjectName domainOn = J2eeObjectName.J2EEDomain(getDomainName()); 364 try { 365 getJmxServer().unregisterMBean(domainOn); 366 } catch (Exception e) { 367 logger.log(BasicLevel.INFO, "Cannot unregister JEEDomain MBean:" + domainOn.toString()); 368 } 369 ObjectName serverOn = J2eeObjectName.J2EEServer(getDomainName(), getJonasServerName()); 370 try { 371 getJmxServer().unregisterMBean(serverOn); 372 } catch (Exception e) { 373 logger.log(BasicLevel.INFO, "Cannot unregister JEEServer MBean:" + serverOn.toString()); 374 } 375 releaseJmxServer(); 377 378 if (logger.isLoggable(BasicLevel.DEBUG)) { 379 logger.log(BasicLevel.DEBUG, "JMX Service stopped"); 380 } 381 } 382 383 384 388 public JMXServiceURL [] getConnectorServerURLs() { 389 return this.connectorServerURLs; 390 } 391 392 398 public void handleNotification(Notification notification, Object handback) { 399 if (notification instanceof MBeanServerNotification ) { 400 String type = notification.getType(); 401 ObjectName registeredOn = ((MBeanServerNotification ) notification).getMBeanName(); 403 String name = registeredOn.getKeyProperty("name"); 404 if ((name != null) && (name.equals("discoveryEnroller") || name.equals("discoveryClient"))) { 406 if (type.equals(MBeanServerNotification.REGISTRATION_NOTIFICATION)) { 407 try { 408 getJmxServer().addNotificationListener(registeredOn, this, null, null); 410 if (loggerDomain.isLoggable(BasicLevel.DEBUG)) { 411 loggerDomain.log(BasicLevel.DEBUG, "J2EEDomain (this) registered as listener to notifs emitted by " + registeredOn); 412 } 413 } catch (InstanceNotFoundException e) { 414 e.printStackTrace(); 416 } 417 } 418 if (type.equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) { 419 try { 420 getJmxServer().removeNotificationListener(registeredOn, this); 422 if (loggerDomain.isLoggable(BasicLevel.DEBUG)) { 423 loggerDomain.log(BasicLevel.DEBUG, "J2EEDomain (this) removed listener for notifs emitted by " + registeredOn); 424 } 425 } catch (InstanceNotFoundException e) { 426 e.printStackTrace(); 428 } catch (ListenerNotFoundException e) { 429 e.printStackTrace(); 431 } 432 } 433 } 434 } else { 435 String type = notification.getType(); 437 String message = notification.getMessage(); 438 DiscEvent userData = (DiscEvent) notification.getUserData(); 439 String source = ((ObjectName ) notification.getSource()).toString(); 440 String state = userData.getState(); 441 if (loggerDomain.isLoggable(BasicLevel.DEBUG)) { 442 loggerDomain.log(BasicLevel.DEBUG, "Treat notification:"); 443 loggerDomain.log(BasicLevel.DEBUG, "- source: " + source); 444 loggerDomain.log(BasicLevel.DEBUG, "- type: " + type); 445 loggerDomain.log(BasicLevel.DEBUG, "- data: "); 446 loggerDomain.log(BasicLevel.DEBUG, "--- state: " + state); 447 loggerDomain.log(BasicLevel.DEBUG, "--- serverName : " + userData.getServerName()); 448 loggerDomain.log(BasicLevel.DEBUG, "--- domainName : " + userData.getDomainName()); 449 if (userData.getConnectorURL() != null) { 450 String [] urls = userData.getConnectorURL(); 451 for (int i = 0; i < urls.length; i++) { 452 loggerDomain.log(BasicLevel.DEBUG, "--- urls : " + urls[i]); 453 } 454 } 455 loggerDomain.log(BasicLevel.DEBUG, ""); 456 } 457 if (state.equals(DiscEvent.RUNNING)) { 458 String [] urls = userData.getConnectorURL(); 459 for (int i = 0; i < urls.length; i++) { 460 addServer(userData.getDomainName(), userData.getServerName(), urls[i]); 461 } 462 } else if (state.equals(DiscEvent.STOPPING)) { 463 removeServer(userData.getDomainName(), userData.getServerName()); 464 } 465 } 466 } 467 475 public void addServer(String domainName, String serverName, String connectorServerURL) { 476 if (loggerDomain.isLoggable(BasicLevel.DEBUG)) { 477 loggerDomain.log(BasicLevel.DEBUG, "domain name: " + domainName + ", server name: " + serverName + ", url: " + connectorServerURL); 478 } 479 if (domainName.equals(getDomainName())) { 480 if (!managedServersToUrls.containsKey(serverName)) { 482 boolean created; 484 try { 485 created = createConnection(serverName, connectorServerURL); 486 } catch (Exception e) { 487 created = false; 488 if (loggerDomain.isLoggable(BasicLevel.WARN)) { 489 loggerDomain.log(BasicLevel.WARN, "Could not create JMX connection for server " + serverName , e); 490 } 491 } 492 if (created) { 493 ArrayList urls = new ArrayList (); 494 urls.add(connectorServerURL); 495 managedServersToUrls.put(serverName, urls); 496 } 497 } } else { 500 if (loggerDomain.isLoggable(BasicLevel.WARN)) { 501 loggerDomain.log(BasicLevel.WARN, "The server named " + serverName + " was not started in the management domain " 502 + getDomainName() + ", but in management domain " + domainName); 503 } 504 } 505 } 506 507 515 private boolean createConnection(String serverName, String connectorServerURL) throws NamingException , IOException { 516 boolean created = false; 517 MBeanServerConnection connection; 518 JMXConnector connector = null; 520 JMXServiceURL url = new JMXServiceURL (connectorServerURL); 521 Map env = null; 522 if (url.getProtocol().equals("iiop")) { 523 env = new HashMap (); 524 env.put("java.naming.corba.orb", new InitialContext ().lookup("java:comp/ORB")); 525 } 526 connector = JMXConnectorFactory.newJMXConnector(url, env); 527 connector.connect(env); 528 connection = connector.getMBeanServerConnection(); 529 if (connection != null) { 530 testConnection(connection, serverName); 532 if (managedServersToConnections.containsKey(serverName)) { 533 JMXConnector oldConnector = (JMXConnector ) managedServersToConnectors.get(serverName); 541 try { 542 oldConnector.close(); 543 } catch (IOException e1) { 544 } 545 } 546 managedServersToConnections.put(serverName, connection); 547 managedServersToConnectors.put(serverName, connector); 548 created = true; 549 loggerDomain.log(BasicLevel.INFO, "MBeanServerConnection created for connecting to server " + serverName + " using URL: " + connectorServerURL); 550 } else { 551 if (connector != null) { 552 try { 553 connector.close(); 554 } catch (IOException e1) { 555 } 556 } 557 } 558 return created; 559 } 560 561 private boolean testConnection(MBeanServerConnection connection, String serverName) { 562 boolean ok = false; 563 try { 564 Integer nb = connection.getMBeanCount(); 565 568 ok = true; 569 } catch (IOException ioe) { 570 ioe.printStackTrace(); 571 } 572 return ok; 573 } 574 575 580 public void removeServer(String domainName, String serverName) { 581 if (domainName.equals(getDomainName())) { 582 584 managedServersToConnections.remove(serverName); 585 JMXConnector connector = (JMXConnector ) managedServersToConnectors.remove(serverName); 586 if (connector != null) { 587 try { 588 connector.close(); 589 } catch (IOException e1) { 590 } 591 } 592 managedServersToUrls.remove(serverName); 593 } else { 594 if (loggerDomain.isLoggable(BasicLevel.WARN)) { 595 loggerDomain.log(BasicLevel.WARN, "The server named " + serverName + " was not started in the management domain " 596 + getDomainName() + ", but in management domain " + domainName); 597 } 598 } 599 } 600 605 public MBeanServerConnection getServerConnection(String serverName) { 606 return (MBeanServerConnection ) managedServersToConnections.get(serverName); 607 } 608 } 609 | Popular Tags |