You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by da...@apache.org on 2003/09/05 04:38:32 UTC

cvs commit: incubator-geronimo/modules/core/src/java/org/apache/geronimo/jmx GeronimoAttributeInfo.java GeronimoMBean.java GeronimoMBeanContext.java GeronimoMBeanInfo.java GeronimoMBeanInfoXMLLoader.java GeronimoMBeanTarget.java GeronimoNotificationInfo.java GeronimoOperationInfo.java GeronimoParameterInfo.java

dain        2003/09/04 19:38:32

  Added:       modules/core/src/java/org/apache/geronimo/jmx
                        GeronimoAttributeInfo.java GeronimoMBean.java
                        GeronimoMBeanContext.java GeronimoMBeanInfo.java
                        GeronimoMBeanInfoXMLLoader.java
                        GeronimoMBeanTarget.java
                        GeronimoNotificationInfo.java
                        GeronimoOperationInfo.java
                        GeronimoParameterInfo.java
  Log:
  Initial revision.
  
  Revision  Changes    Path
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/jmx/GeronimoAttributeInfo.java
  
  Index: GeronimoAttributeInfo.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.jmx;
  
  import java.lang.reflect.Method;
  import javax.management.MBeanAttributeInfo;
  
  import net.sf.cglib.MethodProxy;
  
  /**
   * Describes an attibute of a GeronimoMBean.  This extension allows the properties to be mutable during setup,
   * and once the MBean is deployed an imutable copy of will be made.  This class also adds support for to
   * direct the attibute to a specific target in a multi target GeronimoMBean.  It also supports caching of the
   * attribute value, which can reduce the number of calls on the target.
   *
   * @version $Revision: 1.1 $ $Date: 2003/09/05 02:38:32 $
   */
  public class GeronimoAttributeInfo extends MBeanAttributeInfo {
      /**
       * Is this class still mutable from users.
       */
      private final boolean immutable;
  
      /**
       * Name of this attribute.
       */
      private String name;
  
      /**
       * Type of this attribute.
       */
      private final String type;
  
      /**
       * A user displayable descrption of this attribute.
       */
      private String description;
  
      /**
       * Is this attribute readable?
       */
      private boolean readable = true;
  
      /**
       * Is this attribute writiable?
       */
      private boolean writable = true;
  
      /**
       * Is the getter method an is method?
       * This variable is completely useless but required by the spec, so we do our best to honor it.
       */
      private boolean is;
  
      /**
       * Logical name of the target.
       */
      private String targetName;
  
      /**
       * Name of the getter method.
       * The default is "get" + name.  In the case of a defualt value we do a caseless search for the name.
       */
      private String getterName;
  
      /**
       * Name of the setter method.
       * The default is "set" + name.  In the case of a defualt value we do a caseless search for the name.
       */
      private String setterName;
  
      /**
       * The maximum ammount ot time in seconds that a cached value is valid.
       */
      long cacheTimeLimit;
  
      //
      // Runtime information -- this is not exposed to clients
      //
  
      /**
       * The cached value of the attribute.
       */
      Object value;
  
      /**
       * The object on which the getter and setter will be invoked
       */
      Object target;
  
      /**
       * The method that will be called to get the attribute value.  If null, the cached value will
       * be returned.
       */
      final MethodProxy getterProxy;
  
      /**
       * The method that will be called to set the attribute value.  If null, the value will only be
       * set into the cache.
       */
      final MethodProxy setterProxy;
  
      /**
       * Time stamp from when the value field was last updated.
       */
      long lastUpdate;
      private final int hashCode = System.identityHashCode(this);
  
      /**
       * Creates an empty mutable GeronimoAttributeInfo.
       */
      public GeronimoAttributeInfo() {
          super(null, null, null, true, true, false);
          immutable = false;
          getterProxy = null;
          setterProxy = null;
          type = null;
      }
  
      /**
       * Creates an immutable copy of the source GeronimoAttributeInfo.
       * @param source the source GeronimoAttributeInfo to copy
       * @param parent the GeronimoMBeanInfo that will contain this attribute
       */
      GeronimoAttributeInfo(GeronimoAttributeInfo source, GeronimoMBeanInfo parent) {
          super(null, null, null, true, true, false);
          immutable = true;
  
          //
          // Required
          //
          if (source.name == null) {
              throw new IllegalArgumentException("Attribute name is null");
          }
          name = source.name;
          readable = source.readable;
          writable = source.writable;
  
          if (!readable && !writable) {
              throw new IllegalArgumentException("Attribute is neither readable or writable: name=" + name);
          }
  
          //
          // Optional
          //
          description = source.description;
          cacheTimeLimit = source.cacheTimeLimit;
  
          //
          // Optional (derived)
          //
          if (source.target != null) {
              target = source.target;
              targetName = source.targetName;
          } else if (source.targetName == null) {
              target = parent.getTarget();
          } else {
              targetName = source.targetName;
              target = parent.getTarget(targetName);
              if (target == null) {
                  throw new IllegalArgumentException("Target not found: targetName=" + targetName);
              }
          }
  
          Method[] methods = target.getClass().getMethods();
          Class attributeType = null;
          if (readable) {
              Method getterMethod = null;
              if (source.getterName == null) {
                  String getterName = "get" + name;
                  String isName = "is" + name;
                  for (int i = 0; i < methods.length; i++) {
                      Method method = methods[i];
                      if (method.getParameterTypes().length == 0 &&
                              (getterName.equalsIgnoreCase(method.getName()) ||
                              isName.equalsIgnoreCase(method.getName()))) {
                          getterMethod = method;
                          break;
                      }
                  }
              } else {
                  try {
                      String methodName = source.getterName;
                      getterMethod = target.getClass().getMethod(methodName, null);
                  } catch (Exception e) {
                      // we will throw the formatted exception below
                  }
              }
  
              if (getterMethod == null) {
                  throw new IllegalArgumentException("Getter method not found on target:" +
                          " name=" + name +
                          " targetClass=" + target.getClass().getName());
              }
  
              getterName = getterMethod.getName();
              is = getterName.startsWith("is");
              getterProxy = MethodProxy.create(getterMethod, getterMethod);
              attributeType = getterMethod.getReturnType();
          } else {
              getterName = null;
              readable = false;
              getterProxy = null;
          }
  
          if (writable) {
              Method setterMethod = null;
              String methodName = null;
              if (source.setterName == null) {
                  methodName = "set" + name;
                  for (int i = 0; i < methods.length; i++) {
                      Method method = methods[i];
                      if (method.getParameterTypes().length == 1 && methodName.equalsIgnoreCase(method.getName())) {
                          setterMethod = method;
                          break;
                      }
                  }
              } else {
                  // even though we have an exact name we need to search the methods becaus we don't know the parameter type
                  methodName = source.setterName;
                  for (int i = 0; i < methods.length; i++) {
                      Method method = methods[i];
                      if (method.getParameterTypes().length == 1 && methodName.equals(method.getName())) {
                          setterMethod = method;
                          break;
                      }
                  }
              }
  
              if (setterMethod == null) {
                  throw new IllegalArgumentException("Setter method not found on target:" +
                          " setterName=" + methodName +
                          " targetClass=" + source.target.getClass().getName());
              }
  
              setterName = setterMethod.getName();
              setterProxy = MethodProxy.create(setterMethod, setterMethod);
              attributeType = setterMethod.getParameterTypes()[0];
          } else {
              setterName = null;
              setterProxy = null;
          }
          type = attributeType.getName();
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.name = name;
      }
  
      public String getDescription() {
          return description;
      }
  
      public void setDescription(String description) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.description = description;
      }
  
      public boolean isReadable() {
          return readable;
      }
  
      public void setReadable(boolean readable) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.readable = readable;
      }
  
      public boolean isWritable() {
          return writable;
      }
  
      public void setWritable(boolean writable) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.writable = writable;
      }
  
      public String getTargetName() {
          return targetName;
      }
  
      public void setTargetName(String targetName) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.targetName = targetName;
      }
  
      public String getGetterName() {
          return getterName;
      }
  
      public void setGetterName(String getterName) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.getterName = getterName;
      }
  
      public String getSetterName() {
          return setterName;
      }
  
      public void setSetterName(String setterName) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.setterName = setterName;
          is = (setterName != null && setterName.startsWith("is"));
      }
  
      public String getType() {
          return type;
      }
  
      public boolean isIs() {
          return is;
      }
  
      public long getCacheTimeLimit() {
          return cacheTimeLimit;
      }
  
      public void setCacheTimeLimit(long cacheTimeLimit) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.cacheTimeLimit = cacheTimeLimit;
      }
  
      public String getCachePolicy() {
          if (cacheTimeLimit < 0) {
              return GeronimoMBeanInfo.NEVER;
          } else if (cacheTimeLimit == 0) {
              return GeronimoMBeanInfo.ALWAYS;
          } else {
              return "" + cacheTimeLimit;
          }
  
      }
  
      public void setCachePolicy(String cacheTimeLimit) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          if (cacheTimeLimit == null || cacheTimeLimit.length() == 0) {
              throw new IllegalArgumentException("cacheTimeLimit is null");
          }
          if (GeronimoMBeanInfo.ALWAYS.equalsIgnoreCase(cacheTimeLimit)) {
              this.cacheTimeLimit = 0;
          } else if (GeronimoMBeanInfo.NEVER.equalsIgnoreCase(cacheTimeLimit)) {
              this.cacheTimeLimit = -1;
          } else {
              this.cacheTimeLimit = Long.parseLong(cacheTimeLimit);
          }
      }
  
      public int hashCode() {
          return hashCode;
      }
  
      public boolean equals(Object object) {
          return (this == object);
      }
  
      public String toString() {
          return "[GeronimoAttributeInfo: name=" + name + " description=" + description + "]";
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/jmx/GeronimoMBean.java
  
  Index: GeronimoMBean.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.jmx;
  
  import java.lang.reflect.InvocationTargetException;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Set;
  import javax.management.Attribute;
  import javax.management.AttributeList;
  import javax.management.AttributeNotFoundException;
  import javax.management.DynamicMBean;
  import javax.management.InstanceNotFoundException;
  import javax.management.InvalidAttributeValueException;
  import javax.management.JMException;
  import javax.management.MBeanException;
  import javax.management.MBeanInfo;
  import javax.management.MBeanNotificationInfo;
  import javax.management.MBeanOperationInfo;
  import javax.management.MBeanServer;
  import javax.management.ObjectName;
  import javax.management.ReflectionException;
  import javax.management.RuntimeOperationsException;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.geronimo.deployment.DeploymentException;
  import org.apache.geronimo.management.AbstractManagedObject;
  import org.apache.geronimo.management.NotificationType;
  
  /**
   * A GeronimoMBean is a J2EE Management Managed Object, and is standard base for Geronimo services.
   * This wraps one or more target POJOs and exposes the attributes and opperation according to a supplied
   * GeronimoMBeanInfo instance.  The GeronimoMBean also support caching of attribute values and invocation results
   * which can reduce the number of calls to a target.
   *
   * @version $Revision: 1.1 $ $Date: 2003/09/05 02:38:32 $
   */
  public class GeronimoMBean extends AbstractManagedObject implements DynamicMBean {
      private final Log log = LogFactory.getLog(getClass());
      private final Map attributeInfoMap = new HashMap();
      private final Map operationInfoMap = new HashMap();
      private GeronimoMBeanContext context;
      private GeronimoMBeanInfo mbeanInfo;
      private ClassLoader classLoader;
  
      public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
          super.preRegister(server, name);
          if (classLoader == null) {
              throw new DeploymentException("No class loader set for Geronimo MBean");
          }
          if (mbeanInfo == null) {
              throw new DeploymentException("No MBean info set for Geronimo MBean");
          }
  
          ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
          try {
              Thread.currentThread().setContextClassLoader(classLoader);
  
              addManagedObjectMBeanInfo();
              mbeanInfo = new GeronimoMBeanInfo(mbeanInfo);
              Set attributes = mbeanInfo.getAttributeSet();
              for (Iterator iterator = attributes.iterator(); iterator.hasNext();) {
                  GeronimoAttributeInfo attributeInfo = (GeronimoAttributeInfo) iterator.next();
                  attributeInfoMap.put(attributeInfo.getName(), attributeInfo);
              }
              Set operations = mbeanInfo.getOperationsSet();
              for (Iterator iterator = operations.iterator(); iterator.hasNext();) {
                  GeronimoOperationInfo operationInfo = (GeronimoOperationInfo) iterator.next();
                  operationInfoMap.put(new MethodKey(operationInfo.getName(), operationInfo.getParameterTypes()), operationInfo);
              }
  
              context = new GeronimoMBeanContext(server, this, name);
              for (Iterator i = mbeanInfo.targets.values().iterator(); i.hasNext();) {
                  Object target = i.next();
                  if (target instanceof GeronimoMBeanTarget) {
                      ((GeronimoMBeanTarget) target).setMBeanContext(context);
                  }
              }
          } finally {
              Thread.currentThread().setContextClassLoader(oldClassLoader);
          }
          return this.objectName;
      }
  
      public void postDeregister() {
          super.postDeregister();
          for (Iterator i = mbeanInfo.targets.values().iterator(); i.hasNext();) {
              Object target = i.next();
              if (target instanceof GeronimoMBeanTarget) {
                  ((GeronimoMBeanTarget) target).setMBeanContext(null);
              }
          }
      }
  
      public ClassLoader getClassLoader() {
          return classLoader;
      }
  
      public void setClassLoader(ClassLoader classLoader) {
          this.classLoader = classLoader;
      }
  
      public MBeanInfo getMBeanInfo() {
          return mbeanInfo;
      }
  
      public void setMBeanInfo(GeronimoMBeanInfo mbeanInfo) throws MBeanException, RuntimeOperationsException {
          if (mbeanInfo == null) {
              throw new RuntimeOperationsException(new IllegalArgumentException("MBean info cannot be null"));
          }
          if (server != null) {
              throw new RuntimeOperationsException(new IllegalStateException("MBean info cannot changed while registered with the MBean server"));
          }
  
          this.mbeanInfo = mbeanInfo;
      }
  
      protected boolean canStart() {
          for (Iterator i = mbeanInfo.targets.values().iterator(); i.hasNext();) {
              Object target = i.next();
              if (target instanceof GeronimoMBeanTarget) {
                  if (!((GeronimoMBeanTarget) target).canStart()) {
                      return false;
                  }
              }
          }
          return true;
      }
  
      protected void doStart() throws Exception {
          for (Iterator i = mbeanInfo.targets.values().iterator(); i.hasNext();) {
              Object target = i.next();
              if (target instanceof GeronimoMBeanTarget) {
                  ((GeronimoMBeanTarget) target).doStart();
              }
          }
      }
  
      protected boolean canStop() {
          for (Iterator i = mbeanInfo.targets.values().iterator(); i.hasNext();) {
              Object target = i.next();
              if (target instanceof GeronimoMBeanTarget) {
                  if (!((GeronimoMBeanTarget) target).canStop()) {
                      return false;
                  }
              }
          }
          return true;
      }
  
      protected void doStop() throws Exception {
          for (Iterator i = mbeanInfo.targets.values().iterator(); i.hasNext();) {
              Object target = i.next();
              if (target instanceof GeronimoMBeanTarget) {
                  ((GeronimoMBeanTarget) target).doStop();
              }
          }
      }
  
      public Object getAttribute(String attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException {
          GeronimoAttributeInfo attributeInfo = (GeronimoAttributeInfo) attributeInfoMap.get(attributeName);
          if (attributeInfo == null) {
              throw new AttributeNotFoundException("Unknown attribute " + attributeName);
          }
  
          return getAttribute(attributeInfo);
      }
  
      private Object getAttribute(GeronimoAttributeInfo attributeInfo) throws ReflectionException {
          // if the attribute is never stale, just return the cached value
          long cacheTimeLimit = attributeInfo.cacheTimeLimit;
          if (cacheTimeLimit == 0) {
              // must be synchronized to assure a consistent view of the cache
              synchronized (attributeInfo) {
                  // has this attribute every been loaded?
                  if (attributeInfo.lastUpdate > 0) {
                      return attributeInfo.value;
                  }
              }
          }
  
          if (cacheTimeLimit > 0) {
              long now = System.currentTimeMillis();
  
              // check if the current cached value is still valid
              // this must be done in a synchronized block to assure a consistent view of the cache
              synchronized (attributeInfo) {
                  long lastUpdate = attributeInfo.lastUpdate;
                  if (now < lastUpdate + (cacheTimeLimit * 1000)) {
                      return attributeInfo.value;
                  }
              }
          }
  
          // invoke the getter
          ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
          try {
              Thread.currentThread().setContextClassLoader(classLoader);
              Object value = attributeInfo.getterProxy.invoke(attributeInfo.target, null);
  
              // if we need to update the cache do it in a synchonized block to assure a
              // consistent view of the cache
              if (cacheTimeLimit >= 0) {
                  synchronized (attributeInfo) {
                      attributeInfo.value = value;
                      attributeInfo.lastUpdate = System.currentTimeMillis();
                  }
              }
              return value;
          } catch (Throwable throwable) {
              throw new ReflectionException(new InvocationTargetException(throwable));
          } finally {
              Thread.currentThread().setContextClassLoader(oldClassLoader);
          }
      }
  
      public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
          GeronimoAttributeInfo attributeInfo = (GeronimoAttributeInfo) attributeInfoMap.get(attribute.getName());
          if (attributeInfo == null) {
              throw new AttributeNotFoundException("Unknown attribute " + attribute);
          }
  
          setAttribute(attributeInfo, attribute.getValue());
      }
  
      private void setAttribute(GeronimoAttributeInfo attributeInfo, Object value) throws ReflectionException {
          ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
          try {
              Thread.currentThread().setContextClassLoader(classLoader);
              attributeInfo.setterProxy.invoke(attributeInfo.target, new Object[]{value});
          } catch (Throwable throwable) {
              throw new ReflectionException(new InvocationTargetException(throwable));
          } finally {
              Thread.currentThread().setContextClassLoader(oldClassLoader);
          }
  
          // if we use caching at all...
          long cacheTimeLimit = attributeInfo.cacheTimeLimit;
          if (cacheTimeLimit >= 0) {
              // this must be in a synchronized block to assure a consistent view of the cache
              synchronized (attributeInfo) {
                  // if have a specific time out, we need to update the last update time stamp
                  if (cacheTimeLimit > 0) {
                      attributeInfo.lastUpdate = System.currentTimeMillis();
                  }
  
                  // finally set the cached value
                  attributeInfo.value = value;
              }
          }
      }
  
      public AttributeList getAttributes(String[] attributes) {
          AttributeList results = new AttributeList(attributes.length);
          for (int i = 0; i < attributes.length; i++) {
              String name = attributes[i];
              try {
                  Object value = getAttribute(name);
                  results.add(new Attribute(name, value));
              } catch (JMException e) {
                  log.warn("Exception while getting attribute " + name, e);
              }
          }
          return results;
      }
  
      public AttributeList setAttributes(AttributeList attributes) {
          AttributeList results = new AttributeList(attributes.size());
          for (Iterator iterator = attributes.iterator(); iterator.hasNext();) {
              Attribute attribute = (Attribute) iterator.next();
              try {
                  setAttribute(attribute);
                  results.add(attribute);
              } catch (JMException e) {
                  log.warn("Exception while setting attribute " + attribute.getName(), e);
              }
          }
          return results;
      }
  
      public Object invoke(String methodName, Object[] arguments, String[] types) throws MBeanException, ReflectionException {
          MethodKey key = new MethodKey(methodName, types);
          Object info = operationInfoMap.get(key);
          if (info == null) {
              throw new ReflectionException(new NoSuchMethodException("Unknown operation " + key));
          }
  
  
          // If this is an attribute accessor get call the getAttibute or setAttribute method,
          // so caching and such are respected.
          if (info instanceof GeronimoAttributeInfo) {
              GeronimoAttributeInfo attributeInfo = (GeronimoAttributeInfo) info;
              if (arguments == null || arguments.length == 0) {
                  return getAttribute(attributeInfo);
              } else {
                  setAttribute(attributeInfo, arguments[0]);
                  return null;
              }
          }
  
          GeronimoOperationInfo operationInfo = (GeronimoOperationInfo) info;
  
          // if the attribute is never stale, just return the cached value
          long cacheTimeLimit = operationInfo.cacheTimeLimit;
          if (cacheTimeLimit == 0) {
              // must be done in a synchronized block to assure a consistent view of the cache
              synchronized (operationInfo) {
                  // has this method every been invoked?
                  if (operationInfo.lastUpdate > 0) {
                      return operationInfo.value;
                  }
              }
          }
  
          if (cacheTimeLimit > 0) {
              long now = System.currentTimeMillis();
  
              // check if the current cached value is still valid
              // this must be done in a synchronized block to assure a consistent view of the cache
              synchronized (operationInfo) {
                  long lastUpdate = operationInfo.lastUpdate;
                  if (now < lastUpdate + (cacheTimeLimit * 1000)) {
                      return operationInfo.value;
                  }
              }
          }
  
          // invoke the operations
          ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
          try {
              Thread.currentThread().setContextClassLoader(classLoader);
              Object value = operationInfo.methodProxy.invoke(operationInfo.target, arguments);
  
              // if we need to update the cache do it in a synchonized block to assure a
              // consistent view of the cache
              if (cacheTimeLimit >= 0) {
                  synchronized (operationInfo) {
                      operationInfo.value = value;
                      operationInfo.lastUpdate = System.currentTimeMillis();
                  }
              }
              return value;
          } catch (Throwable throwable) {
              throw new ReflectionException(new InvocationTargetException(throwable));
          } finally {
              Thread.currentThread().setContextClassLoader(oldClassLoader);
          }
      }
  
      public void load() throws MBeanException, InstanceNotFoundException, RuntimeOperationsException {
          throw new MBeanException(null, "Persistence is not supported");
      }
  
      public void store() throws MBeanException, RuntimeOperationsException, InstanceNotFoundException {
          throw new MBeanException(null, "Persistence is not supported");
      }
  
      public MBeanNotificationInfo[] getNotificationInfo() {
          return mbeanInfo.getNotifications();
      }
  
      private void addManagedObjectMBeanInfo() {
          GeronimoAttributeInfo attributeInfo;
  
          attributeInfo = new GeronimoAttributeInfo();
          attributeInfo.setName("state");
          attributeInfo.target = this;
          attributeInfo.setDescription("J2EE Management State");
          attributeInfo.setReadable(true);
          attributeInfo.setWritable(false);
          attributeInfo.setCacheTimeLimit(-1);
          mbeanInfo.addAttributeInfo(attributeInfo);
  
          attributeInfo = new GeronimoAttributeInfo();
          attributeInfo.setName("objectName");
          attributeInfo.target = this;
          attributeInfo.setDescription("JMX Object Name");
          attributeInfo.setReadable(true);
          attributeInfo.setWritable(false);
          attributeInfo.setCacheTimeLimit(0);
          mbeanInfo.addAttributeInfo(attributeInfo);
  
          attributeInfo = new GeronimoAttributeInfo();
          attributeInfo.setName("startTime");
          attributeInfo.target = this;
          attributeInfo.setDescription("Time the MBean started");
          attributeInfo.setReadable(true);
          attributeInfo.setWritable(false);
          attributeInfo.setCacheTimeLimit(-1);
          mbeanInfo.addAttributeInfo(attributeInfo);
  
          attributeInfo = new GeronimoAttributeInfo();
          attributeInfo.setName("stateManageable");
          attributeInfo.target = this;
          attributeInfo.setDescription("Is this MBean state manageable?");
          attributeInfo.setReadable(true);
          attributeInfo.setWritable(false);
          attributeInfo.setCacheTimeLimit(0);
          mbeanInfo.addAttributeInfo(attributeInfo);
  
          attributeInfo = new GeronimoAttributeInfo();
          attributeInfo.setName("statisticsProvider");
          attributeInfo.target = this;
          attributeInfo.setDescription("Does this MBean provide statistics?");
          attributeInfo.setReadable(true);
          attributeInfo.setWritable(false);
          attributeInfo.setCacheTimeLimit(0);
          mbeanInfo.addAttributeInfo(attributeInfo);
  
          attributeInfo = new GeronimoAttributeInfo();
          attributeInfo.setName("eventProvider");
          attributeInfo.target = this;
          attributeInfo.setDescription("Does this MBean provide events?");
          attributeInfo.setReadable(true);
          attributeInfo.setWritable(false);
          attributeInfo.setCacheTimeLimit(0);
          mbeanInfo.addAttributeInfo(attributeInfo);
  
          GeronimoOperationInfo operationInfo;
  
          operationInfo = new GeronimoOperationInfo();
          operationInfo.setName("start");
          operationInfo.target = this;
          operationInfo.setDescription("Starts the MBean");
          operationInfo.setImpact(MBeanOperationInfo.ACTION);
          operationInfo.setCacheTimeLimit(-1);
          mbeanInfo.addOperationInfo(operationInfo);
  
          operationInfo = new GeronimoOperationInfo();
          operationInfo.setName("startRecursive");
          operationInfo.target = this;
          operationInfo.setDescription("Starts the MBean and then starts all the dependent MBeans");
          operationInfo.setImpact(MBeanOperationInfo.ACTION);
          operationInfo.setCacheTimeLimit(-1);
          mbeanInfo.addOperationInfo(operationInfo);
  
          operationInfo = new GeronimoOperationInfo();
          operationInfo.setName("stop");
          operationInfo.target = this;
          operationInfo.setDescription("Stops the MBean");
          operationInfo.setImpact(MBeanOperationInfo.ACTION);
          operationInfo.setCacheTimeLimit(-1);
          mbeanInfo.addOperationInfo(operationInfo);
  
          GeronimoNotificationInfo notificationInfo = new GeronimoNotificationInfo();
  
          notificationInfo.setName("javax.management.Notification");
          notificationInfo.setDescription("J2EE Notifications");
          notificationInfo.addAllNotificationTypes(NotificationType.TYPES);
          mbeanInfo.addNotificationInfo(notificationInfo);
      }
  
      private final static String[] NO_TYPES = new String[0];
  
      private final class MethodKey {
          private final String name;
          private final String[] argumentTypes;
  
          public MethodKey(String name, String[] argumentTypes) {
              this.name = name;
              if (argumentTypes != null) {
                  this.argumentTypes = argumentTypes;
              } else {
                  this.argumentTypes = NO_TYPES;
              }
          }
  
          public boolean equals(Object object) {
              if (!(object instanceof MethodKey)) {
                  return false;
              }
  
              // match names
              MethodKey methodKey = (MethodKey) object;
              if (!methodKey.name.equals(name)) {
                  return false;
              }
  
              // match arg length
              int length = methodKey.argumentTypes.length;
              if (length != argumentTypes.length) {
                  return false;
              }
  
              // match each arg
              for (int i = 0; i < length; i++) {
                  if (!methodKey.argumentTypes[i].equals(argumentTypes[i])) {
                      return false;
                  }
              }
              return true;
          }
  
          public int hashCode() {
              int result = 17;
              result = 37 * result + name.hashCode();
              for (int i = 0; i < argumentTypes.length; i++) {
                  result = 37 * result + argumentTypes[i].hashCode();
              }
              return result;
          }
  
          public String toString() {
              StringBuffer buffer = new StringBuffer(name);
              for (int i = 0; i < argumentTypes.length; i++) {
                  buffer.append(argumentTypes[i]);
              }
              return buffer.toString();
          }
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/jmx/GeronimoMBeanContext.java
  
  Index: GeronimoMBeanContext.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.jmx;
  
  import javax.management.MBeanServer;
  import javax.management.ObjectName;
  import javax.management.Notification;
  
  /**
   * Context handle for Geronimo MBean targets which gives a target a reference to the MBean server, the object name
   * of the GeronimoMBean containing the target, allows the target to send MBean notifications.
   *
   * @version $Revision: 1.1 $ $Date: 2003/09/05 02:38:32 $
   */
  public class GeronimoMBeanContext {
      private MBeanServer server;
      private GeronimoMBean geronimoMBean;
      private ObjectName objectName;
  
      /**
       * Creates a new context for a target.
       *
       * @param server a reference to the mbean server in which the Geronimo Mbean is registered
       * @param geronimoMBean the Geronimo Mbean the contains the target
       * @param objectName the registered name of the Geronimo MBean
       */
      public GeronimoMBeanContext(MBeanServer server, GeronimoMBean geronimoMBean, ObjectName objectName) {
          this.server = server;
          this.geronimoMBean = geronimoMBean;
          this.objectName = objectName;
      }
  
      /**
       * Gets a reference to the MBean server in which the Geronimo MBean is registered.
       * @return a reference to the MBean server in which the Geronimo MBean is registered
       */
      public MBeanServer getServer() {
          return server;
      }
  
      /**
       * Gets the registered name of the Geronimo MBean
       * @return the registered name of the Geronimo MBean
       */
      public ObjectName getObjectName() {
          return objectName;
      }
  
      /**
       * Sends the specified notification in a javax.management.Notification.
       * The message must be declared in the a GeronimoNotificationInfo.
       * @param message the message to send
       */
      public void sendNotification(String message) {
          geronimoMBean.sendNotification(message);
      }
  
      /**
       * Sends the specified notification .
       * The norification must be declared in the a GeronimoNotificationInfo.
       * @param notification the notification to send
       */
      public void sendNotification(Notification notification) {
          geronimoMBean.sendNotification(notification);
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/jmx/GeronimoMBeanInfo.java
  
  Index: GeronimoMBeanInfo.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.jmx;
  
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Set;
  import javax.management.MBeanAttributeInfo;
  import javax.management.MBeanConstructorInfo;
  import javax.management.MBeanInfo;
  import javax.management.MBeanNotificationInfo;
  import javax.management.MBeanOperationInfo;
  
  import org.apache.geronimo.common.Classes;
  
  /**
   * Describes a GeronimoMBean.  This extension allows the properties to be mutable during setup,
   * and once the MBean is deployed an imutable copy of will be made.  This class also adds support for multi target
   * POJOs under the MBean.
   *
   * @version $Revision: 1.1 $ $Date: 2003/09/05 02:38:32 $
   */
  public final class GeronimoMBeanInfo extends MBeanInfo {
      /**
       * The key for the default target.
       */
      private final static String DEFAULT_TARGET_NAME = "default";
  
      private static final MBeanConstructorInfo[] NO_CONSTRUCTORS = new MBeanConstructorInfo[0];
      private final boolean immutable;
      private final int hashCode = System.identityHashCode(this);
      private String name;
      private String description;
      private final Map targetClasses = new HashMap();
      private final Set attributes = new HashSet();
      private final Set operations = new HashSet();
      private final Set notifications = new HashSet();
      final Map targets = new HashMap();
      public static final String ALWAYS = "always";
      public static final String NEVER = "never";
  
      public GeronimoMBeanInfo() {
          super(null, null, null, null, null, null);
          immutable = false;
      }
  
      GeronimoMBeanInfo(GeronimoMBeanInfo source) {
          super(null, null, null, null, null, null);
          immutable = true;
  
          //
          // Required
          //
          if (source.targetClasses.get(DEFAULT_TARGET_NAME) == null) {
              throw new IllegalStateException("No default target specified");
          }
          // we can just put all because everything in the targetClasses map is immutable
          targetClasses.putAll(source.targetClasses);
  
          //
          // Optional
          //
          name = source.name;
          description = source.description;
  
          //
          // Derived
          //
          String className = null;
          try {
              for (Iterator i = targetClasses.entrySet().iterator(); i.hasNext();) {
                  Map.Entry entry = (Map.Entry) i.next();
                  className = (String) entry.getValue();
                  Object target = Classes.loadClass(className).newInstance();
                  targets.put(entry.getKey(), target);
              }
          } catch (ClassNotFoundException e) {
              throw new IllegalArgumentException("Target class could not be loaded: className=" + className);
          } catch (InstantiationException e) {
              IllegalArgumentException exception = new IllegalArgumentException("Target class could not be loaded: className=" + className);
              exception.initCause(e);
              throw exception;
          } catch (IllegalAccessException e) {
              IllegalArgumentException exception = new IllegalArgumentException("Cound not access target class default constructor: className=" + className);
              exception.initCause(e);
              throw exception;
          }
  
          //
          // Contained classes
          //
          for (Iterator iterator = source.attributes.iterator(); iterator.hasNext();) {
              GeronimoAttributeInfo attributeInfo = (GeronimoAttributeInfo) iterator.next();
              attributes.add(new GeronimoAttributeInfo(attributeInfo, this));
          }
  
          for (Iterator iterator = source.operations.iterator(); iterator.hasNext();) {
              GeronimoOperationInfo operationInfo = (GeronimoOperationInfo) iterator.next();
              operations.add(new GeronimoOperationInfo(operationInfo, this));
          }
  
          for (Iterator iterator = source.notifications.iterator(); iterator.hasNext();) {
              GeronimoNotificationInfo notificationInfo = (GeronimoNotificationInfo) iterator.next();
              notifications.add(new GeronimoNotificationInfo(notificationInfo, this));
          }
      }
  
      public String getClassName() {
          return getTargetClass();
      }
  
      public String getTargetClass() {
          return (String) targetClasses.get(DEFAULT_TARGET_NAME);
      }
  
      public void setTargetClass(String className) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          targetClasses.put(DEFAULT_TARGET_NAME, className);
      }
  
      public String getTargetClass(String targetName) {
          return (String) targetClasses.get(targetName);
      }
  
      public void setTargetClass(String targetName, String className) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          if (targetName != null && targetName.length() > 0) {
              targetClasses.put(targetName, className);
          } else {
              targetClasses.put(DEFAULT_TARGET_NAME, className);
          }
      }
  
      Object getTarget() {
          return targets.get(DEFAULT_TARGET_NAME);
      }
  
      Object getTarget(String name) {
          return targets.get(name);
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.name = name;
      }
  
      public String getDescription() {
          return description;
      }
  
      public void setDescription(String description) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.description = description;
      }
  
      public MBeanConstructorInfo[] getConstructors() {
          // This MBean does not have constructors
          return NO_CONSTRUCTORS;
      }
  
      public Set getAttributeSet() {
          return Collections.unmodifiableSet(attributes);
      }
  
      public MBeanAttributeInfo[] getAttributes() {
          return (MBeanAttributeInfo[]) attributes.toArray(new MBeanAttributeInfo[attributes.size()]);
      }
  
      public void addAttributeInfo(GeronimoAttributeInfo attributeInfo) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          attributes.add(attributeInfo);
      }
  
      public Set getOperationsSet() {
          return Collections.unmodifiableSet(operations);
      }
  
      public MBeanOperationInfo[] getOperations() {
          return (MBeanOperationInfo[]) operations.toArray(new MBeanOperationInfo[operations.size()]);
      }
  
      public void addOperationInfo(GeronimoOperationInfo operationInfo) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          operations.add(operationInfo);
      }
  
      public Set getNotificationsSet() {
          return Collections.unmodifiableSet(notifications);
      }
  
      public MBeanNotificationInfo[] getNotifications() {
          return (MBeanNotificationInfo[]) notifications.toArray(new MBeanNotificationInfo[notifications.size()]);
      }
  
      public void addNotificationInfo(GeronimoNotificationInfo notificationInfo) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          notifications.add(notificationInfo);
      }
  
      public int hashCode() {
          return hashCode;
      }
  
      public boolean equals(Object object) {
          return (this == object);
      }
  
      public String toString() {
          return "[GeronimoMBeanInfo: name=" + name + " description=" + description + "]";
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/jmx/GeronimoMBeanInfoXMLLoader.java
  
  Index: GeronimoMBeanInfoXMLLoader.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.jmx;
  
  import java.io.InputStream;
  import java.net.URI;
  
  import org.apache.commons.digester.Digester;
  import org.apache.geronimo.deployment.DeploymentException;
  import org.apache.xerces.parsers.SAXParser;
  
  
  /**
   * Loads the GeronimoMBeanInfo from xml.
   *
   * @version $Revision: 1.1 $ $Date: 2003/09/05 02:38:32 $
   */
  public class GeronimoMBeanInfoXMLLoader {
      private Digester digester;
  
      public GeronimoMBeanInfoXMLLoader() throws DeploymentException {
          SAXParser parser = new SAXParser();
          try {
              parser.setFeature("http://xml.org/sax/features/validation", true);
              parser.setFeature("http://apache.org/xml/features/validation/schema", true);
              parser.setFeature("http://apache.org/xml/features/validation/dynamic", true);
          } catch (Exception e) {
              throw new DeploymentException(e);
          }
  
          digester = new Digester(parser);
  
          // MBean
          digester.addObjectCreate("mbean", GeronimoMBeanInfo.class);
          digester.addCallMethod("mbean/target", "setTargetClass", 2);
          digester.addCallParam("mbean/target", 0, "name");
          digester.addCallParam("mbean/target", 1, "class");
  
          // Attribute
          digester.addObjectCreate("mbean/attribute", GeronimoAttributeInfo.class);
          digester.addSetProperties("mbean/attribute", "cache", "cachePolicy");
          digester.addSetNext("mbean/attribute", "addAttributeInfo");
  
          // Operation
          digester.addObjectCreate("mbean/operation", GeronimoOperationInfo.class);
          digester.addSetProperties("mbean/operation", "cache", "cachePolicy");
          digester.addObjectCreate("mbean/operation/parameter", GeronimoParameterInfo.class);
          digester.addSetProperties("mbean/operation/parameter");
          digester.addSetNext("mbean/operation/parameter", "addParameterInfo");
          digester.addSetNext("mbean/operation", "addOperationInfo");
  
          // Notification
          digester.addObjectCreate("mbean/notification", GeronimoNotificationInfo.class);
          digester.addSetProperties("mbean/notification", "class", "name");
          digester.addCallMethod("mbean/notification/type", "addNotificationType", 1);
          digester.addCallParam("mbean/notification/type", 0);
          digester.addSetNext("mbean/notification", "addNotificationInfo");
      }
  
      public GeronimoMBeanInfo loadXML(InputStream in) throws DeploymentException {
          try {
              return (GeronimoMBeanInfo) digester.parse(in);
          } catch (Exception e) {
              throw new DeploymentException(e);
          }
      }
  
      public GeronimoMBeanInfo loadXML(URI uri) throws DeploymentException {
          try {
              return (GeronimoMBeanInfo) digester.parse(uri.toURL().openStream());
          } catch (Exception e) {
              throw new DeploymentException(e);
          }
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/jmx/GeronimoMBeanTarget.java
  
  Index: GeronimoMBeanTarget.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.jmx;
  
  /**
   * An optional interface for targets of a GeronimoMBean.  When a target implements this interface, the target
   * will get a regerence to the GeronimoMBeanContext, and will get life-cycle callbacks.
   *
   * @version $Revision: 1.1 $ $Date: 2003/09/05 02:38:32 $
   */
  public interface GeronimoMBeanTarget {
      /**
       * Sets the GeronimoMBeanContext.  This is called before doStart and with a null context after stop.
       *
       * @param context the new context; will be null after stop
       */
      void setMBeanContext(GeronimoMBeanContext context);
  
      /**
       * Checks if the target is ready to start.  A target can delay the start of the GeronimoBean by returning
       * false from this method.
       *
       * @return true if the target is ready to start; false otherwise
       */
      boolean canStart();
  
      /**
       * Starts the target.  This method is called by the GeronimoMBean to inform the target that the MBean is about to
       * start.  This is called immediately before moving to the running state.
       */
      void doStart();
  
      /**
       * Checks if the target is ready to stop.  A target can delay the stopping of the GeronimoBean by returning
       * false from this method.
       *
       * @return true if the target is ready to stop; false otherwise
       */
      boolean canStop();
  
      /**
       * Stops the target.  This method is called by the GeronimoMBean to inform the target that the MBean is about to
       * stop.  This is called immediately before moving to the stopped state.
       */
      void doStop();
  
      /**
       * Fails the MBean.  This method is called by the GeronimoMBean to inform the target that the MBean is about to
       * fail.  This is called immediately before moving to the failed state.
       */
      void doFail();
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/jmx/GeronimoNotificationInfo.java
  
  Index: GeronimoNotificationInfo.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.jmx;
  
  import java.util.Collection;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.Set;
  import javax.management.MBeanNotificationInfo;
  
  /**
   * Describes a notification of a GeronimoMBean.  This extension allows the properties to be mutable during setup,
   * and once the MBean is deployed an imutable copy of will be made.
   *
   * @version $Revision: 1.1 $ $Date: 2003/09/05 02:38:32 $
   */
  public final class GeronimoNotificationInfo extends MBeanNotificationInfo {
      private final boolean immutable;
      private String name;
      private String description;
      private final Set notificationTypes = new HashSet();
      private final int hashCode = System.identityHashCode(this);
  
      public GeronimoNotificationInfo() {
          super(null, null, null);
          immutable = false;
      }
  
      GeronimoNotificationInfo(GeronimoNotificationInfo source, GeronimoMBeanInfo parent) {
          super(null, null, null);
          immutable = true;
          name = source.name;
          description = source.name;
          notificationTypes.addAll(source.notificationTypes);
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.name = name;
      }
  
      public String getDescription() {
          return description;
      }
  
      public void setDescription(String description) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.description = description;
      }
  
      public String[] getNotifTypes() {
          return (String[]) notificationTypes.toArray(new String[notificationTypes.size()]);
      }
  
      public void addNotificationType(String notificationType) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          notificationTypes.add(notificationType);
      }
  
      public void addAllNotificationTypes(String[] notificationTypes) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          for (int i = 0; i < notificationTypes.length; i++) {
              this.notificationTypes.add(notificationTypes[i]);
          }
      }
  
      public void addAllNotificationTypes(Collection notificationTypes) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          for (Iterator iterator = notificationTypes.iterator(); iterator.hasNext();) {
              String notificationType = (String) iterator.next();
              this.notificationTypes.add(notificationType);
          }
      }
  
      public int hashCode() {
          return hashCode;
      }
  
      public boolean equals(Object object) {
          return (this == object);
      }
  
      public String toString() {
          return "[GeronimoNotificationInfo: name=" + name + " description=" + description + "]";
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/jmx/GeronimoOperationInfo.java
  
  Index: GeronimoOperationInfo.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.jmx;
  
  import java.lang.reflect.Method;
  import java.util.Collections;
  import java.util.LinkedList;
  import java.util.List;
  import javax.management.MBeanOperationInfo;
  import javax.management.MBeanParameterInfo;
  
  import net.sf.cglib.MethodProxy;
  
  /**
   * Describes an operation on a GeronimoMBean.  This extension allows the properties to be mutable during setup,
   * and once the MBean is deployed an imutable copy of will be made.  This class also adds support to
   * direct the operation to a specific target in a multi target GeronimoMBean.  It also supports caching of the
   * invocation result, which can reduce the number of calls on the target.
   *
   * @version $Revision: 1.1 $ $Date: 2003/09/05 02:38:32 $
   */
  public final class GeronimoOperationInfo extends MBeanOperationInfo {
      /**
       * Is this class still mutable from users.
       */
      private final boolean immutable;
  
      /**
       * The name of this method.
       */
      private String name;
  
      /**
       * Parameters of this method.
       */
      private final List parameters = new LinkedList();
  
      /**
       * Parameter types of this operation.
       */
      private final String[] parameterTypes;
  
      /**
       * Return type of the operation.
       * This is set during the transition to running.
       */
      private final String returnType;
  
      /**
       * A user displayable description of this method.
       */
      private String description;
  
      /**
       * Impact of the method as defined in the JMX spec.
       */
      private int impact;
  
      /**
       * Logical name of the target.
       */
      private String targetName;
  
      /**
       * Target method name.
       */
      private String targetMethodName;
  
      /**
       * The maximum ammount ot time in seconds that a cached value is valid.
       */
      long cacheTimeLimit;
  
      //
      // Runtime information -- this is not exposed to clients
      //
  
      /**
       * The object on which the method will be invoked.
       */
      Object target;
  
      /**
       * The method that will be called on the target.
       */
      final MethodProxy methodProxy;
  
      /**
       * The cached result of the method.
       */
      Object value;
  
      /**
       * Time stamp from when the value field was last updated.
       */
      long lastUpdate;
      private final int hashCode = System.identityHashCode(this);
  
      public GeronimoOperationInfo() {
          super(null, null, null, null, MBeanOperationInfo.UNKNOWN);
          immutable = false;
          methodProxy = null;
          returnType = null;
          parameterTypes = null;
      }
  
      GeronimoOperationInfo(GeronimoOperationInfo source, GeronimoMBeanInfo parent) {
          super(null, null, null, null, MBeanOperationInfo.UNKNOWN);
          this.immutable = true;
  
          //
          // Required
          //
          if (source.name == null) {
              throw new IllegalArgumentException("Operation name is null");
          }
          name = source.name;
  
  
          //
          // Optional
          //
          description = source.description;
          impact = source.impact;
          cacheTimeLimit = source.cacheTimeLimit;
  
          //
          // Optional (derived)
          //
          if(source.target != null) {
              target = source.target;
              targetName = source.targetName;
          } else if (source.targetName == null) {
              target = parent.getTarget();
          } else {
              targetName = source.targetName;
              target = parent.getTarget(targetName);
          }
  
          if (source.targetMethodName == null) {
              targetMethodName = name;
          } else {
              targetMethodName = source.targetMethodName;
          }
  
          parameterTypes = new String[source.parameters.size()];
          Class[] types = new Class[source.parameters.size()];
          for (int i = 0; i < source.parameters.size(); i++) {
              GeronimoParameterInfo parameterInfo = (GeronimoParameterInfo) source.parameters.get(i);
              parameterInfo = new GeronimoParameterInfo(parameterInfo, this);
              parameters.add(parameterInfo);
              types[i] = parameterInfo.getTypeClass();
              parameterTypes[i] = parameterInfo.getType();
          }
  
          //
          // Derived
          //
          Method method = null;
          try {
              method = target.getClass().getMethod(targetMethodName, types);
          } catch (NoSuchMethodException e) {
              throw new IllegalArgumentException("Target does not have specifed method:" +
                      " target=" + target +
                      " methodName=" + targetMethodName);
          } catch (SecurityException e) {
              e.printStackTrace();  //To change body of catch statement use Options | File Templates.
          }
          returnType = method.getReturnType().getName();
          methodProxy = MethodProxy.create(method, method);
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String operationName) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.name = operationName;
      }
  
      public String getDescription() {
          return description;
      }
  
      public void setDescription(String description) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.description = description;
      }
  
      public int getImpact() {
          return impact;
      }
  
      public void setImpact(int impact) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          if (impact != MBeanOperationInfo.ACTION &&
                  impact != MBeanOperationInfo.ACTION_INFO &&
                  impact != MBeanOperationInfo.INFO &&
                  impact != MBeanOperationInfo.UNKNOWN) {
              throw new IllegalArgumentException("Unknow impact type: " + impact);
          }
          this.impact = impact;
      }
  
      public String getReturnType() {
          return returnType;
      }
  
      public String getTargetName() {
          return targetName;
      }
  
      public void setTargetName(String targetName) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.targetName = targetName;
      }
  
      public String getTargetMethodName() {
          return targetMethodName;
      }
  
      public void setMethodName(String targetMethodName) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.targetMethodName = targetMethodName;
      }
  
      public long getCacheTimeLimit() {
          return cacheTimeLimit;
      }
  
      public void setCacheTimeLimit(long cacheTimeLimit) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.cacheTimeLimit = cacheTimeLimit;
      }
  
      public String getCachePolicy() {
          if(cacheTimeLimit < 0) {
              return GeronimoMBeanInfo.NEVER;
          } else if (cacheTimeLimit == 0) {
              return GeronimoMBeanInfo.ALWAYS;
          } else {
              return "" + cacheTimeLimit;
          }
  
      }
      public void setCachePolicy(String cacheTimeLimit) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          if (cacheTimeLimit == null || cacheTimeLimit.length() == 0) {
              throw new IllegalArgumentException("cacheTimeLimit is null");
          }
          if (GeronimoMBeanInfo.ALWAYS.equalsIgnoreCase(cacheTimeLimit)) {
              this.cacheTimeLimit = 0;
          } else if (GeronimoMBeanInfo.NEVER.equalsIgnoreCase(cacheTimeLimit)) {
              this.cacheTimeLimit = -1;
          } else {
              this.cacheTimeLimit = Long.parseLong(cacheTimeLimit);
          }
      }
  
      public List getParameterList() {
          return Collections.unmodifiableList(parameters);
      }
  
      public String[] getParameterTypes() {
          return parameterTypes;
      }
  
      public MBeanParameterInfo[] getSignature() {
          return (MBeanParameterInfo[]) parameters.toArray(new MBeanParameterInfo[parameters.size()]);
      }
  
      public void addParameterInfo(GeronimoParameterInfo parameterInfo) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          parameters.add(parameterInfo);
      }
  
      public void addParameterInfo(String name, String type, String description) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          GeronimoParameterInfo parameterInfo = new GeronimoParameterInfo();
          parameterInfo.setName(name);
          parameterInfo.setType(type);
          parameterInfo.setDescription(description);
          parameters.add(parameterInfo);
      }
  
      public int hashCode() {
          return hashCode;
      }
  
      public boolean equals(Object object) {
          return (this == object);
      }
  
      public String toString() {
          return "[GeronimoOperationInfo: name=" +  name + " description=" + description + "]";
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/jmx/GeronimoParameterInfo.java
  
  Index: GeronimoParameterInfo.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.jmx;
  
  import javax.management.MBeanParameterInfo;
  
  import org.apache.geronimo.common.Classes;
  
  /**
   * Describes a parameter of an operation.  This extension allows the properties to be mutable during setup,
   * and once the MBean is deployed an imutable copy of will be made.
   *
   * @version $Revision: 1.1 $ $Date: 2003/09/05 02:38:32 $
   */
  public final class GeronimoParameterInfo extends MBeanParameterInfo {
      private final int hashCode = System.identityHashCode(this);
      private final boolean immutable;
      private String name;
      private String type;
      private String description;
      private final Class typeClass;
  
      public GeronimoParameterInfo() {
          super(null, null, null);
          immutable = false;
          typeClass = null;
      }
  
      GeronimoParameterInfo(GeronimoParameterInfo source, GeronimoOperationInfo parent) {
          super(null, null, null);
          this.immutable = true;
  
          //
          // Required
          //
          type = source.type;
          if (type == null) {
              throw new IllegalArgumentException("Parameter type is null: " + name);
          }
  
          //
          // Optional
          //
          name = source.name;
          description = source.description;
  
          //
          // Derived
          //
          try {
              typeClass = Classes.loadClass(getType());
          } catch (ClassNotFoundException e) {
              throw new IllegalArgumentException("Could not load parameter type class: name=" + name + " type=" + type);
          }
      }
  
      public String getName() {
          return name;
      }
  
      public void setName(String name) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.name = name;
      }
  
      public String getType() {
          return type;
      }
  
      public void setType(String type) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.type = type;
      }
  
      public String getDescription() {
          return description;
      }
  
      public void setDescription(String description) {
          if (immutable) {
              throw new IllegalStateException("Data is no longer mutable");
          }
          this.description = description;
      }
  
      Class getTypeClass() {
          return typeClass;
      }
  
      public int hashCode() {
          return hashCode;
      }
  
      public boolean equals(Object object) {
          return object == this;
      }
  
      public String toString() {
          return "[GeronimoParameterInfo: name=" + name + " type=" + type + " description=" + description + "]";
      }
  }