/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.management.j2ee; import org.jboss.deployment.DeploymentInfo; import org.jboss.deployment.MainDeployerConstants; import org.jboss.deployment.SubDeployer; import org.jboss.logging.Logger; import org.jboss.management.j2ee.factory.DefaultManagedObjectFactoryMap; import org.jboss.management.j2ee.factory.ManagedObjectFactory; import org.jboss.management.j2ee.factory.ManagedObjectFactoryMap; import org.jboss.system.ServiceControllerMBean; import org.jboss.system.ServiceMBean; import org.jboss.system.ServiceMBeanSupport; import javax.management.JMException; import javax.management.MBeanException; import javax.management.MBeanServer; import javax.management.Notification; import javax.management.NotificationListener; import javax.management.ObjectName; import java.net.InetAddress; import java.util.Collection; import java.util.Iterator; import java.util.Set; /** * The integration MBean for the local JBoss server management domain. This * bridges between the core JBoss JSR-77 agnostic code to the JSR-77 * managed object interfaces. * * @author <a href="mailto:andreas@jboss.org">Andreas Schaefer</a> * @author <a href="mailto:scott.stark@jboss.org">Scott Stark</a> * @version $Revision: 81025 $ */ public class LocalJBossServerDomain extends ServiceMBeanSupport implements NotificationListener, LocalJBossServerDomainMBean { /** * Class logger. */ private static final Logger log = Logger.getLogger(LocalJBossServerDomain.class); private J2EEDomain serverDomain; /** * The name of the MainDeployer */ private ObjectName mainDeployer; /** * The name of the SARDeployer */ private ObjectName sarDeployer; /** * The name of the EARDeployer */ private ObjectName earDeployer; /** * The name of the EJBDeployer */ private ObjectName ejbDeployer; /** * The name of the RARDeployer */ private ObjectName rarDeployer; /** * The name of the JCA connection manager deployer */ private ObjectName jcaCMDeployer; /** * The name of the WARDeployer */ private ObjectName warDeployer; /** * The client application deployer */ private ObjectName carDeployer; /** * The name of the JMS service */ private ObjectName jmsService; /** * The name of the JNDI service */ private ObjectName jndiService; /** * The name of the JTA service */ private ObjectName jtaService; /** * The name of the UserTransaction service */ private ObjectName userTxService; /** * The name of the JavaMail service */ private ObjectName mailService; /** * The name of the RMI_IIOP service */ private ObjectName rmiiiopService; /** * The name of the service which emites URL binding events */ private ObjectName jndiBindingService; /** * A mapping of JMX notifications to ManagedObjectFactory instances */ private ManagedObjectFactoryMap managedObjFactoryMap; private Class managedObjFactoryMapClass = DefaultManagedObjectFactoryMap.class; // ------------------------------------------------------------------------- // Constructors // ------------------------------------------------------------------------- public LocalJBossServerDomain() { } // ------------------------------------------------------------------------- // Properties (Getters/Setters) // ------------------------------------------------------------------------- /** * @return The MainDeployer mbean name * @jmx:managed-attribute */ public ObjectName getMainDeployer() { return mainDeployer; } /** * @param name The MainDeployer mbean name * @jmx:managed-attribute */ public void setMainDeployer(ObjectName name) { this.mainDeployer = name; } /** * @return The SARDeployer mbean name * @jmx:managed-attribute */ public ObjectName getSARDeployer() { return sarDeployer; } /** * @param name The SARDeployer mbean name * @jmx:managed-attribute */ public void setSARDeployer(ObjectName name) { this.sarDeployer = name; } /** * @return The EARDeployer mbean name * @jmx:managed-attribute */ public ObjectName getEARDeployer() { return earDeployer; } /** * @param name The EARDeployer mbean name * @jmx:managed-attribute */ public void setEARDeployer(ObjectName name) { this.earDeployer = name; } /** * @return The EJBDeployer mbean name * @jmx:managed-attribute */ public ObjectName getEJBDeployer() { return ejbDeployer; } /** * @param name The EJBDeployer mbean name * @jmx:managed-attribute */ public void setEJBDeployer(ObjectName name) { this.ejbDeployer = name; } /** * @return The RARDeployer mbean name * @jmx:managed-attribute */ public ObjectName getRARDeployer() { return rarDeployer; } /** * @param name The RARDeployer mbean name * @jmx:managed-attribute */ public void setRARDeployer(ObjectName name) { this.rarDeployer = name; } /** * @return The JCA Connection manager deployer name * @jmx:managed-attribute */ public ObjectName getCMDeployer() { return jcaCMDeployer; } /** * @param name The JCA Connection manager deployer name * @jmx:managed-attribute */ public void setCMDeployer(ObjectName name) { this.jcaCMDeployer = name; } /** * @return The WARDeployer mbean name * @jmx:managed-attribute */ public ObjectName getWARDeployer() { return warDeployer; } /** * @param name The WARDeployer mbean name * @jmx:managed-attribute */ public void setWARDeployer(ObjectName name) { this.warDeployer = name; } /** * @return The CARDeployer mbean name * @jmx:managed-attribute */ public ObjectName getCARDeployer() { return carDeployer; } /** * @param name The CARDeployer mbean name * @jmx:managed-attribute */ public void setCARDeployer(ObjectName name) { this.carDeployer = name; } /** * @return The JMS service mbean name * @jmx:managed-attribute */ public ObjectName getJMSService() { return jmsService; } /** * @param name The JMS service mbean name * @jmx:managed-attribute */ public void setJMSService(ObjectName name) { this.jmsService = name; } /** * @return The JNDI service mbean name * @jmx:managed-attribute */ public ObjectName getJNDIService() { return jndiService; } /** * @param name The JNDI service mbean name * @jmx:managed-attribute */ public void setJNDIService(ObjectName name) { this.jndiService = name; } /** * @return The JTA service mbean name * @jmx:managed-attribute */ public ObjectName getJTAService() { return jtaService; } /** * @param name The JTA service mbean name * @jmx:managed-attribute */ public void setJTAService(ObjectName name) { this.jtaService = name; } /** * @return The JavaMail service mbean name * @jmx:managed-attribute */ public ObjectName getMailService() { return mailService; } /** * @param name The JavaMail service mbean name * @jmx:managed-attribute */ public void setMailService(ObjectName name) { this.mailService = name; } /** * @return The UserTransaction service mbean name * @jmx:managed-attribute */ public ObjectName getUserTransactionService() { return userTxService; } /** * @param name The UserTransaction service mbean name * @jmx:managed-attribute */ public void setUserTransactionService(ObjectName name) { this.userTxService = name; } /** * @return The RMI/IIOP service mbean name * @jmx:managed-attribute */ public ObjectName getRMI_IIOPService() { return rmiiiopService; } /** * @param name The RMI/IIOP service mbean name * @jmx:managed-attribute */ public void setRMI_IIOPService(ObjectName name) { this.rmiiiopService = name; } /** * @return The Jndi binding service mbean name * @jmx:managed-attribute */ public ObjectName getJndiBindingService() { return jndiBindingService; } /** * @param name The Jndi binding service mbean name * @jmx:managed-attribute */ public void setJndiBindingService(ObjectName name) { this.jndiBindingService = name; } /** * @return The ManagementObjFactoryMap class * @jmx:managed-attribute */ public Class getManagementObjFactoryMapClass() { return managedObjFactoryMapClass; } /** * @param cls The ManagementObjFactoryMap class * @jmx:managed-attribute */ public void setManagementObjFactoryMapClass(Class cls) { this.managedObjFactoryMapClass = cls; } /** * The JMX nofication callback. Here we create/destroy JSR77 MBeans based * on the create/destory notifications. * * @param msg the notification msg * @param handback currently unused */ public void handleNotification(Notification msg, Object handback) { MBeanServer mbeanServer = getServer(); if (managedObjFactoryMap == null || mbeanServer == null) { return; } log.debug("handleNotification: " + msg); String type = msg.getType(); Object userData = msg.getUserData(); try { /* As this section keeps growing I should change this to a command dispatch pattern as well. An issue here is that there is a choice made about what 'data' to pass the ManagedObjectFactory based on the event type that probably should be hidden in the factory map. */ if (type.equals(ServiceMBean.CREATE_EVENT)) { ManagedObjectFactory factory = managedObjFactoryMap.getFactory(msg); if (factory != null) { factory.create(mbeanServer, userData); } } else if (type.equals(ServiceMBean.DESTROY_EVENT)) { ManagedObjectFactory factory = managedObjFactoryMap.getFactory(msg); if (factory != null) { factory.destroy(mbeanServer, userData); } } else if (type.equals(SubDeployer.START_NOTIFICATION)) { ManagedObjectFactory factory = managedObjFactoryMap.getFactory(msg); if (factory != null) { factory.create(mbeanServer, userData); } } else if (type.equals(SubDeployer.DESTROY_NOTIFICATION)) { ManagedObjectFactory factory = managedObjFactoryMap.getFactory(msg); if (factory != null) { DeploymentInfo di = (DeploymentInfo) msg.getUserData(); factory.destroy(mbeanServer, di); } } else if (type.equals(MainDeployerConstants.ADD_DEPLOYER)) { ObjectName deployerName = (ObjectName) msg.getUserData(); registerWithDeployer(deployerName); } else if (type.equals(MainDeployerConstants.REMOVE_DEPLOYER)) { ObjectName deployerName = (ObjectName) msg.getUserData(); unregisterWithDeployer(deployerName); } } catch (Throwable t) { log.debug("Failed to handle event", t); } } public String toString() { return "LocalJBossServerDomain { " + super.toString() + " } []"; } public void createService() throws Exception { MBeanServer server = getServer(); setupJ2EEMBeans(server); registerWithController(server); populateFactoryMap(); registerWithCurrentDeployers(server); } /** * Called to destroy the service. This unregisters with all deployers and * then removes all MBeans in this services domain to remove all JSR77 * beans. * * @throws Exception */ protected void destroyService() throws Exception { MBeanServer server = getServer(); unregisterWithCurrentDeployers(server); cleanupLeftoverMBeans(server); unregisterWithController(server); } /** * Register as a listener of the given deployer. * * @param deployerName */ protected void registerWithDeployer(ObjectName deployerName) { log.debug("Registering as listener of deployer: " + deployerName); try { getServer().addNotificationListener(deployerName, this, null, null); } catch (Exception e) { log.debug("Failed to register with deployer: " + deployerName, e); } } /** * Unregister as a listener of the given deployer. * * @param deployerName */ protected void unregisterWithDeployer(ObjectName deployerName) { log.debug("Unregistering as listener of deployer: " + deployerName); try { getServer().removeNotificationListener(deployerName, this); } catch (Exception e) { log.debug("Failed to unregister with deployer: " + deployerName, e); } } /** * Build the ManagedObjectFactoryMap used to obtain the ManagedObjectFactory * instances from notification msgs. * * @throws Exception */ private void populateFactoryMap() throws Exception { // Create the ManagedObjectFactoryMap managedObjFactoryMap = (ManagedObjectFactoryMap) managedObjFactoryMapClass.newInstance(); managedObjFactoryMap.setSARDeployer(sarDeployer); managedObjFactoryMap.setEARDeployer(earDeployer); managedObjFactoryMap.setEJBDeployer(ejbDeployer); managedObjFactoryMap.setRARDeployer(rarDeployer); managedObjFactoryMap.setCMDeployer(jcaCMDeployer); managedObjFactoryMap.setWARDeployer(warDeployer); managedObjFactoryMap.setJMSResource(jmsService); managedObjFactoryMap.setJNDIResource(jndiService); managedObjFactoryMap.setJTAResource(jtaService); managedObjFactoryMap.setJTAResource(userTxService); managedObjFactoryMap.setJavaMailResource(mailService); managedObjFactoryMap.setRMI_IIOPResource(rmiiiopService); } /** * Create the J2EEServer and JVM MBeans. * * @param mbeanServer the MBeanServer to register the mbeans with. */ private void setupJ2EEMBeans(MBeanServer mbeanServer) { // Create Server Component try { log.debug("setupJ2EEMBeans(), create J2EEServer instance"); Package pkg = Package.getPackage("org.jboss"); String vendor = pkg.getSpecificationVendor(); String version = pkg.getImplementationVersion(); // Create the createService serverDomain = new J2EEDomain(serviceName.getDomain()); ObjectName domain = serverDomain.getObjectName(); mbeanServer.registerMBean(serverDomain, domain); // Create single Local J2EEServer MBean J2EEServer j2eeServer = new J2EEServer("Local", domain, vendor, version); ObjectName lServer = j2eeServer.getObjectName(); mbeanServer.registerMBean(j2eeServer, lServer); // Create the JVM MBean String hostName = "localhost"; try { InetAddress lLocalHost = InetAddress.getLocalHost(); hostName = lLocalHost.getHostName(); } catch (Exception e) { // Ignore when host address is not accessible (localhost is used instead) } String vmVendor = System.getProperty("java.vendor"); String vmVersion = System.getProperty("java.version"); String name = vmVendor + " " + vmVersion; JVM jvm = new JVM(name, lServer, vmVersion, vmVendor, hostName); ObjectName jvmName = jvm.getObjectName(); mbeanServer.registerMBean(jvm, jvmName); } catch (JMException jme) { log.debug("setupJ2EEMBeans - unexpected JMException", jme); } catch (Exception e) { log.debug("setupJ2EEMBeans - unexpected exception", e); } } /** * Register as a listener of the ServiceControllerMBean * * @param mbeanServer */ private void registerWithController(MBeanServer mbeanServer) { try { mbeanServer.addNotificationListener(ServiceControllerMBean.OBJECT_NAME, this, null, null); log.debug("Registered as listener of: " + ServiceControllerMBean.OBJECT_NAME); } catch (JMException jme) { log.debug("unexpected exception", jme); } catch (Exception e) { log.debug("unexpected exception", e); } } /** * Unregister as a listener of the ServiceControllerMBean. * * @param mbeanServer */ private void unregisterWithController(MBeanServer mbeanServer) { try { mbeanServer.removeNotificationListener(ServiceControllerMBean.OBJECT_NAME, this); log.debug("UNRegistered as listener of: " + ServiceControllerMBean.OBJECT_NAME); } catch (JMException jme) { log.debug("unexpected exception", jme); } catch (Exception e) { log.debug("unexpected exception", e); } } /** * Register with deployers known to the MainDeployer * * @param mbeanServer * @throws Exception thrown on failure to register as a listener of the * MainDeployer or to obtain the list of deployers */ private void registerWithCurrentDeployers(MBeanServer mbeanServer) throws Exception { log.debug("Registering with all deployers, mainDeployer=" + mainDeployer); mbeanServer.addNotificationListener(mainDeployer, this, null, null); // Obtain the deployers list log.debug("Getting current deployers"); Object[] args = {}; String[] sig = {}; Collection deployers = (Collection) mbeanServer.invoke(mainDeployer, "listDeployers", args, sig); Iterator iter = deployers.iterator(); while (iter.hasNext()) { ObjectName name = (ObjectName) iter.next(); registerWithDeployer(name); } } /** * Unregister with all deployers known to the MainDeployer * * @param mbeanServer * @throws Exception thrown on failure to unregister as a listener of the * MainDeployer or to obtain the list of deployers */ private void unregisterWithCurrentDeployers(MBeanServer mbeanServer) throws Exception { log.debug("Unregistering with all deployers, mainDeployer=" + mainDeployer); mbeanServer.removeNotificationListener(mainDeployer, this); // Obtain the deployers list log.debug("Getting current deployers"); Object[] args = {}; String[] sig = {}; Collection deployers = (Collection) mbeanServer.invoke(mainDeployer, "listDeployers", args, sig); Iterator iter = deployers.iterator(); while (iter.hasNext()) { ObjectName name = (ObjectName) iter.next(); unregisterWithDeployer(name); } } /** * Query for all mbeans in this services domain and unregisters them. * * @throws Exception if the domain query fails */ private void cleanupLeftoverMBeans(MBeanServer mbeanServer) throws Exception { String domain = serviceName.getDomain(); ObjectName domainName = new ObjectName(domain + ":*"); Set domainNames = mbeanServer.queryNames(domainName, null); log.debug("Found " + domainNames.size() + " domain mbeans"); Iterator domainIter = domainNames.iterator(); while (domainIter.hasNext()) { try { ObjectName name = (ObjectName) domainIter.next(); if (name.equals(serviceName)) continue; server.unregisterMBean(name); } catch (MBeanException ignore) { } } } }