tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cos...@apache.org
Subject svn commit: r407661 [1/3] - in /tomcat/sandbox/java/org/apache/tomcat/util/modeler: ./ modules/
Date Thu, 18 May 2006 23:27:35 GMT
Author: costin
Date: Thu May 18 16:27:34 2006
New Revision: 407661

URL: http://svn.apache.org/viewvc?rev=407661&view=rev
Log:
Refactored modeler - using DynamicMbeans instead of model mbeans.

The name 'modeler' is still valid - it 'models' mbeans, but it doesn't have to use
the heavy ModelMBean interfaces. 

Most of the model-related features, and other things not used in tomcat are removed. 

Tested on tomcat6 - but since it's a big change I want to have it in sandbox first


Added:
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/AttributeInfo.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseModelMBean.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseNotificationBroadcaster.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/ConstructorInfo.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/FeatureInfo.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/FixedNotificationFilter.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/ManagedBean.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/NotificationInfo.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/OperationInfo.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/ParameterInfo.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/Registry.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/RegistryMBean.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/mbeans-descriptors.dtd
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/modules/
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDOMSource.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDigesterSource.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsIntrospectionSource.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsSerSource.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/modules/MbeansSource.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/modules/MbeansSourceMBean.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/modules/ModelerSource.java
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/modules/package.html
    tomcat/sandbox/java/org/apache/tomcat/util/modeler/package.html

Added: tomcat/sandbox/java/org/apache/tomcat/util/modeler/AttributeInfo.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/tomcat/util/modeler/AttributeInfo.java?rev=407661&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/modeler/AttributeInfo.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/modeler/AttributeInfo.java Thu May 18 16:27:34 2006
@@ -0,0 +1,274 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.tomcat.util.modeler;
+
+
+import java.io.Serializable;
+
+import javax.management.MBeanAttributeInfo;
+
+
+/**
+ * <p>Internal configuration information for an <code>Attribute</code>
+ * descriptor.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 155428 $ $Date: 2005-02-26 14:12:25 +0100 (sam., 26 févr. 2005) $
+ */
+
+public class AttributeInfo extends FeatureInfo implements Serializable {
+    static final long serialVersionUID = -2511626862303972143L;
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The <code>ModelMBeanAttributeInfo</code> object that corresponds
+     * to this <code>AttributeInfo</code> instance.
+     */
+    protected transient MBeanAttributeInfo info = null;
+    protected String displayName = null;
+    protected String getMethod = null;
+    protected String setMethod = null;
+
+//    protected transient Method getMethodObj = null;
+//    protected transient Method setMethodObj = null;
+
+    protected boolean readable = true;
+    protected boolean writeable = true;
+
+    protected boolean is = false;
+    protected String type = null;
+
+    protected String persist;
+    protected String defaultStringValue;
+    // ------------------------------------------------------------- Properties
+
+
+    /**
+     * Override the <code>description</code> property setter.
+     *
+     * @param description The new description
+     */
+    public void setDescription(String description) {
+        super.setDescription(description);
+        this.info = null;
+    }
+
+    /**
+     * Override the <code>name</code> property setter.
+     *
+     * @param name The new name
+     */
+    public void setName(String name) {
+        super.setName(name);
+        this.info = null;
+    }
+
+    /**
+     * The display name of this attribute.
+     */
+    public String getDisplayName() {
+        return (this.displayName);
+    }
+
+    public void setDisplayName(String displayName) {
+        this.displayName = displayName;
+    }
+
+    /**
+     * The name of the property getter method, if non-standard.
+     */
+    public String getGetMethod() {
+        if(getMethod == null) 
+            getMethod = getMethodName(getName(), true, isIs());
+        return (this.getMethod);
+    }
+
+    public void setGetMethod(String getMethod) {
+        this.getMethod = getMethod;
+        this.info = null;
+    }
+
+    /**
+     * Is this a boolean attribute with an "is" getter?
+     */
+    public boolean isIs() {
+        return (this.is);
+    }
+
+    public void setIs(boolean is) {
+        this.is = is;
+        this.info = null;
+    }
+
+
+    /**
+     * Is this attribute readable by management applications?
+     */
+    public boolean isReadable() {
+        return (this.readable);
+    }
+
+    public void setReadable(boolean readable) {
+        this.readable = readable;
+        this.info = null;
+    }
+
+
+    /**
+     * The name of the property setter method, if non-standard.
+     */
+    public String getSetMethod() {
+        if( setMethod == null )
+            setMethod = getMethodName(getName(), false, false);
+        return (this.setMethod);
+    }
+
+    public void setSetMethod(String setMethod) {
+        this.setMethod = setMethod;
+        this.info = null;
+    }
+
+
+    /**
+     * The fully qualified Java class name of this attribute.
+     */
+    public String getType() {
+        return (this.type);
+    }
+
+    public void setType(String type) {
+        this.type = type;
+        this.info = null;
+    }
+
+
+    /**
+     * Is this attribute writeable by management applications?
+     */
+    public boolean isWriteable() {
+        return (this.writeable);
+    }
+
+    public void setWriteable(boolean writeable) {
+        this.writeable = writeable;
+        this.info = null;
+    }
+
+    /** Persistence policy.
+     * All persistent attributes should have this attribute set.
+     * Valid values:
+     *   ???
+     */
+    public String getPersist() {
+        return persist;
+    }
+
+    public void setPersist(String persist) {
+        this.persist = persist;
+    }
+
+    /** Default value. If set, it can provide info to the user and
+     * it can be used by persistence mechanism to generate a more compact
+     * representation ( a value may not be saved if it's default )
+     */
+    public String getDefault() {
+        return defaultStringValue;
+    }
+
+    public void setDefault(String defaultStringValue) {
+        this.defaultStringValue = defaultStringValue;
+    }
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Create and return a <code>ModelMBeanAttributeInfo</code> object that
+     * corresponds to the attribute described by this instance.
+     */
+    public MBeanAttributeInfo createAttributeInfo() {
+        // Return our cached information (if any)
+        if (info != null)
+            return (info);
+        // Create and return a new information object
+        info = new MBeanAttributeInfo
+            (getName(), getType(), getDescription(),
+             isReadable(), isWriteable(), false);
+        return (info);
+
+    }
+
+
+    /**
+     * Return a string representation of this attribute descriptor.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer("AttributeInfo[");
+        sb.append("name=");
+        sb.append(name);
+        sb.append(", description=");
+        sb.append(description);
+        if (!readable) {
+            sb.append(", readable=");
+            sb.append(readable);
+        }
+        sb.append(", type=");
+        sb.append(type);
+        if (!writeable) {
+            sb.append(", writeable=");
+            sb.append(writeable);
+        }
+        sb.append("]");
+        return (sb.toString());
+
+    }
+
+
+    // -------------------------------------------------------- Private Methods
+
+
+    /**
+     * Create and return the name of a default property getter or setter
+     * method, according to the specified values.
+     *
+     * @param name Name of the property itself
+     * @param getter Do we want a get method (versus a set method)?
+     * @param is If returning a getter, do we want the "is" form?
+     */
+    private String getMethodName(String name, boolean getter, boolean is) {
+
+        StringBuffer sb = new StringBuffer();
+        if (getter) {
+            if (is)
+                sb.append("is");
+            else
+                sb.append("get");
+        } else
+            sb.append("set");
+        sb.append(Character.toUpperCase(name.charAt(0)));
+        sb.append(name.substring(1));
+        return (sb.toString());
+
+    }
+
+
+}

Added: tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java?rev=407661&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java Thu May 18 16:27:34 2006
@@ -0,0 +1,159 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.tomcat.util.modeler;
+
+
+import java.util.HashSet;
+
+import javax.management.AttributeChangeNotification;
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+
+
+/**
+ * <p>Implementation of <code>NotificationFilter</code> for attribute change
+ * notifications.  This class is used by <code>BaseModelMBean</code> to
+ * construct attribute change notification event filters when a filter is not
+ * supplied by the application.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 155428 $ $Date: 2005-02-26 14:12:25 +0100 (sam., 26 févr. 2005) $
+ */
+
+public class BaseAttributeFilter implements NotificationFilter {
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Construct a new filter that accepts only the specified attribute
+     * name.
+     *
+     * @param name Name of the attribute to be accepted by this filter, or
+     *  <code>null</code> to accept all attribute names
+     */
+    public BaseAttributeFilter(String name) {
+
+        super();
+        if (name != null)
+            addAttribute(name);
+
+    }
+
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The set of attribute names that are accepted by this filter.  If this
+     * list is empty, all attribute names are accepted.
+     */
+    private HashSet names = new HashSet();
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Add a new attribute name to the set of names accepted by this filter.
+     *
+     * @param name Name of the attribute to be accepted
+     */
+    public void addAttribute(String name) {
+
+        synchronized (names) {
+            names.add(name);
+        }
+
+    }
+
+
+    /**
+     * Clear all accepted names from this filter, so that it will accept
+     * all attribute names.
+     */
+    public void clear() {
+
+        synchronized (names) {
+            names.clear();
+        }
+
+    }
+
+
+    /**
+     * Return the set of names that are accepted by this filter.  If this
+     * filter accepts all attribute names, a zero length array will be
+     * returned.
+     */
+    public String[] getNames() {
+
+        synchronized (names) {
+            return ((String[]) names.toArray(new String[names.size()]));
+        }
+
+    }
+
+
+    /**
+     * <p>Test whether notification enabled for this event.
+     * Return true if:</p>
+     * <ul>
+     * <li>This is an attribute change notification</li>
+     * <li>Either the set of accepted names is empty (implying that all
+     *     attribute names are of interest) or the set of accepted names
+     *     includes the name of the attribute in this notification</li>
+     * </ul>
+     */
+    public boolean isNotificationEnabled(Notification notification) {
+
+        if (notification == null)
+            return (false);
+        if (!(notification instanceof AttributeChangeNotification))
+            return (false);
+        AttributeChangeNotification acn =
+            (AttributeChangeNotification) notification;
+        if (!AttributeChangeNotification.ATTRIBUTE_CHANGE.equals(acn.getType()))
+            return (false);
+        synchronized (names) {
+            if (names.size() < 1)
+                return (true);
+            else
+                return (names.contains(acn.getAttributeName()));
+        }
+
+    }
+
+
+    /**
+     * Remove an attribute name from the set of names accepted by this
+     * filter.
+     *
+     * @param name Name of the attribute to be removed
+     */
+    public void removeAttribute(String name) {
+
+        synchronized (names) {
+            names.remove(name);
+        }
+
+    }
+
+
+}

Added: tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseModelMBean.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseModelMBean.java?rev=407661&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseModelMBean.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseModelMBean.java Thu May 18 16:27:34 2006
@@ -0,0 +1,1292 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.tomcat.util.modeler;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+
+import javax.management.Attribute;
+import javax.management.AttributeChangeNotification;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InstanceNotFoundException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.RuntimeErrorException;
+import javax.management.RuntimeOperationsException;
+import javax.management.modelmbean.InvalidTargetObjectTypeException;
+import javax.management.modelmbean.ModelMBeanNotificationBroadcaster;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/*
+ * Changes from commons.modeler:
+ * 
+ *  - use DynamicMBean
+ *  - remove methods not used in tomcat and redundant/not very generic
+ *  - must be created from the ManagedBean - I don't think there were any direct
+ *    uses, but now it is required.
+ *  - some of the gratuituous flexibility removed - instead this is more predictive and
+ *    strict with the use cases.
+ *  - all Method and metadata is stored in ManagedBean. BaseModelBMean and ManagedBean act
+ *    like Object and Class. 
+ *  - setModelMBean is no longer called on resources ( not used in tomcat )
+ *  - no caching of Methods for now - operations and setters are not called repeatedly in most 
+ *  management use cases. Getters should't be called very frequently either - and even if they
+ *  are, the overhead of getting the method should be small compared with other JMX costs ( RMI, etc ).
+ *  We can add getter cache if needed.
+ *  - removed unused constructor, fields
+ *  
+ *  TODO:
+ *   - clean up catalina.mbeans, stop using weird inheritance
+ */
+
+/**
+ * <p>Basic implementation of the <code>DynamicMBean</code> interface, which
+ * supports the minimal requirements of the interface contract.</p>
+ *
+ * <p>This can be used directly to wrap an existing java bean, or inside
+ * an mlet or anywhere an MBean would be used. 
+ *
+ * Limitations:
+ * <ul>
+ * <li>Only managed resources of type <code>objectReference</code> are
+ *     supportd.</li>
+ * <li>Caching of attribute values and operation results is not supported.
+ *     All calls to <code>invoke()</code> are immediately executed.</li>
+ * <li>Persistence of MBean attributes and operations is not supported.</li>
+ * <li>All classes referenced as attribute types, operation parameters, or
+ *     operation return values must be one of the following:
+ *     <ul>
+ *     <li>One of the Java primitive types (boolean, byte, char, double,
+ *         float, integer, long, short).  Corresponding value will be wrapped
+ *         in the appropriate wrapper class automatically.</li>
+ *     <li>Operations that return no value should declare a return type of
+ *         <code>void</code>.</li>
+ *     </ul>
+ * <li>Attribute caching is not supported</li>
+ * </ul>
+ *
+ * @author Craig R. McClanahan
+ * @author Costin Manolache
+ */
+public class BaseModelMBean implements DynamicMBean, MBeanRegistration, ModelMBeanNotificationBroadcaster {
+    private static Log log = LogFactory.getLog(BaseModelMBean.class);
+
+    // ----------------------------------------------------------- Constructors
+
+    /**
+     * Construct a <code>ModelMBean</code> with default
+     * <code>ModelMBeanInfo</code> information.
+     *
+     * @exception MBeanException if the initializer of an object
+     *  throws an exception
+     * @exception RuntimeOperationsException if an IllegalArgumentException
+     *  occurs
+     */
+    public BaseModelMBean() throws MBeanException, RuntimeOperationsException {
+
+        super();
+        if( log.isDebugEnabled()) log.debug("default constructor");
+        //BaseModelMBeans should be created only from ManagedBean, which sets the model explicitely.
+        //No need to create another object
+        //setModelMBeanInfo(createDefaultModelMBeanInfo());
+    }
+
+
+    /**
+     * Construct a <code>ModelMBean</code> associated with the specified
+     * <code>ModelMBeanInfo</code> information.
+     *
+     * @param info ModelMBeanInfo for this MBean
+     *
+     * @exception MBeanException if the initializer of an object
+     *  throws an exception
+     * @exception RuntimeOperationsException if an IllegalArgumentException
+     *  occurs
+     */
+//     public BaseModelMBean(ModelMBeanInfo info)
+//        throws MBeanException, RuntimeOperationsException {
+//        // XXX should be deprecated - just call setInfo
+//        super();
+//        setModelMBeanInfo(info);
+//        if( log.isDebugEnabled()) log.debug("ModelMBeanInfo constructor");
+//    }
+
+    /** Construct a ModelMBean of a specified type.
+     *  The type can be a class name or the key used in one of the descriptors.
+     *
+     * If no descriptor is available, we'll first try to locate one in
+     * the same package with the class, then use introspection.
+     *
+     * The mbean resource will be created.
+     *
+     * @param type Class name or the type key used in the descriptor.
+     * @throws MBeanException
+     * @throws RuntimeOperationsException
+     */
+    // not used
+//    public BaseModelMBean( String type )
+//        throws MBeanException, RuntimeOperationsException
+//    {
+//        try {
+//            // This constructor is used from <mlet>, it should create
+//            // the resource
+//            setModeledType(type);
+//        } catch( Throwable ex ) {
+//            log.error( "Error creating mbean ", ex);
+//        }
+//    }
+
+    // not used
+//    public BaseModelMBean( String type, ModelerSource source )
+//        throws MBeanException, RuntimeOperationsException
+//    {
+//        try {
+//            setModeledType(type);
+//        } catch( Throwable ex ) {
+//            log.error( "Error creating mbean ", ex);
+//        }
+//        this.source=source;
+//    }
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    // Information from MBeanRegistration
+    /** Registry we are associated with
+     */
+//    protected Registry registry=null;
+
+    protected ObjectName oname=null;
+
+    /**
+     * Notification broadcaster for attribute changes.
+     */
+    protected BaseNotificationBroadcaster attributeBroadcaster = null;
+
+    /**
+     * Notification broadcaster for general notifications.
+     */
+    protected BaseNotificationBroadcaster generalBroadcaster = null;
+
+    
+    /** Metadata for the mbean instance.
+     */
+    protected ManagedBean managedBean = null;
+
+    /**
+     * The managed resource this MBean is associated with (if any).
+     */
+    protected Object resource = null;
+
+    /** Source object used to read this mbean. Can be used to
+     * persist the mbean
+     */
+    //protected ModelerSource source=null;
+
+    /** Attribute values. XXX That can be stored in the value Field
+     */
+    //protected HashMap attributes=new HashMap();
+
+    // --------------------------------------------------- DynamicMBean Methods
+    // TODO: move to ManagedBean
+    static final Object[] NO_ARGS_PARAM=new Object[0];
+    static final Class[] NO_ARGS_PARAM_SIG=new Class[0];
+    
+    /**
+     * The <code>ModelMBeanInfo</code> object that controls our activity.
+     */
+    protected MBeanInfo info = null;
+    protected String resourceType = null;
+
+    // key: operation val: invoke method
+    //private Hashtable invokeAttMap=new Hashtable();
+
+    /**
+     * Obtain and return the value of a specific attribute of this MBean.
+     *
+     * @param name Name of the requested attribute
+     *
+     * @exception AttributeNotFoundException if this attribute is not
+     *  supported by this MBean
+     * @exception MBeanException if the initializer of an object
+     *  throws an exception
+     * @exception ReflectionException if a Java reflection exception
+     *  occurs when invoking the getter
+     */
+    public Object getAttribute(String name)
+        throws AttributeNotFoundException, MBeanException,
+            ReflectionException {
+        // Validate the input parameters
+        if (name == null)
+            throw new RuntimeOperationsException
+                (new IllegalArgumentException("Attribute name is null"),
+                 "Attribute name is null");
+
+        if( (resource instanceof DynamicMBean) && 
+             ! ( resource instanceof BaseModelMBean )) {
+            return ((DynamicMBean)resource).getAttribute(name);
+        }
+        
+        Method m=managedBean.getGetter(name, this, resource);
+        Object result = null;
+        try {
+            Class declaring=m.getDeclaringClass();
+            // workaround for catalina weird mbeans - the declaring class is BaseModelMBean.
+            // but this is the catalina class.
+            if( declaring.isAssignableFrom(this.getClass()) ) {
+                result = m.invoke(this, NO_ARGS_PARAM );
+            } else {
+                result = m.invoke(resource, NO_ARGS_PARAM );
+            }
+        } catch (InvocationTargetException e) {
+            Throwable t = e.getTargetException();
+            if (t == null)
+                t = e;
+            if (t instanceof RuntimeException)
+                throw new RuntimeOperationsException
+                    ((RuntimeException) t, "Exception invoking method " + name);
+            else if (t instanceof Error)
+                throw new RuntimeErrorException
+                    ((Error) t, "Error invoking method " + name);
+            else
+                throw new MBeanException
+                    (e, "Exception invoking method " + name);
+        } catch (Exception e) {
+            throw new MBeanException
+                (e, "Exception invoking method " + name);
+        }
+
+        // Return the results of this method invocation
+        // FIXME - should we validate the return type?
+        return (result);
+    }
+
+
+    /**
+     * Obtain and return the values of several attributes of this MBean.
+     *
+     * @param names Names of the requested attributes
+     */
+    public AttributeList getAttributes(String names[]) {
+
+        // Validate the input parameters
+        if (names == null)
+            throw new RuntimeOperationsException
+                (new IllegalArgumentException("Attribute names list is null"),
+                 "Attribute names list is null");
+
+        // Prepare our response, eating all exceptions
+        AttributeList response = new AttributeList();
+        for (int i = 0; i < names.length; i++) {
+            try {
+                response.add(new Attribute(names[i],getAttribute(names[i])));
+            } catch (Exception e) {
+                ; // Not having a particular attribute in the response
+                ; // is the indication of a getter problem
+            }
+        }
+        return (response);
+
+    }
+
+    public void setManagedBean(ManagedBean managedBean) {
+        this.managedBean = managedBean;
+    }
+
+    /**
+     * Return the <code>MBeanInfo</code> object for this MBean.
+     */
+    public MBeanInfo getMBeanInfo() {
+        // XXX Why do we have to clone ?
+        if( info== null ) return null;
+        return ((MBeanInfo) info.clone());
+    }
+
+
+    /**
+     * Invoke a particular method on this MBean, and return any returned
+     * value.
+     *
+     * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation will
+     * attempt to invoke this method on the MBean itself, or (if not
+     * available) on the managed resource object associated with this
+     * MBean.</p>
+     *
+     * @param name Name of the operation to be invoked
+     * @param params Array containing the method parameters of this operation
+     * @param signature Array containing the class names representing
+     *  the signature of this operation
+     *
+     * @exception MBeanException if the initializer of an object
+     *  throws an exception
+     * @exception ReflectioNException if a Java reflection exception
+     *  occurs when invoking a method
+     */
+    public Object invoke(String name, Object params[], String signature[])
+        throws MBeanException, ReflectionException 
+    {
+        if( (resource instanceof DynamicMBean) && 
+             ! ( resource instanceof BaseModelMBean )) {
+            return ((DynamicMBean)resource).invoke(name, params, signature);
+        }
+    
+        // Validate the input parameters
+        if (name == null)
+            throw new RuntimeOperationsException
+                (new IllegalArgumentException("Method name is null"),
+                 "Method name is null");
+
+        if( log.isDebugEnabled()) log.debug("Invoke " + name);
+	MethodKey mkey = new MethodKey(name, signature);
+        Method method= managedBean.getInvoke(name, params, signature, this, resource);
+        
+        // Invoke the selected method on the appropriate object
+        Object result = null;
+        try {
+            if( method.getDeclaringClass().isAssignableFrom( this.getClass()) ) {
+                result = method.invoke(this, params );
+            } else {
+                result = method.invoke(resource, params);
+            }
+        } catch (InvocationTargetException e) {
+            Throwable t = e.getTargetException();
+            log.error("Exception invoking method " + name , t );
+            if (t == null)
+                t = e;
+            if (t instanceof RuntimeException)
+                throw new RuntimeOperationsException
+                    ((RuntimeException) t, "Exception invoking method " + name);
+            else if (t instanceof Error)
+                throw new RuntimeErrorException
+                    ((Error) t, "Error invoking method " + name);
+            else
+                throw new MBeanException
+                    ((Exception)t, "Exception invoking method " + name);
+        } catch (Exception e) {
+            log.error("Exception invoking method " + name , e );
+            throw new MBeanException
+                (e, "Exception invoking method " + name);
+        }
+
+        // Return the results of this method invocation
+        // FIXME - should we validate the return type?
+        return (result);
+
+    }
+
+    static Class getAttributeClass(String signature)
+        throws ReflectionException
+    {
+        if (signature.equals(Boolean.TYPE.getName()))
+            return Boolean.TYPE;
+        else if (signature.equals(Byte.TYPE.getName()))
+            return Byte.TYPE;
+        else if (signature.equals(Character.TYPE.getName()))
+            return Character.TYPE;
+        else if (signature.equals(Double.TYPE.getName()))
+            return Double.TYPE;
+        else if (signature.equals(Float.TYPE.getName()))
+            return Float.TYPE;
+        else if (signature.equals(Integer.TYPE.getName()))
+            return Integer.TYPE;
+        else if (signature.equals(Long.TYPE.getName()))
+            return Long.TYPE;
+        else if (signature.equals(Short.TYPE.getName()))
+            return Short.TYPE;
+        else {
+            try {
+                ClassLoader cl=Thread.currentThread().getContextClassLoader();
+                if( cl!=null )
+                    return cl.loadClass(signature); 
+            } catch( ClassNotFoundException e ) {
+            }
+            try {
+                return Class.forName(signature);
+            } catch (ClassNotFoundException e) {
+                throw new ReflectionException
+                    (e, "Cannot find Class for " + signature);
+            }
+        }
+    }
+
+    /**
+     * Set the value of a specific attribute of this MBean.
+     *
+     * @param attribute The identification of the attribute to be set
+     *  and the new value
+     *
+     * @exception AttributeNotFoundException if this attribute is not
+     *  supported by this MBean
+     * @exception MBeanException if the initializer of an object
+     *  throws an exception
+     * @exception ReflectionException if a Java reflection exception
+     *  occurs when invoking the getter
+     */
+    public void setAttribute(Attribute attribute)
+        throws AttributeNotFoundException, MBeanException,
+        ReflectionException
+    {
+        if( log.isDebugEnabled() )
+            log.debug("Setting attribute " + this + " " + attribute );
+
+        if( (resource instanceof DynamicMBean) && 
+             ! ( resource instanceof BaseModelMBean )) {
+            try {
+                ((DynamicMBean)resource).setAttribute(attribute);
+            } catch (InvalidAttributeValueException e) {
+                throw new MBeanException(e);                
+            }
+            return;
+        }
+        
+        // Validate the input parameters
+        if (attribute == null)
+            throw new RuntimeOperationsException
+                (new IllegalArgumentException("Attribute is null"),
+                 "Attribute is null");
+
+        String name = attribute.getName();
+        Object value = attribute.getValue();
+
+        if (name == null)
+            throw new RuntimeOperationsException
+                (new IllegalArgumentException("Attribute name is null"),
+                 "Attribute name is null");
+
+        Object oldValue=null;
+        //if( getAttMap.get(name) != null )
+        //    oldValue=getAttribute( name );
+
+        Method m=managedBean.getSetter(name,this,resource);
+
+        try {
+            if( m.getDeclaringClass().isAssignableFrom( this.getClass()) ) {
+                m.invoke(this, new Object[] { value });
+            } else {
+                m.invoke(resource, new Object[] { value });
+            }
+        } catch (InvocationTargetException e) {
+            Throwable t = e.getTargetException();
+            if (t == null)
+                t = e;
+            if (t instanceof RuntimeException)
+                throw new RuntimeOperationsException
+                    ((RuntimeException) t, "Exception invoking method " + name);
+            else if (t instanceof Error)
+                throw new RuntimeErrorException
+                    ((Error) t, "Error invoking method " + name);
+            else
+                throw new MBeanException
+                    (e, "Exception invoking method " + name);
+        } catch (Exception e) {
+            log.error("Exception invoking method " + name , e );
+            throw new MBeanException
+                (e, "Exception invoking method " + name);
+        }
+        try {
+            sendAttributeChangeNotification(new Attribute( name, oldValue),
+                    attribute);
+        } catch(Exception ex) {
+            log.error("Error sending notification " + name, ex);
+        }
+        //attributes.put( name, value );
+//        if( source != null ) {
+//            // this mbean is asscoiated with a source - maybe we want to persist
+//            source.updateField(oname, name, value);
+//        }
+    }
+
+    public String toString() {
+        if( resource==null ) 
+            return "BaseModelMbean[" + resourceType + "]";
+        return resource.toString();
+    }
+
+    /**
+     * Set the values of several attributes of this MBean.
+     *
+     * @param attributes THe names and values to be set
+     *
+     * @return The list of attributes that were set and their new values
+     */
+    public AttributeList setAttributes(AttributeList attributes) {
+        AttributeList response = new AttributeList();
+
+        // Validate the input parameters
+        if (attributes == null)
+            return response;
+        
+        // Prepare and return our response, eating all exceptions
+        String names[] = new String[attributes.size()];
+        int n = 0;
+        Iterator items = attributes.iterator();
+        while (items.hasNext()) {
+            Attribute item = (Attribute) items.next();
+            names[n++] = item.getName();
+            try {
+                setAttribute(item);
+            } catch (Exception e) {
+                ; // Ignore all exceptions
+            }
+        }
+
+        return (getAttributes(names));
+
+    }
+
+
+    // ----------------------------------------------------- ModelMBean Methods
+
+
+    /**
+     * Get the instance handle of the object against which we execute
+     * all methods in this ModelMBean management interface.
+     *
+     * @exception InstanceNotFoundException if the managed resource object
+     *  cannot be found
+     * @exception MBeanException if the initializer of the object throws
+     *  an exception
+     * @exception RuntimeOperationsException if the managed resource or the
+     *  resource type is <code>null</code> or invalid
+     */
+    public Object getManagedResource()
+        throws InstanceNotFoundException, InvalidTargetObjectTypeException,
+        MBeanException, RuntimeOperationsException {
+
+        if (resource == null)
+            throw new RuntimeOperationsException
+                (new IllegalArgumentException("Managed resource is null"),
+                 "Managed resource is null");
+
+        return resource;
+
+    }
+
+
+    /**
+     * Set the instance handle of the object against which we will execute
+     * all methods in this ModelMBean management interface.
+     *
+     * <strike>This method will detect and call "setModelMbean" method. A resource
+     * can implement this method to get a reference to the model mbean.
+     * The reference can be used to send notification and access the
+     * registry.
+     * </strike> The caller can provide the mbean instance or the object name to
+     * the resource, if needed.
+     *
+     * @param resource The resource object to be managed
+     * @param type The type of reference for the managed resource
+     *  ("ObjectReference", "Handle", "IOR", "EJBHandle", or
+     *  "RMIReference")
+     *
+     * @exception InstanceNotFoundException if the managed resource object
+     *  cannot be found
+     * @exception InvalidTargetObjectTypeException if this ModelMBean is
+     *  asked to handle a reference type it cannot deal with
+     * @exception MBeanException if the initializer of the object throws
+     *  an exception
+     * @exception RuntimeOperationsException if the managed resource or the
+     *  resource type is <code>null</code> or invalid
+     */
+    public void setManagedResource(Object resource, String type)
+        throws InstanceNotFoundException, 
+        MBeanException, RuntimeOperationsException
+    {
+        if (resource == null)
+            throw new RuntimeOperationsException
+                (new IllegalArgumentException("Managed resource is null"),
+                 "Managed resource is null");
+
+//        if (!"objectreference".equalsIgnoreCase(type))
+//            throw new InvalidTargetObjectTypeException(type);
+
+        this.resource = resource;
+        this.resourceType = resource.getClass().getName();
+        
+//        // Make the resource aware of the model mbean.
+//        try {
+//            Method m=resource.getClass().getMethod("setModelMBean",
+//                    new Class[] {ModelMBean.class});
+//            if( m!= null ) {
+//                m.invoke(resource, new Object[] {this});
+//            }
+//        } catch( NoSuchMethodException t ) {
+//            // ignore
+//        } catch( Throwable t ) {
+//            log.error( "Can't set model mbean ", t );
+//        }
+    }
+
+
+    /**
+     * Initialize the <code>ModelMBeanInfo</code> associated with this
+     * <code>ModelMBean</code>.  After the information and associated
+     * descriptors have been customized, the <code>ModelMBean</code> should
+     * be registered with the associated <code>MBeanServer</code>.
+     *
+     * Currently the model can be set after registration. This behavior is
+     * deprecated and won't be supported in future versions.
+     *
+     * @param info The ModelMBeanInfo object to be used by this ModelMBean
+     *
+     * @exception MBeanException If an exception occurs recording this
+     *  ModelMBeanInfo information
+     * @exception RuntimeOperations if the specified parameter is
+     *  <code>null</code> or invalid
+     */
+    public void setMBeanInfo(MBeanInfo info)
+        throws MBeanException, RuntimeOperationsException {
+
+        if (info == null)
+            throw new RuntimeOperationsException
+                (new IllegalArgumentException("ModelMBeanInfo is null"),
+                 "ModelMBeanInfo is null");
+
+//        if (!isModelMBeanInfoValid(info))
+//            throw new RuntimeOperationsException
+//                (new IllegalArgumentException("ModelMBeanInfo is invalid"),
+//                 "ModelMBeanInfo is invalid");
+
+        this.info = (MBeanInfo) info.clone();
+
+    }
+
+
+    // ------------------------------ ModelMBeanNotificationBroadcaster Methods
+
+
+    /**
+     * Add an attribute change notification event listener to this MBean.
+     *
+     * @param listener Listener that will receive event notifications
+     * @param name Name of the attribute of interest, or <code>null</code>
+     *  to indicate interest in all attributes
+     * @param handback Handback object to be sent along with event
+     *  notifications
+     *
+     * @exception IllegalArgumentException if the listener parameter is null
+     */
+    public void addAttributeChangeNotificationListener
+        (NotificationListener listener, String name, Object handback)
+        throws IllegalArgumentException {
+
+        if (listener == null)
+            throw new IllegalArgumentException("Listener is null");
+        if (attributeBroadcaster == null)
+            attributeBroadcaster = new BaseNotificationBroadcaster();
+
+        if( log.isDebugEnabled() )
+            log.debug("addAttributeNotificationListener " + listener);
+
+        BaseAttributeFilter filter = new BaseAttributeFilter(name);
+        attributeBroadcaster.addNotificationListener
+            (listener, filter, handback);
+
+    }
+
+
+    /**
+     * Remove an attribute change notification event listener from
+     * this MBean.
+     *
+     * @param listener The listener to be removed
+     * @param name The attribute name for which no more events are required
+     *
+     *
+     * @exception ListenerNotFoundException if this listener is not
+     *  registered in the MBean
+     */
+    public void removeAttributeChangeNotificationListener
+        (NotificationListener listener, String name)
+        throws ListenerNotFoundException {
+
+        if (listener == null)
+            throw new IllegalArgumentException("Listener is null");
+        if (attributeBroadcaster == null)
+            attributeBroadcaster = new BaseNotificationBroadcaster();
+
+        // FIXME - currently this removes *all* notifications for this listener
+        attributeBroadcaster.removeNotificationListener(listener);
+
+    }
+
+
+    /**
+     * Remove an attribute change notification event listener from
+     * this MBean.
+     *
+     * @param listener The listener to be removed
+     * @param attributeName The attribute name for which no more events are required
+     * @param handback Handback object to be sent along with event
+     *  notifications
+     *
+     *
+     * @exception ListenerNotFoundException if this listener is not
+     *  registered in the MBean
+     */
+    public void removeAttributeChangeNotificationListener
+        (NotificationListener listener, String attributeName, Object handback)
+        throws ListenerNotFoundException {
+
+        removeAttributeChangeNotificationListener(listener, attributeName);
+
+    }
+
+
+    /**
+     * Send an <code>AttributeChangeNotification</code> to all registered
+     * listeners.
+     *
+     * @param notification The <code>AttributeChangeNotification</code>
+     *  that will be passed
+     *
+     * @exception MBeanException if an object initializer throws an
+     *  exception
+     * @exception RuntimeOperationsException wraps IllegalArgumentException
+     *  when the specified notification is <code>null</code> or invalid
+     */
+    public void sendAttributeChangeNotification
+        (AttributeChangeNotification notification)
+        throws MBeanException, RuntimeOperationsException {
+
+        if (notification == null)
+            throw new RuntimeOperationsException
+                (new IllegalArgumentException("Notification is null"),
+                 "Notification is null");
+        if (attributeBroadcaster == null)
+            return; // This means there are no registered listeners
+        if( log.isDebugEnabled() )
+            log.debug( "AttributeChangeNotification " + notification );
+        attributeBroadcaster.sendNotification(notification);
+
+    }
+
+
+    /**
+     * Send an <code>AttributeChangeNotification</code> to all registered
+     * listeners.
+     *
+     * @param oldValue The original value of the <code>Attribute</code>
+     * @param newValue The new value of the <code>Attribute</code>
+     *
+     * @exception MBeanException if an object initializer throws an
+     *  exception
+     * @exception RuntimeOperationsException wraps IllegalArgumentException
+     *  when the specified notification is <code>null</code> or invalid
+     */
+    public void sendAttributeChangeNotification
+        (Attribute oldValue, Attribute newValue)
+        throws MBeanException, RuntimeOperationsException {
+
+        // Calculate the class name for the change notification
+        String type = null;
+        if (newValue.getValue() != null)
+            type = newValue.getValue().getClass().getName();
+        else if (oldValue.getValue() != null)
+            type = oldValue.getValue().getClass().getName();
+        else
+            return;  // Old and new are both null == no change
+
+        AttributeChangeNotification notification =
+            new AttributeChangeNotification
+            (this, 1, System.currentTimeMillis(),
+             "Attribute value has changed",
+             oldValue.getName(), type,
+             oldValue.getValue(), newValue.getValue());
+        sendAttributeChangeNotification(notification);
+
+    }
+
+
+
+
+    /**
+     * Send a <code>Notification</code> to all registered listeners as a
+     * <code>jmx.modelmbean.general</code> notification.
+     *
+     * @param notification The <code>Notification</code> that will be passed
+     *
+     * @exception MBeanException if an object initializer throws an
+     *  exception
+     * @exception RuntimeOperationsException wraps IllegalArgumentException
+     *  when the specified notification is <code>null</code> or invalid
+     */
+    public void sendNotification(Notification notification)
+        throws MBeanException, RuntimeOperationsException {
+
+        if (notification == null)
+            throw new RuntimeOperationsException
+                (new IllegalArgumentException("Notification is null"),
+                 "Notification is null");
+        if (generalBroadcaster == null)
+            return; // This means there are no registered listeners
+        generalBroadcaster.sendNotification(notification);
+
+    }
+
+
+    /**
+     * Send a <code>Notification</code> which contains the specified string
+     * as a <code>jmx.modelmbean.generic</code> notification.
+     *
+     * @param message The message string to be passed
+     *
+     * @exception MBeanException if an object initializer throws an
+     *  exception
+     * @exception RuntimeOperationsException wraps IllegalArgumentException
+     *  when the specified notification is <code>null</code> or invalid
+     */
+    public void sendNotification(String message)
+        throws MBeanException, RuntimeOperationsException {
+
+        if (message == null)
+            throw new RuntimeOperationsException
+                (new IllegalArgumentException("Message is null"),
+                 "Message is null");
+        Notification notification = new Notification
+            ("jmx.modelmbean.generic", this, 1, message);
+        sendNotification(notification);
+
+    }
+
+
+
+
+    // ---------------------------------------- NotificationBroadcaster Methods
+
+
+    /**
+     * Add a notification event listener to this MBean.
+     *
+     * @param listener Listener that will receive event notifications
+     * @param filter Filter object used to filter event notifications
+     *  actually delivered, or <code>null</code> for no filtering
+     * @param handback Handback object to be sent along with event
+     *  notifications
+     *
+     * @exception IllegalArgumentException if the listener parameter is null
+     */
+    public void addNotificationListener(NotificationListener listener,
+                                        NotificationFilter filter,
+                                        Object handback)
+        throws IllegalArgumentException {
+
+        if (listener == null)
+            throw new IllegalArgumentException("Listener is null");
+
+        if( log.isDebugEnabled() ) log.debug("addNotificationListener " + listener);
+
+        if (generalBroadcaster == null)
+            generalBroadcaster = new BaseNotificationBroadcaster();
+        generalBroadcaster.addNotificationListener
+            (listener, filter, handback);
+
+        // We'll send the attribute change notifications to all listeners ( who care )
+        // The normal filtering can be used.
+        // The problem is that there is no other way to add attribute change listeners
+        // to a model mbean ( AFAIK ). I suppose the spec should be fixed.
+        if (attributeBroadcaster == null)
+            attributeBroadcaster = new BaseNotificationBroadcaster();
+
+        if( log.isDebugEnabled() )
+            log.debug("addAttributeNotificationListener " + listener);
+
+        attributeBroadcaster.addNotificationListener
+                (listener, filter, handback);
+    }
+
+
+    /**
+     * Return an <code>MBeanNotificationInfo</code> object describing the
+     * notifications sent by this MBean.
+     */
+    public MBeanNotificationInfo[] getNotificationInfo() {
+
+        // Acquire the set of application notifications
+        MBeanNotificationInfo current[] = info.getNotifications();
+        if (current == null)
+            current = new MBeanNotificationInfo[0];
+        MBeanNotificationInfo response[] =
+            new MBeanNotificationInfo[current.length + 2];
+ //       Descriptor descriptor = null;
+
+        // Fill in entry for general notifications
+//        descriptor = new DescriptorSupport
+//            (new String[] { "name=GENERIC",
+//                            "descriptorType=notification",
+//                            "log=T",
+//                            "severity=5",
+//                            "displayName=jmx.modelmbean.generic" });
+        response[0] = new MBeanNotificationInfo
+            (new String[] { "jmx.modelmbean.generic" },
+             "GENERIC",
+             "Text message notification from the managed resource");
+             //descriptor);
+
+        // Fill in entry for attribute change notifications
+//        descriptor = new DescriptorSupport
+//            (new String[] { "name=ATTRIBUTE_CHANGE",
+//                            "descriptorType=notification",
+//                            "log=T",
+//                            "severity=5",
+//                            "displayName=jmx.attribute.change" });
+        response[1] = new MBeanNotificationInfo
+            (new String[] { "jmx.attribute.change" },
+             "ATTRIBUTE_CHANGE",
+             "Observed MBean attribute value has changed");
+             //descriptor);
+
+        // Copy remaining notifications as reported by the application
+        System.arraycopy(current, 0, response, 2, current.length);
+        return (response);
+
+    }
+
+
+    /**
+     * Remove a notification event listener from this MBean.
+     *
+     * @param listener The listener to be removed (any and all registrations
+     *  for this listener will be eliminated)
+     *
+     * @exception ListenerNotFoundException if this listener is not
+     *  registered in the MBean
+     */
+    public void removeNotificationListener(NotificationListener listener)
+        throws ListenerNotFoundException {
+
+        if (listener == null)
+            throw new IllegalArgumentException("Listener is null");
+        if (generalBroadcaster == null)
+            generalBroadcaster = new BaseNotificationBroadcaster();
+        generalBroadcaster.removeNotificationListener(listener);
+
+
+    }
+
+
+    /**
+     * Remove a notification event listener from this MBean.
+     *
+     * @param listener The listener to be removed (any and all registrations
+     *  for this listener will be eliminated)
+     * @param handback Handback object to be sent along with event
+     *  notifications
+     *
+     * @exception ListenerNotFoundException if this listener is not
+     *  registered in the MBean
+     */
+    public void removeNotificationListener(NotificationListener listener,
+                                           Object handback)
+        throws ListenerNotFoundException {
+
+        removeNotificationListener(listener);
+
+    }
+
+
+    /**
+     * Remove a notification event listener from this MBean.
+     *
+     * @param listener The listener to be removed (any and all registrations
+     *  for this listener will be eliminated)
+     * @param filter Filter object used to filter event notifications
+     *  actually delivered, or <code>null</code> for no filtering
+     * @param handback Handback object to be sent along with event
+     *  notifications
+     *
+     * @exception ListenerNotFoundException if this listener is not
+     *  registered in the MBean
+     */
+    public void removeNotificationListener(NotificationListener listener,
+                                           NotificationFilter filter,
+                                           Object handback)
+        throws ListenerNotFoundException {
+
+        removeNotificationListener(listener);
+
+    }
+
+
+    // ------------------------------------------------ PersistentMBean Methods
+
+
+    /**
+     * Instantiates this MBean instance from data found in the persistent
+     * store.  The data loaded could include attribute and operation values.
+     * This method should be called during construction or initialization
+     * of the instance, and before the MBean is registered with the
+     * <code>MBeanServer</code>.
+     *
+     * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation does
+     * not support persistence.</p>
+     *
+     * @exception InstanceNotFoundException if the managed resource object
+     *  cannot be found
+     * @exception MBeanException if the initializer of the object throws
+     *  an exception
+     * @exception RuntimeOperationsException if an exception is reported
+     *  by the persistence mechanism
+     */
+//    public void load() throws InstanceNotFoundException,
+//        MBeanException, RuntimeOperationsException {
+//        // XXX If a context was set, use it to load the data
+//        throw new MBeanException
+//            (new IllegalStateException("Persistence is not supported"),
+//             "Persistence is not supported");
+//
+//    }
+
+
+    /**
+     * Capture the current state of this MBean instance and write it out
+     * to the persistent store.  The state stored could include attribute
+     * and operation values.  If one of these methods of persistence is not
+     * supported, a "service not found" exception will be thrown.
+     *
+     * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation does
+     * not support persistence.</p>
+     *
+     * @exception InstanceNotFoundException if the managed resource object
+     *  cannot be found
+     * @exception MBeanException if the initializer of the object throws
+     *  an exception, or persistence is not supported
+     * @exception RuntimeOperationsException if an exception is reported
+     *  by the persistence mechanism
+     */
+//    public void store() throws InstanceNotFoundException,
+//        MBeanException, RuntimeOperationsException {
+//
+//        // XXX if a context was set, use it to store the data
+//        throw new MBeanException
+//            (new IllegalStateException("Persistence is not supported"),
+//             "Persistence is not supported");
+//
+//    }
+
+    // --------------------  BaseModelMBean methods --------------------
+
+    /** Set the type of the mbean. This is used as a key to locate
+     * the description in the Registry.
+     *
+     * @param type the type of classname of the modeled object
+     */
+//    void setModeledType( String type ) {
+//        initModelInfo(type);
+//        createResource();
+//    }
+    /** Set the type of the mbean. This is used as a key to locate
+     * the description in the Registry.
+     *
+     * @param type the type of classname of the modeled object
+     */
+//    void initModelInfo( String type ) {
+//        try {
+//            if( log.isDebugEnabled())
+//                log.debug("setModeledType " + type);
+//
+//            log.debug( "Set model Info " + type);
+//            if(type==null) {
+//                return;
+//            }
+//            resourceType=type;
+//            //Thread.currentThread().setContextClassLoader(BaseModelMBean.class.getClassLoader());
+//            Class c=null;
+//            try {
+//                c=Class.forName( type);
+//            } catch( Throwable t ) {
+//                log.debug( "Error creating class " + t);
+//            }
+//
+//            // The class c doesn't need to exist
+//            ManagedBean descriptor=getRegistry().findManagedBean(c, type);
+//            if( descriptor==null ) 
+//                return;
+//            this.setModelMBeanInfo(descriptor.createMBeanInfo());
+//        } catch( Throwable ex) {
+//            log.error( "TCL: " + Thread.currentThread().getContextClassLoader(),
+//                    ex);
+//        }
+//    }
+
+    /** Set the type of the mbean. This is used as a key to locate
+     * the description in the Registry.
+     */
+//    protected void createResource() {
+//        try {
+//            //Thread.currentThread().setContextClassLoader(BaseModelMBean.class.getClassLoader());
+//            Class c=null;
+//            try {
+//                c=Class.forName( resourceType );
+//                resource = c.newInstance();
+//            } catch( Throwable t ) {
+//                log.error( "Error creating class " + t);
+//            }
+//        } catch( Throwable ex) {
+//            log.error( "TCL: " + Thread.currentThread().getContextClassLoader(),
+//                    ex);
+//        }
+//    }
+
+
+    public String getModelerType() {
+        return resourceType;
+    }
+
+    public String getClassName() {
+        return getModelerType();
+    }
+
+    public ObjectName getJmxName() {
+        return oname;
+    }
+
+    public String getObjectName() {
+        if (oname != null) {
+            return oname.toString();
+        } else {
+            return null;
+        }
+    }
+
+//    public void setRegistry(Registry registry) {
+//        this.registry = registry;
+//    }
+//
+//    public Registry getRegistry() {
+//        // XXX Need a better solution - to avoid the static
+//        if( registry == null )
+//            registry=Registry.getRegistry();
+//
+//        return registry;
+//    }
+
+    // ------------------------------------------------------ Protected Methods
+
+
+    /**
+     * Create and return a default <code>ModelMBeanInfo</code> object.
+     */
+//    protected ModelMBeanInfo createDefaultModelMBeanInfo() {
+//
+//        return (new ModelMBeanInfoSupport(this.getClass().getName(),
+//                                          "Default ModelMBean",
+//                                          null, null, null, null));
+//
+//    }
+
+    /**
+     * Is the specified <code>ModelMBeanInfo</code> instance valid?
+     *
+     * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation
+     * does not check anything, but this method can be overridden
+     * as required.</p>
+     *
+     * @param info The <code>ModelMBeanInfo object to check
+     */
+//    protected boolean isModelMBeanInfoValid(ModelMBeanInfo info) {
+//        return (true);
+//    }
+
+    // -------------------- Registration  --------------------
+    // XXX We can add some method patterns here- like setName() and
+    // setDomain() for code that doesn't implement the Registration
+
+    public ObjectName preRegister(MBeanServer server,
+                                  ObjectName name)
+            throws Exception
+    {
+        if( log.isDebugEnabled())
+            log.debug("preRegister " + resource + " " + name );
+        oname=name;
+        if( resource instanceof MBeanRegistration ) {
+            oname = ((MBeanRegistration)resource).preRegister(server, name );
+        }
+        return oname;
+    }
+
+    public void postRegister(Boolean registrationDone) {
+        if( resource instanceof MBeanRegistration ) {
+            ((MBeanRegistration)resource).postRegister(registrationDone);
+        }
+    }
+
+    public void preDeregister() throws Exception {
+        if( resource instanceof MBeanRegistration ) {
+            ((MBeanRegistration)resource).preDeregister();
+        }
+    }
+
+    public void postDeregister() {
+        if( resource instanceof MBeanRegistration ) {
+            ((MBeanRegistration)resource).postDeregister();
+        }
+    }
+
+    static class MethodKey {
+	private String name;
+	private String[] signature;
+
+	MethodKey(String name, String[] signature) {
+	    this.name = name;
+	    if(signature == null) {
+		signature = new String[0];
+	    }
+	    this.signature = signature;
+	}
+
+	public boolean equals(Object other) {
+	    if(!(other instanceof MethodKey)) {
+		return false;
+	    }
+	    MethodKey omk = (MethodKey)other;
+	    if(!name.equals(omk.name)) {
+		return false;
+	    }
+	    if(signature.length != omk.signature.length) {
+		return false;
+	    }
+	    for(int i=0; i < signature.length; i++) {
+		if(!signature[i].equals(omk.signature[i])) {
+		    return false;
+		}
+	    }
+	    return true;
+	}
+
+	public int hashCode() {
+	    return name.hashCode();
+	}
+    }
+}

Added: tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseNotificationBroadcaster.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseNotificationBroadcaster.java?rev=407661&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseNotificationBroadcaster.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/modeler/BaseNotificationBroadcaster.java Thu May 18 16:27:34 2006
@@ -0,0 +1,264 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.tomcat.util.modeler;
+
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.Notification;
+import javax.management.NotificationBroadcaster;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+
+
+/**
+ * <p>Implementation of <code>NotificationBroadcaster</code> for attribute
+ * change notifications.  This class is used by <code>BaseModelMBean</code> to
+ * handle notifications of attribute change events to interested listeners.
+ *</p>
+ *
+ * @author Craig R. McClanahan
+ * @author Costin Manolache
+ */
+
+public class BaseNotificationBroadcaster implements NotificationBroadcaster {
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The set of registered <code>BaseNotificationBroadcasterEntry</code>
+     * entries.
+     */
+    protected ArrayList entries = new ArrayList();
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Add a notification event listener to this MBean.
+     *
+     * @param listener Listener that will receive event notifications
+     * @param filter Filter object used to filter event notifications
+     *  actually delivered, or <code>null</code> for no filtering
+     * @param handback Handback object to be sent along with event
+     *  notifications
+     *
+     * @exception IllegalArgumentException if the listener parameter is null
+     */
+    public void addNotificationListener(NotificationListener listener,
+                                        NotificationFilter filter,
+                                        Object handback)
+        throws IllegalArgumentException {
+
+        synchronized (entries) {
+
+            // Optimization to coalesce attribute name filters
+            if (filter instanceof BaseAttributeFilter) {
+                BaseAttributeFilter newFilter = (BaseAttributeFilter) filter;
+                Iterator items = entries.iterator();
+                while (items.hasNext()) {
+                    BaseNotificationBroadcasterEntry item =
+                        (BaseNotificationBroadcasterEntry) items.next();
+                    if ((item.listener == listener) &&
+                        (item.filter != null) &&
+                        (item.filter instanceof BaseAttributeFilter) &&
+                        (item.handback == handback)) {
+                        BaseAttributeFilter oldFilter =
+                            (BaseAttributeFilter) item.filter;
+                        String newNames[] = newFilter.getNames();
+                        String oldNames[] = oldFilter.getNames();
+                        if (newNames.length == 0) {
+                            oldFilter.clear();
+                        } else {
+                            if (oldNames.length != 0) {
+                                for (int i = 0; i < newNames.length; i++)
+                                    oldFilter.addAttribute(newNames[i]);
+                            }
+                        }
+                        return;
+                    }
+                }
+            }
+
+            // General purpose addition of a new entry
+            entries.add(new BaseNotificationBroadcasterEntry
+                        (listener, filter, handback));
+        }
+
+    }
+
+
+    /**
+     * Return an <code>MBeanNotificationInfo</code> object describing the
+     * notifications sent by this MBean.
+     */
+    public MBeanNotificationInfo[] getNotificationInfo() {
+
+        return (new MBeanNotificationInfo[0]);
+
+    }
+
+
+    /**
+     * Remove a notification event listener from this MBean.
+     *
+     * @param listener The listener to be removed (any and all registrations
+     *  for this listener will be eliminated)
+     *
+     * @exception ListenerNotFoundException if this listener is not
+     *  registered in the MBean
+     */
+    public void removeNotificationListener(NotificationListener listener)
+        throws ListenerNotFoundException {
+
+        synchronized (entries) {
+            Iterator items = entries.iterator();
+            while (items.hasNext()) {
+                BaseNotificationBroadcasterEntry item =
+                    (BaseNotificationBroadcasterEntry) items.next();
+                if (item.listener == listener)
+                    items.remove();
+            }
+        }
+
+    }
+
+
+    /**
+     * Remove a notification event listener from this MBean.
+     *
+     * @param listener The listener to be removed (any and all registrations
+     *  for this listener will be eliminated)
+     * @param handback Handback object to be sent along with event
+     *  notifications
+     *
+     * @exception ListenerNotFoundException if this listener is not
+     *  registered in the MBean
+     */
+    public void removeNotificationListener(NotificationListener listener,
+                                           Object handback)
+        throws ListenerNotFoundException {
+
+        removeNotificationListener(listener);
+
+    }
+
+
+    /**
+     * Remove a notification event listener from this MBean.
+     *
+     * @param listener The listener to be removed (any and all registrations
+     *  for this listener will be eliminated)
+     * @param filter Filter object used to filter event notifications
+     *  actually delivered, or <code>null</code> for no filtering
+     * @param handback Handback object to be sent along with event
+     *  notifications
+     *
+     * @exception ListenerNotFoundException if this listener is not
+     *  registered in the MBean
+     */
+    public void removeNotificationListener(NotificationListener listener,
+                                           NotificationFilter filter,
+                                           Object handback)
+        throws ListenerNotFoundException {
+
+        removeNotificationListener(listener);
+
+    }
+
+
+    /**
+     * Send the specified notification to all interested listeners.
+     *
+     * @param notification The notification to be sent
+     */
+    public void sendNotification(Notification notification) {
+
+        synchronized (entries) {
+            Iterator items = entries.iterator();
+            while (items.hasNext()) {
+                BaseNotificationBroadcasterEntry item =
+                    (BaseNotificationBroadcasterEntry) items.next();
+                if ((item.filter != null) &&
+                    (!item.filter.isNotificationEnabled(notification)))
+                    continue;
+                item.listener.handleNotification(notification, item.handback);
+            }
+        }
+
+    }
+
+
+    // -------------------- Internal Extensions   --------------------
+
+    // Fast access. First index is the hook type
+    // ( FixedNotificationFilter.getType() ).
+    NotificationListener hooks[][]=new NotificationListener[20][];
+    int hookCount[]=new int[20];
+
+    private synchronized void registerNotifications( FixedNotificationFilter filter ) {
+        String names[]=filter.getNames();
+        Registry reg=Registry.getRegistry();
+        for( int i=0; i<names.length; i++ ) {
+            int code=reg.getId(null, names[i]);
+            if( hooks.length < code ) {
+                // XXX reallocate
+                throw new RuntimeException( "Too many hooks " + code );
+            }
+            NotificationListener listeners[]=hooks[code];
+            if( listeners== null ) {
+
+            }
+
+
+        }
+    }
+
+}
+
+
+/**
+ * Utility class representing a particular registered listener entry.
+ */
+
+class BaseNotificationBroadcasterEntry {
+
+    public BaseNotificationBroadcasterEntry(NotificationListener listener,
+                                            NotificationFilter filter,
+                                            Object handback) {
+        this.listener = listener;
+        this.filter = filter;
+        this.handback = handback;
+    }
+
+    public NotificationFilter filter = null;
+
+    public Object handback = null;
+
+    public NotificationListener listener = null;
+
+}

Added: tomcat/sandbox/java/org/apache/tomcat/util/modeler/ConstructorInfo.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/tomcat/util/modeler/ConstructorInfo.java?rev=407661&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/modeler/ConstructorInfo.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/modeler/ConstructorInfo.java Thu May 18 16:27:34 2006
@@ -0,0 +1,161 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.tomcat.util.modeler;
+
+
+import java.io.Serializable;
+
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanParameterInfo;
+
+
+/**
+ * <p>Internal configuration information for a <code>Constructor</code>
+ * descriptor.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 155428 $ $Date: 2005-02-26 14:12:25 +0100 (sam., 26 févr. 2005) $
+ */
+
+public class ConstructorInfo extends FeatureInfo implements Serializable {
+    static final long serialVersionUID = -5735336213417238238L;
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The <code>ModelMBeanConstructorInfo</code> object that corresponds
+     * to this <code>ConstructorInfo</code> instance.
+     */
+    transient MBeanConstructorInfo info = null;
+    protected String displayName = null;
+    protected ParameterInfo parameters[] = new ParameterInfo[0];
+
+
+    // ------------------------------------------------------------- Properties
+
+    public ConstructorInfo() {
+        System.err.println("CONSTRUCTOR XXXX");
+    }
+
+    /**
+     * Override the <code>description</code> property setter.
+     *
+     * @param description The new description
+     */
+    public void setDescription(String description) {
+        super.setDescription(description);
+        this.info = null;
+    }
+
+
+    /**
+     * Override the <code>name</code> property setter.
+     *
+     * @param name The new name
+     */
+    public void setName(String name) {
+        super.setName(name);
+        this.info = null;
+        System.err.println("Constructor: name");
+    }
+
+
+    /**
+     * The display name of this attribute.
+     */
+    public String getDisplayName() {
+        return (this.displayName);
+    }
+
+    public void setDisplayName(String displayName) {
+        this.displayName = displayName;
+    }
+
+
+    /**
+     * The set of parameters for this constructor.
+     */
+    public ParameterInfo[] getSignature() {
+        return (this.parameters);
+    }
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Add a new parameter to the set of parameters for this constructor.
+     *
+     * @param parameter The new parameter descriptor
+     */
+    public void addParameter(ParameterInfo parameter) {
+
+        synchronized (parameters) {
+            ParameterInfo results[] = new ParameterInfo[parameters.length + 1];
+            System.arraycopy(parameters, 0, results, 0, parameters.length);
+            results[parameters.length] = parameter;
+            parameters = results;
+            this.info = null;
+        }
+
+    }
+
+
+    /**
+     * Create and return a <code>ModelMBeanConstructorInfo</code> object that
+     * corresponds to the attribute described by this instance.
+     */
+    public MBeanConstructorInfo createConstructorInfo() {
+
+        // Return our cached information (if any)
+        if (info != null)
+            return (info);
+
+        // Create and return a new information object
+        ParameterInfo params[] = getSignature();
+        MBeanParameterInfo parameters[] =
+            new MBeanParameterInfo[params.length];
+        for (int i = 0; i < params.length; i++)
+            parameters[i] = params[i].createParameterInfo();
+        info = new MBeanConstructorInfo
+            (getName(), getDescription(), parameters);
+        return (info);
+
+    }
+
+
+    /**
+     * Return a string representation of this constructor descriptor.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer("ConstructorInfo[");
+        sb.append("name=");
+        sb.append(name);
+        sb.append(", description=");
+        sb.append(description);
+        sb.append(", parameters=");
+        sb.append(parameters.length);
+        sb.append("]");
+        return (sb.toString());
+
+    }
+
+
+}

Added: tomcat/sandbox/java/org/apache/tomcat/util/modeler/FeatureInfo.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/tomcat/util/modeler/FeatureInfo.java?rev=407661&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/modeler/FeatureInfo.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/modeler/FeatureInfo.java Thu May 18 16:27:34 2006
@@ -0,0 +1,112 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.tomcat.util.modeler;
+
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * <p>Convenience base class for <code>AttributeInfo</code>,
+ * <code>ConstructorInfo</code>, and <code>OperationInfo</code> classes
+ * that will be used to collect configuration information for the
+ * <code>ModelMBean</code> beans exposed for management.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 155428 $ $Date: 2005-02-26 14:12:25 +0100 (sam., 26 févr. 2005) $
+ */
+
+public class FeatureInfo implements Serializable {
+    static final long serialVersionUID = -911529176124712296L;
+    protected String description = null;
+    //protected List fields = new ArrayList();
+    protected String name = null;
+
+    // ------------------------------------------------------------- Properties
+
+
+    /**
+     * The human-readable description of this feature.
+     */
+    public String getDescription() {
+        return (this.description);
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+
+    /**
+     * The field information for this feature.
+     */
+//    public List getFields() {
+//        return (fields);
+//    }
+
+
+    /**
+     * The name of this feature, which must be unique among features in the
+     * same collection.
+     */
+    public String getName() {
+        return (this.name);
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * <p>Add a new field to the fields associated with the
+     * Descriptor that will be created from this metadata.</p>
+     *
+     * @param field The field to be added
+     */
+//    public void addField(FieldInfo field) {
+//        fields.add(field);
+//    }
+
+
+    // ------------------------------------------------------ Protected Methods
+
+
+    /**
+     * <p>Add the name/value fields that have been stored into the
+     * specified <code>Descriptor</code> instance.</p>
+     *
+     * @param descriptor The <code>Descriptor</code> to add fields to
+     */
+//    protected void addFields(Descriptor descriptor) {
+//
+//        Iterator items = getFields().iterator();
+//        while (items.hasNext()) {
+//            FieldInfo item = (FieldInfo) items.next();
+//            descriptor.setField(item.getName(), item.getValue());
+//        }
+//
+//    }
+
+
+}

Added: tomcat/sandbox/java/org/apache/tomcat/util/modeler/FixedNotificationFilter.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/tomcat/util/modeler/FixedNotificationFilter.java?rev=407661&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/modeler/FixedNotificationFilter.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/modeler/FixedNotificationFilter.java Thu May 18 16:27:34 2006
@@ -0,0 +1,94 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.tomcat.util.modeler;
+
+
+import java.util.HashSet;
+
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+
+
+/**
+ * Special NotificationFilter that allows modeler to optimize its notifications.
+ *
+ * This class is immutable - after you construct it it'll filter based on
+ * a fixed set of notification names.
+ *
+ * The JMX specification requires the filters to be called before the
+ * notifications are sent. We can call this filter well in advance, when
+ * the listener is added. Based on the result we can maintain separate
+ * channels for each notification - and reduce the overhead.
+ *
+ * @author Costin Manolache
+ */
+public class FixedNotificationFilter implements NotificationFilter {
+
+    /**
+     * The set of attribute names that are accepted by this filter.  If this
+     * list is empty, all attribute names are accepted.
+     */
+    private HashSet names = new HashSet();
+    String namesA[]=null;
+
+    /**
+     * Construct a new filter that accepts only the specified notification
+     * names.
+     *
+     * @param names Names of the notification types
+     */
+    public FixedNotificationFilter(String names[]) {
+        super();
+    }
+
+    /**
+     * Return the set of names that are accepted by this filter.  If this
+     * filter accepts all attribute names, a zero length array will be
+     * returned.
+     */
+    public String[] getNames() {
+        synchronized (names) {
+            return ((String[]) names.toArray(new String[names.size()]));
+        }
+    }
+
+
+    /**
+     * <p>Test whether notification enabled for this event.
+     * Return true if:</p>
+     * <ul>
+     * <li>Either the set of accepted names is empty (implying that all
+     *     attribute names are of interest) or the set of accepted names
+     *     includes the name of the attribute in this notification</li>
+     * </ul>
+     */
+    public boolean isNotificationEnabled(Notification notification) {
+
+        if (notification == null)
+            return (false);
+        synchronized (names) {
+            if (names.size() < 1)
+                return (true);
+            else
+                return (names.contains(notification.getType()));
+        }
+
+    }
+
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message