User: mnf999 Date: 01/12/18 22:26:19 Modified: src/main/org/jboss/system ServiceController.java Log: The ServiceController logic, start and stop dependent beans automatically, simplified logic Revision Changes Path 1.17 +494 -518 jboss/src/main/org/jboss/system/ServiceController.java Index: ServiceController.java =================================================================== RCS file: /cvsroot/jboss/jboss/src/main/org/jboss/system/ServiceController.java,v retrieving revision 1.16 retrieving revision 1.17 diff -u -r1.16 -r1.17 --- ServiceController.java 2001/11/30 15:49:35 1.16 +++ ServiceController.java 2001/12/19 06:26:19 1.17 @@ -1,9 +1,9 @@ /* - * JBoss, the OpenSource J2EE webOS - * - * Distributable under LGPL license. - * See terms of license at gnu.org. - */ +* JBoss, the OpenSource J2EE webOS +* +* Distributable under LGPL license. +* See terms of license at gnu.org. +*/ package org.jboss.system; @@ -15,6 +15,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.LinkedList; import java.util.ListIterator; import java.util.Map; import javax.management.InstanceNotFoundException; @@ -31,152 +32,130 @@ import javax.management.RuntimeErrorException; import javax.management.RuntimeMBeanException; import javax.management.RuntimeOperationsException; + import org.w3c.dom.Element; import org.jboss.logging.Logger; /** - * This is the main Service Controller. A controller can deploy a service to a - * JBOSS-SYSTEM It installs by delegating, it configures by delegating - * - * @see org.jboss.system.Service - * @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a> - * @author <a href="mailto:[EMAIL PROTECTED]">David Jencks</a> - * @version $Revision: 1.16 $ <p> - * - * <b>Revisions:</b> <p> - * - * <b>20010830 marcf</b> - * <ol> - * <li>Initial version checked in - * </ol> - * <b>20010908 david jencks</b> - * <ol> - * <li>fixed tabs to spaces and log4j logging. Made it report the number - * of successes on init etc. Modified to support undeploy and work with - * .sar dependency management and recursive sar deployment. - * </ol> - */ +* This is the main Service Controller. A controller can deploy a service to a +* JBOSS-SYSTEM It installs by delegating, it configures by delegating +* +* @see org.jboss.system.Service +* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a> +* @author <a href="mailto:[EMAIL PROTECTED]">David Jencks</a> +* @version $Revision: 1.17 $ <p> +* +* <b>Revisions:</b> <p> +* +* <b>20010830 marcf</b> +* <ol> +* <li>Initial version checked in +* </ol> +* <b>20010908 david jencks</b> +* <ol> +* <li>fixed tabs to spaces and log4j logging. Made it report the number +* of successes on init etc. Modified to support remove and work with +* .sar dependency management and recursive sar deployment. +* </ol> +* <b>2001210 marcf</b> +* <ol> +* <li>Rewrite +* </ol> +*/ public class ServiceController - //extends ServiceMBeanSupport - implements ServiceControllerMBean, MBeanRegistration +//extends ServiceMBeanSupport +implements ServiceControllerMBean, MBeanRegistration { - - private final Logger log = Logger.getLogger(getClass()); - - - /** - * A mapping from the Service interface method names to the corresponding - * index into the ServiceProxy.hasOp array. - */ - private static HashMap serviceOpMap = new HashMap(); - /** - * Map between mbeans and the mbean references they have - */ - private static HashMap mbeanToMBeanRefsMap = new HashMap(); - //inverse map - private static HashMap mbeanRefToMBeansMap = new HashMap(); - - /** - * The set of mbeans that can't find all their mbean references, mapped to - * the mbeans they can't find. - */ - private static HashMap suspendedToMissingMBeanMap = new HashMap(); - - /** - * The map between missing mbeans and what is waiting for them : - * inverse of suspendedToMissingMBeanMap - */ - private static HashMap missingToSuspendedMBeanMap = new HashMap(); - - - /** - * Helper classes to create and configure the classes - */ - protected ServiceCreator creator; - /** - * Description of the Field - */ - protected ServiceConfigurator configurator; - // Attributes ---------------------------------------------------- - + + private final Logger log = Logger.getLogger(getClass()); + /** A callback to the JMX MBeanServer */ MBeanServer server; - - /** The array list keeps the order of deployment. */ - List startedServices = new ArrayList(); - /** The map keeps the list of objectNames to services. */ - Map nameToServiceMap = new HashMap(); - - // Static -------------------------------------------------------- - + /** Creator, helper class to instanciate MBeans **/ + protected ServiceCreator creator; + + /** Configurator, helper class to configure MBeans **/ + protected ServiceConfigurator configurator; + + /** Object Name to Service Proxy map **/ + protected Map nameToServiceMap = new HashMap(); + + /** A linked list of services in the order they were created **/ + protected List installedServices = new LinkedList(); + + // Constructors -------------------------------------------------- - + // Public -------------------------------------------------------- - - public Logger getLog() - { - return log; - } - - /** - * Gets the Name attribute of the ServiceController object - * - * @return The Name value - */ - public String getName() - { - return "Service Controller"; - } - - + + public Logger getLog() { return log;} + + public String getName() { return "Service Controller"; } + + /** - * Gets the Deployed attribute of the ServiceController object - * - * @return The Deployed value - */ + * Gets the Deployed attribute of the ServiceController object + * + * @return The Deployed value + */ public ObjectName[] getDeployed() { - ObjectName[] deployed = new ObjectName[startedServices.size()]; - startedServices.toArray(deployed); - + ObjectName[] deployed = new ObjectName[installedServices.size()]; + + ListIterator iterator = installedServices.listIterator(); + + for (int i = 0; i<installedServices.size() ; i++) + { + + deployed[i] = ((ServiceContext) iterator.next()).objectName; + + } + return deployed; } - + /** - * Gets the Configuration attribute of the ServiceController object - * - * @param objectNames Description of Parameter - * @return The Configuration value - * @exception Exception Description of Exception - */ + * Gets the Configuration attribute of the ServiceController object + * + * @param objectNames Description of Parameter + * @return The Configuration value + * @exception Exception Description of Exception + */ public String getConfiguration(ObjectName[] objectNames) throws Exception { return configurator.getConfiguration(objectNames); } - + /** - * Deploy the beans - * - * @param mbeanElement Description of Parameter - * @return Description of the Returned Value - * @throws Exception ??? - */ - public ObjectName deploy(Element mbeanElement) - throws Exception + * Deploy the beans + * + * Deploy means "instanciate and configure" so the MBean is created in the MBeanServer + * You must call "create" and "start" separately on the MBean to affect the service lifecycle + * deploy doesn't bother with service lifecycle only MBean instanciation/registration/configuration + * + * @param mbeanElement Description of Parameter + * @return Description of the Returned Value + * @throws Exception ??? + */ + public synchronized ObjectName install(Element mbeanElement) + throws Exception { - // The ObjectName of the bean - ObjectName objectName = parseObjectName(mbeanElement); + + // Create a Service Context for the service, or get one if it exists + ServiceContext ctx = getServiceContext(parseObjectName(mbeanElement)); + + // MARCF FIXME THINK ABOUT REMOVe IF ACTIVE HERE //at least make a new version! - //undeploy(objectName); - - // It is not there so really create the component now + //remove(objectName); + + // It is not there so really create the component now, this registers the component in the mbeanserver try { - creator.create(mbeanElement); + creator.install(mbeanElement); } - + catch (MBeanException mbe) { mbe.getTargetException().printStackTrace(); @@ -199,211 +178,330 @@ // catch (Throwable e) { - log.error("Could not create MBean: " + objectName, e); + log.error("Could not create MBean: " + ctx.objectName, e); if (e instanceof Exception) throw (Exception)e; if (e instanceof Error) throw (Error)e; + throw new Error("unexpected throwable: " + e); } - // Configure the MBean - boolean waiting = false; - try - { - ArrayList mBeanRefs = configurator.configure(mbeanElement); - if (mBeanRefs.size() > 0) - { - synchronized (this) - { - mbeanToMBeanRefsMap.put(objectName, mBeanRefs); - //ArrayList waitingFor = new ArrayList(); - Iterator refs = mBeanRefs.iterator(); - while (refs.hasNext()) - { - //First, record dependencies - ObjectName ref = (ObjectName)refs.next(); - ArrayList backRefs = (ArrayList)mbeanRefToMBeansMap.get(ref); - if (backRefs == null) - { - backRefs = new ArrayList(); - mbeanRefToMBeansMap.put(ref, backRefs); - } // end of if () - if (!backRefs.contains(objectName)) - { - backRefs.add(objectName); - } // end of if () - //Now, does the needed mbean exist? if not, note suspension. - //We could use the mbean server or our own service map. - if (!startedServices.contains(ref)) - { - //Not there, mark suspended. - markWaiting(ref, objectName); - } // end of if () - } // end of while () - } + // We got this far + ctx.state = ServiceContext.INSTALLED; + + try { - } // end of if (mBeanRefs.size() > 0) + // Configure the MBean + synchronized (this) + { + + // The return is a list of MBeans this MBean "depends" on + List mbeans = configurator.configure(mbeanElement); + + // Link the dependency me.idependOn(them) and them.dependsOnMe(me) + Iterator iterator = mbeans.iterator(); + while (iterator.hasNext()) { + + // We work from the service context, if it doesn't exist yet, we have a wrapper (OK) + ServiceContext service = getServiceContext((ObjectName) iterator.next()); + + // ctx depends on service + ctx.iDependOn.add(service); + + // Service needs to know I depend on him + service.dependsOnMe.add(ctx); + } + } } catch (Exception e) { - log.error("Could not configure MBean: " + objectName, e); - server.unregisterMBean(objectName); + log.error("Could not configure MBean: " + ctx.objectName, e); + + server.unregisterMBean(ctx.objectName); + + ctx.state = ServiceContext.FAILED ; throw e; + } - String serviceFactory = mbeanElement.getAttribute("serviceFactory"); - try - { - registerAndStartService(objectName, serviceFactory); - } - catch (Exception e) - //ignore errors, we created the mbean so we have to return the name - {} // end of try-catch - return objectName; + // We got this far + ctx.state = ServiceContext.CONFIGURED; + + if ( !installedServices.contains(ctx)) installedServices.add(ctx); + + return ctx.objectName; } - - //needs to be an mbean method, for e.g. RARDeployer to register RAR's for dependency. - //puts a mbean that you created some other way (such as deployed rar) - //into dependency system so other beans can be started/stopped on its - //existence (or registration) - public void registerAndStartService(ObjectName serviceName, String serviceFactory) throws Exception - { - try - { - Service service = getServiceInstance(serviceName, serviceFactory); - // Keep track - nameToServiceMap.put(serviceName, service); - - start(serviceName); - //You are done + + /** + * #Description of the Method + * + * @param serviceName Description of Parameter + * @exception Exception Description of Exception + */ + public synchronized void create(ObjectName serviceName) throws Exception + { + + ServiceContext ctx = (ServiceContext) getServiceContext(serviceName); + + + // Get the fancy service proxy (for the lifecycle API) + ctx.proxy = getServiceProxy(ctx.objectName, null); + + // If we are already created (can happen in dependencies) just return + if (ctx.state == ServiceContext.CREATED || ctx.state == ServiceContext.RUNNING) return; + + // JSR 77, and to avoid circular dependencies + int oldState = ctx.state; + ctx.state= ServiceContext.CREATED; + + // Are all the mbeans I depend on created? if not just return + Iterator iterator = ctx.iDependOn.iterator(); + while (iterator.hasNext()) + { + ServiceContext sc = (ServiceContext) iterator.next(); + + int state = sc.state; + + // A dependent is not created or running + if (!(state == ServiceContext.CREATED || state == ServiceContext.RUNNING)) { + + + log.info("&&&&&&&&&&&&&&&&&&&&&&&& waiting in create "+serviceName.toString() +" waiting on "+sc.objectName); + ctx.state=oldState; + return; + } } - catch (Exception e) + + // Call create on the service Proxy + try { ctx.proxy.create(); } + + catch (Exception e){ ctx.state = ServiceContext.FAILED; throw e;} + + // Those that depend on me are waiting for my creation, recursively create them + Iterator iterator2 = ctx.dependsOnMe.iterator(); + while (iterator2.hasNext()) { - log.error("Problem in registerAndStartService", e); - throw e; - } // end of try-catch - + // marcf fixme circular dependencies? + create(((ServiceContext) iterator2.next()).objectName); + } } + + + /** - * #Description of the Method - * - * @param mbeanElement Description of Parameter - * @exception Exception Description of Exception - */ - public void undeploy(Element mbeanElement) throws Exception + * #Description of the Method + * + * @param serviceName Description of Parameter + * @exception Exception Description of Exception + */ + public synchronized void start(ObjectName serviceName) throws Exception { - - undeploy(parseObjectName(mbeanElement)); + + ServiceContext ctx = (ServiceContext) getServiceContext(serviceName); + + // If we are already started (can happen in dependencies) just return + if (ctx.state == ServiceContext.RUNNING) return; + + // JSR 77, and to avoid circular dependencies + int oldState = ctx.state; + ctx.state= ServiceContext.RUNNING; + + // Are all the mbeans I depend on created? if not just return + Iterator iterator = ctx.iDependOn.iterator(); + while (iterator.hasNext()) + { + ServiceContext sctx = (ServiceContext) iterator.next(); + + int state = sctx.state; + + // A dependent is not running + if (!(state == ServiceContext.RUNNING)) + { + ObjectName cac = new ObjectName("Test:name=test"); + ObjectName ca2 = new ObjectName("Test:name=test"); + + log.info("%%%%%%%%%%%%%%%%%% waiting in start"+serviceName.toString()+" on "+sctx.objectName); + + ctx.state=oldState; + return; + } + } + + // Call create on the service Proxy + try { ctx.proxy.start(); } + + catch (Exception e){ ctx.state = ServiceContext.FAILED; throw e;} + + // JSR 77 + ctx.state = ServiceContext.RUNNING; + + installedServices.add(ctx.objectName); + + // Those that depend on me are waiting for my creation, recursively create them + Iterator iterator2 = ctx.dependsOnMe.iterator(); + while (iterator2.hasNext()) + { + // marcf fixme circular dependencies? + start(((ServiceContext) iterator2.next()).objectName); + } } - - + /** - * #Description of the Method - * - * @param objectName Description of Parameter - * @exception Exception Description of Exception - */ - public void undeploy(ObjectName objectName) throws Exception - { - try - { - stop(objectName); - } - catch (Exception e) - { } // end of try-catch - //We are not needing anyone or waiting for anyone - ArrayList weNeededList = (ArrayList)mbeanToMBeanRefsMap.remove(objectName); - if (weNeededList != null) - { - //remove the back reference for each mbean we needed. - Iterator needed = weNeededList.iterator(); - while (needed.hasNext()) + * #Description of the Method + * + * @param serviceName Description of Parameter + * @exception Exception Description of Exception + */ + public void stop(ObjectName serviceName) throws Exception + { + + ServiceContext ctx = (ServiceContext) nameToServiceMap.get(serviceName); + + if (ctx != null) + { + // If we are already stopped (can happen in dependencies) just return + if (ctx.state == ServiceContext.STOPPED) return; + + // JSR 77 and to avoid circular dependencies + ctx.state = ServiceContext.STOPPED; + + Iterator iterator = ctx.dependsOnMe.iterator(); + while (iterator.hasNext()) { - ObjectName neededName = (ObjectName)needed.next(); - ArrayList needingList = (ArrayList)mbeanRefToMBeansMap.get(neededName); - if (needingList != null) - { - needingList.remove(objectName); - } // end of if () - } // end of while () + // stop all the mbeans that depend on me + stop(((ServiceContext) iterator.next()).objectName); + } - } // end of if () + // Call create on the service Proxy + try { ctx.proxy.stop(); } + + catch (Exception e){ ctx.state = ServiceContext.FAILED; throw e;} + + + + } + + } + + /** + * #Description of the Method + * + * @param serviceName Description of Parameter + * @exception Exception Description of Exception + */ + public void destroy(ObjectName serviceName) throws Exception + { + + ServiceContext ctx = (ServiceContext) nameToServiceMap.get(serviceName); - ArrayList weSuspendedForList = (ArrayList)suspendedToMissingMBeanMap.remove(objectName); - if (weSuspendedForList != null) + if (ctx != null) { - //remove the back reference for each mbean we suspended for. - Iterator suspendedFor = weSuspendedForList.iterator(); - while (suspendedFor.hasNext()) + // If we are already destroyed (can happen in dependencies) just return + if (ctx.state == ServiceContext.DESTROYED) return; + + // JSR 77, and to avoid circular dependencies + ctx.state = ServiceContext.DESTROYED; + + Iterator iterator = ctx.dependsOnMe.iterator(); + while (iterator.hasNext()) { - ObjectName suspendedForName = (ObjectName)suspendedFor.next(); - ArrayList suspendedOnList = (ArrayList)missingToSuspendedMBeanMap.get(suspendedForName); - if (suspendedOnList != null) - { - suspendedOnList.remove(objectName); - } // end of if () - } // end of while () + // destroy all the mbeans that depend on me + destroy(((ServiceContext) iterator.next()).objectName); + } - } // end of if () + // Call create on the service Proxy + try { ctx.proxy.destroy(); } + + catch (Exception e){ ctx.state = ServiceContext.FAILED; throw e;} + + + } + } + + + + /** + * #Description of the Method + * + * @param mbeanElement Description of Parameter + * @exception Exception Description of Exception + */ + public void remove(Element mbeanElement) throws Exception + { + + remove(parseObjectName(mbeanElement)); + } + + + /** + * This MBean is going buh bye + * + * @param objectName Description of Parameter + * @exception Exception Description of Exception + */ + public void remove(ObjectName objectName) throws Exception + { + ServiceContext ctx = getServiceContext(objectName); + // Notify those that think I depend on them + Iterator iterator = ctx.iDependOn.iterator(); + while (iterator.hasNext()) + { + ((ServiceContext) iterator.next()).dependsOnMe.remove(ctx); + } + // Do we have a deployed MBean? if (server.isRegistered(objectName)) { if (log.isDebugEnabled()) { - log.debug("undeploying " + objectName + " from server"); + log.debug("removing " + objectName + " from server"); } - //Remove from local maps - startedServices.remove(objectName); - //Service service = (Service)nameToServiceMap.remove(objectName); nameToServiceMap.remove(objectName); - // Remove the MBean from the MBeanServer - server.unregisterMBean(objectName); - - // Remove the MBeanClassLoader used by the MBean - ObjectName loader = - new ObjectName("ZClassLoaders:id=" + objectName.hashCode()); - if (server.isRegistered(loader)) - { - server.unregisterMBean(loader); - } // end of if () + + // remove the mbean from the instaled ones + installedServices.remove(ctx); + + creator.remove(objectName); } else { if (log.isDebugEnabled()) { - log.debug("no need to undeploy " + objectName + " from server"); + log.debug("no need to remove " + objectName + " from server"); } - - } // end of else + } // end of else + } - + // MBeanRegistration implementation ---------------------------------------- - + /** - * #Description of the Method - * - * @param server Description of Parameter - * @param name Description of Parameter - * @return Description of the Returned Value - * @exception Exception Description of Exception - */ + * #Description of the Method + * + * @param server Description of Parameter + * @param name Description of Parameter + * @return Description of the Returned Value + * @exception Exception Description of Exception + */ public ObjectName preRegister(MBeanServer server, ObjectName name) - throws Exception + throws Exception { this.server = server; - + creator = new ServiceCreator(server); configurator = new ServiceConfigurator(server); - + log.info("Controller MBean online"); return name == null ? new ObjectName(OBJECT_NAME) : name; + + } - + public void postRegister(Boolean registrationDone) { if (!registrationDone.booleanValue()) @@ -413,176 +511,66 @@ } public void preDeregister() - throws Exception + throws Exception { } public void postDeregister() { - } - - // methods about suspension. - - public synchronized boolean isSuspended(ObjectName objectName) - { - return suspendedToMissingMBeanMap.containsKey(objectName); } - + + // Service implementation ---------------------------------------- - - + + /** - * This is the only one we should have of these lifecycle methods! - */ + * This is the only one we should have of these lifecycle methods! + */ public synchronized void shutdown() { - log.info("Stopping " + startedServices.size() + " services"); - - List servicesCopy = new ArrayList(startedServices); - //ListIterator enum = servicesCopy.listIterator(); + log.info("Stopping " + nameToServiceMap.size() + " services"); + + + List servicesCopy = new ArrayList(installedServices); + int serviceCounter = 0; ObjectName name = null; - + for (ListIterator i = servicesCopy.listIterator(servicesCopy.size() - 1); - i.hasPrevious(); ) + i.hasPrevious(); ) { - name = (ObjectName)i.previous(); - + name = ((ServiceContext)i.previous()).objectName; + try { - undeploy(name); - //((Service)nameToServiceMap.get(name)).stop(); - //((Service)nameToServiceMap.get(name)).destroy();//should be obsolete soon - //server.unregisterMBean(name); + remove(name); serviceCounter++; } catch (Throwable e) { - log.error("Could not undeploy " + name, e); + log.error("Could not remove " + name, e); } } log.info("Stopped " + serviceCounter + " services"); - } - - - - - /** - * #Description of the Method - * - * @param serviceName Description of Parameter - * @exception Exception Description of Exception - */ - public void start(ObjectName serviceName) throws Exception - { - if (suspendedToMissingMBeanMap.containsKey(serviceName)) - { - log.debug("waiting to start " + serviceName + " until dependencies are resolved"); - return; - } // end of if () - - if (nameToServiceMap.containsKey(serviceName)) - { - - ((Service)nameToServiceMap.get(serviceName)).start(); - startedServices.add(serviceName); - } - else - { - throw new InstanceNotFoundException - ("Could not find " + serviceName.toString()); - } - ArrayList waitingList = (ArrayList)missingToSuspendedMBeanMap.remove(serviceName); - if (waitingList != null) - { - Iterator waiting = waitingList.iterator(); - while (waiting.hasNext()) - { - ObjectName waitingName = (ObjectName)waiting.next(); - //Is it waiting for anyone else? - ArrayList waitingFor = (ArrayList)suspendedToMissingMBeanMap.get(waitingName); - if (waitingFor == null) - { - //maybe should be DeploymentException, but it might pull in too many classes. - throw new Exception("Missing suspended to Missing map entry between suspended: " + waitingName + " and missing: " + serviceName); - } // end of if () - waitingFor.remove(serviceName); - if (waitingFor.size() == 0) - { - //not waiting for anyone else, can finish deploying. - log.debug("missing mbeans now present, finishing deployment of " + waitingName); - suspendedToMissingMBeanMap.remove(waitingName); - start(waitingName); - } // end of if () - else - { - log.debug("There are still missing mbeans, deployment of " + waitingName + " postponed"); - - } // end of else - - } // end of while () - - - } // end of if () - - } - - /** - * #Description of the Method - * - * @param serviceName Description of Parameter - * @exception Exception Description of Exception - */ - public void stop(ObjectName serviceName) throws Exception - { - ArrayList usingList = (ArrayList)mbeanRefToMBeansMap.get(serviceName); - if (usingList != null) - { - //we have to stop these beans that depend on serviceName. - Iterator using = usingList.iterator(); - while (using.hasNext()) - { - ObjectName usingName = (ObjectName)using.next(); - log.debug("stopping object " + usingName + " using " + serviceName); - if (!isWaitingFor(serviceName, usingName)) - { - markWaiting(serviceName, usingName); - stop(usingName); - } // end of if () - - } // end of while () - - } // end of if () - - if (nameToServiceMap.containsKey(serviceName)) - { - - ((Service)nameToServiceMap.get(serviceName)).stop(); - } - else - { - throw new InstanceNotFoundException - ("Could not find " + serviceName.toString()); - } } - - + + /** - * Get the Service interface through which the mbean given by objectName - * will be managed. - * - * @param objectName - * @param info - * @param serviceFactory - * @return The ServiceInstance value - * - * @throws ClassNotFoundException - * @throws InstantiationException - * @throws IllegalAccessException - */ - private Service getServiceInstance(ObjectName objectName, - String serviceFactory) - throws ClassNotFoundException, InstantiationException, IllegalAccessException, JMException//, InstanceNotFoundException, IntrospectionException + * Get the Service interface through which the mbean given by objectName + * will be managed. + * + * @param objectName + * @param info + * @param serviceFactory + * @return The ServiceInstance value + * + * @throws ClassNotFoundException + * @throws InstantiationException + * @throws IllegalAccessException + */ + private Service getServiceProxy(ObjectName objectName, + String serviceFactory) + throws ClassNotFoundException, InstantiationException, IllegalAccessException, JMException//, InstanceNotFoundException, IntrospectionException { Service service = null; ClassLoader loader = Thread.currentThread().getContextClassLoader(); @@ -600,40 +588,38 @@ InvocationHandler handler = new ServiceProxy(objectName, opInfo); service = (Service)Proxy.newProxyInstance(loader, interfaces, handler); } - + return service; } - - // Protected ----------------------------------------------------- - + /** - * Parse an object name from the given element attribute 'name'. - * - * @param element Element to parse name from. - * @return Object name. - * - * @throws ConfigurationException Missing attribute 'name' (thrown if - * 'name' is null or ""). - * @throws MalformedObjectNameException - */ + * Parse an object name from the given element attribute 'name'. + * + * @param element Element to parse name from. + * @return Object name. + * + * @throws ConfigurationException Missing attribute 'name' (thrown if + * 'name' is null or ""). + * @throws MalformedObjectNameException + */ private ObjectName parseObjectName(final Element element) - throws ConfigurationException, MalformedObjectNameException + throws ConfigurationException, MalformedObjectNameException { String name = element.getAttribute("name"); if (name == null || name.trim().equals("")) { throw new ConfigurationException - ("MBean attribute 'name' must be given."); + ("MBean attribute 'name' must be given."); } return new ObjectName(name); } - + /** - * Go through the myriad of nested JMX exception to pull out the true - * exception if possible and log it. - * - * @param e The exception to be logged. - */ + * Go through the myriad of nested JMX exception to pull out the true + * exception if possible and log it. + * + * @param e The exception to be logged. + */ private void logException(String message, Throwable e) { if (e instanceof RuntimeErrorException) @@ -658,72 +644,61 @@ } log.error(message, e); } - - private void markWaiting(ObjectName missing, ObjectName waiting) - { - ArrayList waitingList = (ArrayList)missingToSuspendedMBeanMap.get(missing); - if (waitingList == null) - { - waitingList = new ArrayList(); - missingToSuspendedMBeanMap.put(missing, waitingList); - } // end of if () - if (!waitingList.contains(waiting)) - { - waitingList.add(waiting); - } // end of if () - //Now do the other way. - ArrayList missingList = (ArrayList)suspendedToMissingMBeanMap.get(waiting); - if (missingList == null) - { - missingList = new ArrayList(); - suspendedToMissingMBeanMap.put(waiting, missingList); - } // end of if () - if (!missingList.contains(missing)) - { - missingList.add(missing); - } // end of if () - } - - private boolean isWaitingFor(ObjectName serviceName, ObjectName usingName) + + // Inner classes ------------------------------------------------- + + // Create a Service Context for the service, or get one if it exists + public synchronized ServiceContext getServiceContext(ObjectName objectName) { - ArrayList waitingList = (ArrayList)missingToSuspendedMBeanMap.get(serviceName); - if (waitingList == null) - { - return false;//noone is waiting for this guy. - } // end of if () - return waitingList.contains(usingName); + // If it is already there just return it + if (nameToServiceMap.containsKey(objectName)) return (ServiceContext) nameToServiceMap.get(objectName); + + // If not create it, add it and return it + ServiceContext ctx = new ServiceContext(); + ctx.objectName = objectName; + + // we keep track of these here + nameToServiceMap.put(objectName, ctx); + + return ctx; } - - // Inner classes ------------------------------------------------- - + + + /** - * An implementation of InvocationHandler used to proxy of the Service - * interface for mbeans. It determines which of the start/stop - * methods of the Service interface an mbean implements by inspecting its - * MBeanOperationInfo values. Each Service interface method that has a - * matching operation is forwarded to the mbean by invoking the method - * through the MBeanServer object. - */ - private class ServiceProxy - implements InvocationHandler + * A mapping from the Service interface method names to the corresponding + * index into the ServiceProxy.hasOp array. + */ + private static HashMap serviceOpMap = new HashMap(); + + /** + * An implementation of InvocationHandler used to proxy of the Service + * interface for mbeans. It determines which of the start/stop + * methods of the Service interface an mbean implements by inspecting its + * MBeanOperationInfo values. Each Service interface method that has a + * matching operation is forwarded to the mbean by invoking the method + * through the MBeanServer object. + */ + public class ServiceProxy + implements InvocationHandler { private boolean[] hasOp = { false, false, false, false }; private ObjectName objectName; - + /** - * Go through the opInfo array and for each operation that matches on of - * the Service interface methods set the corresponding hasOp array value - * to true. - * - * @param objectName - * @param opInfo - */ + * Go through the opInfo array and for each operation that matches on of + * the Service interface methods set the corresponding hasOp array value + * to true. + * + * @param objectName + * @param opInfo + */ public ServiceProxy(ObjectName objectName, - MBeanOperationInfo[] opInfo) + MBeanOperationInfo[] opInfo) { this.objectName = objectName; int opCount = 0; - + for (int op = 0; op < opInfo.length; op++) { MBeanOperationInfo info = opInfo[op]; @@ -733,7 +708,7 @@ { continue; } - + // Validate that is a no-arg void return type method if (info.getReturnType().equals("void") == false) { @@ -743,37 +718,37 @@ { continue; } - + hasOp[opID.intValue()] = true; opCount++; } - + // Log a warning if the mbean does not implement // any Service methods if (opCount == 0) { log.warn(objectName + - " does not implement any Service methods"); + " does not implement any Service methods"); } } - + /** - * Map the method name to a Service interface method index and if the - * corresponding hasOp array element is true, dispatch the method to the - * mbean we are proxying. - * - * @param proxy - * @param method - * @param args - * @return Always null. - * @throws Throwable - */ + * Map the method name to a Service interface method index and if the + * corresponding hasOp array element is true, dispatch the method to the + * mbean we are proxying. + * + * @param proxy + * @param method + * @param args + * @return Always null. + * @throws Throwable + */ public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable + throws Throwable { String name = method.getName(); Integer opID = (Integer)serviceOpMap.get(name); - + if (opID != null && hasOp[opID.intValue()] == true) { try @@ -784,29 +759,30 @@ catch (JMRuntimeException e) { logException("JMRuntimeException thrown during ServiceProxy operation " + - name + " on mbean " + objectName, e); + name + " on mbean " + objectName, e); throw e; } catch (JMException e) { logException("JMException thrown during ServiceProxy operation " + - name + " on mbean " + objectName, e); + name + " on mbean " + objectName, e); throw e; } } - + return null; } } - + /** - * Initialize the service operation map. - */ + * Initialize the service operation map. + */ static { - //serviceOpMap.put("init", new Integer(0)); + serviceOpMap.put("create", new Integer(0)); serviceOpMap.put("start", new Integer(1)); - //serviceOpMap.put("destroy", new Integer(2)); + + serviceOpMap.put("destroy", new Integer(2)); serviceOpMap.put("stop", new Integer(3)); } }
_______________________________________________ Jboss-development mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/jboss-development