You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2006/05/19 01:27:35 UTC

svn commit: r407661 [2/3] - in /tomcat/sandbox/java/org/apache/tomcat/util/modeler: ./ modules/

Added: tomcat/sandbox/java/org/apache/tomcat/util/modeler/ManagedBean.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/tomcat/util/modeler/ManagedBean.java?rev=407661&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/modeler/ManagedBean.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/modeler/ManagedBean.java Thu May 18 16:27:34 2006
@@ -0,0 +1,641 @@
+/*
+ * 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.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.ReflectionException;
+import javax.management.RuntimeOperationsException;
+import javax.management.ServiceNotFoundException;
+//import javax.management.modelmbean.InvalidTargetObjectTypeException;
+
+
+/**
+ * <p>Internal configuration information for a managed bean (MBean)
+ * descriptor.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 383268 $ $Date: 2006-03-05 03:02:01 +0100 (dim., 05 mars 2006) $
+ */
+
+public class ManagedBean implements java.io.Serializable
+{
+    private static final String BASE_MBEAN = "org.apache.tomcat.util.modeler.BaseModelMBean";
+    // ----------------------------------------------------- Instance Variables
+    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 corresponds
+     * to this <code>ManagedBean</code> instance.
+     */
+    transient MBeanInfo info = null;
+    // Map<AttributeInfo>
+    private Map attributes = new HashMap();
+    //Map<OperationInfo>
+    private Map operations = new HashMap();
+    
+    protected String className = BASE_MBEAN;
+    //protected ConstructorInfo constructors[] = new ConstructorInfo[0];
+    protected String description = null;
+    protected String domain = null;
+    protected String group = null;
+    protected String name = null;
+
+    //protected List fields = new ArrayList();
+    protected NotificationInfo notifications[] = new NotificationInfo[0];
+    protected String type = null;
+
+    /** Constructor. Will add default attributes. 
+     *  
+     */ 
+    public ManagedBean() {
+        AttributeInfo ai=new AttributeInfo();
+        ai.setName("modelerType");
+        ai.setDescription("Type of the modeled resource. Can be set only once");
+        ai.setType("java.lang.String");
+        ai.setWriteable(false);
+        addAttribute(ai);
+    }
+    
+    // ------------------------------------------------------------- Properties
+
+
+    /**
+     * The collection of attributes for this MBean.
+     */
+    public AttributeInfo[] getAttributes() {
+        AttributeInfo result[] = new AttributeInfo[attributes.size()];
+        attributes.values().toArray(result);
+        return result;
+    }
+
+
+    /**
+     * The fully qualified name of the Java class of the MBean
+     * described by this descriptor.  If not specified, the standard JMX
+     * class (<code>javax.management.modelmbean.RequiredModeLMBean</code>)
+     * will be utilized.
+     */
+    public String getClassName() {
+        return (this.className);
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+        this.info = null;
+    }
+
+
+//    /**
+//     * The collection of constructors for this MBean.
+//     */
+//    public ConstructorInfo[] getConstructors() {
+//        return (this.constructors);
+//    }
+
+
+    /**
+     * The human-readable description of this MBean.
+     */
+    public String getDescription() {
+        return (this.description);
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+        this.info = null;
+    }
+
+
+    /**
+     * The (optional) <code>ObjectName</code> domain in which this MBean
+     * should be registered in the MBeanServer.
+     */
+    public String getDomain() {
+        return (this.domain);
+    }
+
+    public void setDomain(String domain) {
+        this.domain = domain;
+    }
+
+
+    /**
+     * <p>Return a <code>List</code> of the {@link FieldInfo} objects for
+     * the name/value pairs that should be
+     * added to the Descriptor created from this metadata.</p>
+     */
+//    public List getFields() {
+//        return (this.fields);
+//    }
+//
+
+    /**
+     * The (optional) group to which this MBean belongs.
+     */
+    public String getGroup() {
+        return (this.group);
+    }
+
+    public void setGroup(String group) {
+        this.group = group;
+    }
+
+
+    /**
+     * The name of this managed bean, which must be unique among all
+     * MBeans managed by a particular MBeans server.
+     */
+    public String getName() {
+        return (this.name);
+    }
+
+    public void setName(String name) {
+        this.name = name;
+        this.info = null;
+    }
+
+
+    /**
+     * The collection of notifications for this MBean.
+     */
+    public NotificationInfo[] getNotifications() {
+        return (this.notifications);
+    }
+
+
+    /**
+     * The collection of operations for this MBean.
+     */
+    public OperationInfo[] getOperations() {
+        OperationInfo[] result = new OperationInfo[operations.size()];
+        operations.values().toArray(result);
+        return result;
+    }
+
+
+    /**
+     * The fully qualified name of the Java class of the resource
+     * implementation class described by the managed bean described
+     * by this descriptor.
+     */
+    public String getType() {
+        return (this.type);
+    }
+
+    public void setType(String type) {
+        this.type = type;
+        this.info = null;
+    }
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Add a new attribute to the set of attributes for this MBean.
+     *
+     * @param attribute The new attribute descriptor
+     */
+    public void addAttribute(AttributeInfo attribute) {
+        attributes.put(attribute.getName(), attribute);
+    }
+
+
+    /**
+     * Add a new constructor to the set of constructors for this MBean.
+     *
+     * @param constructor The new constructor descriptor
+     */
+//    public void addConstructor(ConstructorInfo constructor) {
+//
+//        synchronized (constructors) {
+//            ConstructorInfo results[] =
+//                new ConstructorInfo[constructors.length + 1];
+//            System.arraycopy(constructors, 0, results, 0, constructors.length);
+//            results[constructors.length] = constructor;
+//            constructors = results;
+//            this.info = null;
+//        }
+//
+//    }
+
+
+    /**
+     * <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);
+//    }
+
+
+    /**
+     * Add a new notification to the set of notifications for this MBean.
+     *
+     * @param notification The new notification descriptor
+     */
+    public void addNotification(NotificationInfo notification) {
+
+        synchronized (notifications) {
+            NotificationInfo results[] =
+                new NotificationInfo[notifications.length + 1];
+            System.arraycopy(notifications, 0, results, 0,
+                             notifications.length);
+            results[notifications.length] = notification;
+            notifications = results;
+            this.info = null;
+        }
+
+    }
+
+
+    /**
+     * Add a new operation to the set of operations for this MBean.
+     *
+     * @param operation The new operation descriptor
+     */
+    public void addOperation(OperationInfo operation) {
+        operations.put(operation.getName(), operation);
+    }
+
+
+    /**
+     * Create and return a <code>ModelMBean</code> that has been
+     * preconfigured with the <code>ModelMBeanInfo</code> information
+     * for this managed bean, but is not associated with any particular
+     * managed resource.  The returned <code>ModelMBean</code> will
+     * <strong>NOT</strong> have been registered with our
+     * <code>MBeanServer</code>.
+     *
+     * @exception InstanceNotFoundException if the managed resource
+     *  object cannot be found
+     * @exception InvalidTargetObjectTypeException if our MBean cannot
+     *  handle object references (should never happen)
+     * @exception MBeanException if a problem occurs instantiating the
+     *  <code>ModelMBean</code> instance
+     * @exception RuntimeOperationsException if a JMX runtime error occurs
+     */
+    public DynamicMBean createMBean()
+        throws InstanceNotFoundException,
+        MBeanException, RuntimeOperationsException {
+
+        return (createMBean(null));
+
+    }
+
+
+    /**
+     * Create and return a <code>ModelMBean</code> that has been
+     * preconfigured with the <code>ModelMBeanInfo</code> information
+     * for this managed bean, and is associated with the specified
+     * managed object instance.  The returned <code>ModelMBean</code>
+     * will <strong>NOT</strong> have been registered with our
+     * <code>MBeanServer</code>.
+     *
+     * @param instance Instanced of the managed object, or <code>null</code>
+     *  for no associated instance
+     *
+     * @exception InstanceNotFoundException if the managed resource
+     *  object cannot be found
+     * @exception InvalidTargetObjectTypeException if our MBean cannot
+     *  handle object references (should never happen)
+     * @exception MBeanException if a problem occurs instantiating the
+     *  <code>ModelMBean</code> instance
+     * @exception RuntimeOperationsException if a JMX runtime error occurs
+     */
+    public DynamicMBean createMBean(Object instance)
+        throws InstanceNotFoundException,
+        MBeanException, RuntimeOperationsException {
+
+        BaseModelMBean mbean = null;
+        MBeanInfo minfo = createMBeanInfo();
+
+        // Load the ModelMBean implementation class
+        if(getClassName().equals(BASE_MBEAN)) {
+            // Skip introspection
+            mbean = new BaseModelMBean();
+        } else {
+            Class clazz = null;
+            Exception ex = null;
+            try {
+                clazz = Class.forName(getClassName());
+            } catch (Exception e) {
+            }
+          
+            if( clazz==null ) {  
+                try {
+                    ClassLoader cl= Thread.currentThread().getContextClassLoader();
+                    if ( cl != null)
+                        clazz= cl.loadClass(getClassName());
+                } catch (Exception e) {
+                    ex=e;
+                }
+            }
+    
+            if( clazz==null) { 
+                throw new MBeanException
+                    (ex, "Cannot load ModelMBean class " + getClassName());
+            }
+            try {
+                // Stupid - this will set the default minfo first....
+                mbean = (BaseModelMBean) clazz.newInstance();
+            } catch (RuntimeOperationsException e) {
+                throw e;
+            } catch (Exception e) {
+                throw new MBeanException
+                    (e, "Cannot instantiate ModelMBean of class " +
+                     getClassName());
+            }
+        }
+        
+        mbean.setManagedBean(this);
+        
+        // Create a new ModelMBean instance
+        try {
+            mbean.setMBeanInfo(minfo);
+        } catch (MBeanException e) {
+            throw e;
+        } catch (RuntimeOperationsException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new MBeanException
+                (e, "Cannot instantiate ModelMBean of class " +
+                 getClassName());
+        }
+
+        // Set the managed resource (if any)
+        try {
+            if (instance != null)
+                mbean.setManagedResource(instance, "ObjectReference");
+        } catch (InstanceNotFoundException e) {
+            throw e;
+        }
+        return (mbean);
+
+    }
+
+
+    /**
+     * Create and return a <code>ModelMBeanInfo</code> object that
+     * describes this entire managed bean.
+     */
+    MBeanInfo createMBeanInfo() {
+
+        // Return our cached information (if any)
+        if (info != null)
+            return (info);
+
+        // Create subordinate information descriptors as required
+        AttributeInfo attrs[] = getAttributes();
+        MBeanAttributeInfo attributes[] =
+            new MBeanAttributeInfo[attrs.length];
+        for (int i = 0; i < attrs.length; i++)
+            attributes[i] = attrs[i].createAttributeInfo();
+
+        OperationInfo opers[] = getOperations();
+        MBeanOperationInfo operations[] =
+            new MBeanOperationInfo[opers.length];
+        for (int i = 0; i < opers.length; i++)
+            operations[i] = opers[i].createOperationInfo();
+
+
+//        ConstructorInfo consts[] = getConstructors();
+//        ModelMBeanConstructorInfo constructors[] =
+//            new ModelMBeanConstructorInfo[consts.length];
+//        for (int i = 0; i < consts.length; i++)
+//            constructors[i] = consts[i].createConstructorInfo();
+        
+        NotificationInfo notifs[] = getNotifications();
+        MBeanNotificationInfo notifications[] =
+            new MBeanNotificationInfo[notifs.length];
+        for (int i = 0; i < notifs.length; i++)
+            notifications[i] = notifs[i].createNotificationInfo();
+
+        
+        // Construct and return a new ModelMBeanInfo object
+        info = new MBeanInfo(getClassName(), 
+                             getDescription(),
+                             attributes, 
+                             new MBeanConstructorInfo[] {}, 
+                             operations, 
+                             notifications);
+//        try {
+//            Descriptor descriptor = info.getMBeanDescriptor();
+//            Iterator fields = getFields().iterator();
+//            while (fields.hasNext()) {
+//                FieldInfo field = (FieldInfo) fields.next();
+//                descriptor.setField(field.getName(), field.getValue());
+//            }
+//            info.setMBeanDescriptor(descriptor);
+//        } catch (MBeanException e) {
+//            ;
+//        }
+
+        return (info);
+
+    }
+
+
+    /**
+     * Return a string representation of this managed bean.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer("ManagedBean[");
+        sb.append("name=");
+        sb.append(name);
+        sb.append(", className=");
+        sb.append(className);
+        sb.append(", description=");
+        sb.append(description);
+        if (group != null) {
+            sb.append(", group=");
+            sb.append(group);
+        }
+        sb.append(", type=");
+        sb.append(type);
+        sb.append("]");
+        return (sb.toString());
+
+    }
+
+    Method getGetter(String aname, BaseModelMBean mbean, Object resource) 
+            throws AttributeNotFoundException, MBeanException, ReflectionException {
+        // TODO: do we need caching ? JMX is for management, it's not supposed to require lots of performance.
+        Method m=null; // (Method)getAttMap.get( name );
+
+        if( m==null ) {
+            AttributeInfo attrInfo = (AttributeInfo)attributes.get(aname);
+            // Look up the actual operation to be used
+            if (attrInfo == null)
+                throw new AttributeNotFoundException(" Cannot find attribute " + aname + " for " + resource);
+            
+            String getMethod = attrInfo.getGetMethod();
+            if (getMethod == null)
+                throw new AttributeNotFoundException("Cannot find attribute " + aname + " get method name");
+
+            Object object = null;
+            NoSuchMethodException exception = null;
+            try {
+                object = mbean;
+                m = object.getClass().getMethod(getMethod, NO_ARGS_PARAM_SIG);
+            } catch (NoSuchMethodException e) {
+                exception = e;;
+            }
+            if( m== null && resource != null ) {
+                try {
+                    object = resource;
+                    m = object.getClass().getMethod(getMethod, NO_ARGS_PARAM_SIG);
+                    exception=null;
+                } catch (NoSuchMethodException e) {
+                    exception = e;
+                }
+            }
+            if( exception != null )
+                throw new ReflectionException(exception,
+                                              "Cannot find getter method " + getMethod);
+            //getAttMap.put( name, m );
+        }
+
+        return m;
+    }
+
+    public Method getSetter(String aname, BaseModelMBean bean, Object resource) 
+            throws AttributeNotFoundException, MBeanException, ReflectionException {
+        // Cache may be needed for getters, but it is a really bad idea for setters, this is far 
+        // less frequent.
+        Method m=null;//(Method)setAttMap.get( name );
+
+        if( m==null ) {
+            AttributeInfo attrInfo = (AttributeInfo)attributes.get(aname);
+            if (attrInfo == null)
+                throw new AttributeNotFoundException(" Cannot find attribute " + aname);
+
+            // Look up the actual operation to be used
+            String setMethod = attrInfo.getSetMethod();
+            if (setMethod == null)
+                throw new AttributeNotFoundException("Cannot find attribute " + aname + " set method name");
+
+            String argType=attrInfo.getType();
+
+            Class signature[] = new Class[] { BaseModelMBean.getAttributeClass( argType ) };
+
+            Object object = null;
+            NoSuchMethodException exception = null;
+            try {
+                object = this;
+                m = object.getClass().getMethod(setMethod, signature);
+            } catch (NoSuchMethodException e) {
+                exception = e;;
+            }
+            if( m== null && resource != null ) {
+                try {
+                    object = resource;
+                    m = object.getClass().getMethod(setMethod, signature);
+                    exception=null;
+                } catch (NoSuchMethodException e) {
+                    exception = e;
+                }
+            }
+            if( exception != null )
+                throw new ReflectionException(exception,
+                                              "Cannot find setter method " + setMethod +
+                        " " + resource);
+            //setAttMap.put( name, m );
+        }
+
+        return m;
+    }
+
+    public Method getInvoke(String aname, Object[] params, String[] signature, BaseModelMBean bean, Object resource) 
+            throws MBeanException, ReflectionException {
+        Method method = null;
+        if (method == null) {
+            if (params == null)
+                params = new Object[0];
+            if (signature == null)
+                signature = new String[0];
+            if (params.length != signature.length)
+                throw new RuntimeOperationsException(
+                        new IllegalArgumentException(
+                                "Inconsistent arguments and signature"),
+                        "Inconsistent arguments and signature");
+
+            // Acquire the ModelMBeanOperationInfo information for
+            // the requested operation
+            OperationInfo opInfo = (OperationInfo)operations.get(aname);
+            if (opInfo == null)
+                throw new MBeanException(new ServiceNotFoundException(
+                        "Cannot find operation " + aname),
+                        "Cannot find operation " + aname);
+
+            // Prepare the signature required by Java reflection APIs
+            // FIXME - should we use the signature from opInfo?
+            Class types[] = new Class[signature.length];
+            for (int i = 0; i < signature.length; i++) {
+                types[i] = BaseModelMBean.getAttributeClass(signature[i]);
+            }
+
+            // Locate the method to be invoked, either in this MBean itself
+            // or in the corresponding managed resource
+            // FIXME - Accessible methods in superinterfaces?
+            Object object = null;
+            Exception exception = null;
+            try {
+                object = this;
+                method = object.getClass().getMethod(aname, types);
+            } catch (NoSuchMethodException e) {
+                exception = e;
+                ;
+            }
+            try {
+                if ((method == null) && (resource != null)) {
+                    object = resource;
+                    method = object.getClass().getMethod(aname, types);
+                }
+            } catch (NoSuchMethodException e) {
+                exception = e;
+            }
+            if (method == null) {
+                throw new ReflectionException(exception, "Cannot find method "
+                        + aname + " with this signature");
+            }
+            // invokeAttMap.put(mkey, method);
+        }
+        return method;
+    }
+
+
+}

Added: tomcat/sandbox/java/org/apache/tomcat/util/modeler/NotificationInfo.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/tomcat/util/modeler/NotificationInfo.java?rev=407661&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/modeler/NotificationInfo.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/modeler/NotificationInfo.java Thu May 18 16:27:34 2006
@@ -0,0 +1,140 @@
+/*
+ * 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.MBeanNotificationInfo;
+
+
+/**
+ * <p>Internal configuration information for a <code>Notification</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 NotificationInfo extends FeatureInfo implements Serializable {
+    static final long serialVersionUID = -6319885418912650856L;
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The <code>ModelMBeanNotificationInfo</code> object that corresponds
+     * to this <code>NotificationInfo</code> instance.
+     */
+    transient MBeanNotificationInfo info = null;
+    protected String notifTypes[] = new String[0];
+
+    // ------------------------------------------------------------- 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 set of notification types for this MBean.
+     */
+    public String[] getNotifTypes() {
+        return (this.notifTypes);
+    }
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Add a new notification type to the set managed by an MBean.
+     *
+     * @param notifType The new notification type
+     */
+    public void addNotifType(String notifType) {
+
+        synchronized (notifTypes) {
+            String results[] = new String[notifTypes.length + 1];
+            System.arraycopy(notifTypes, 0, results, 0, notifTypes.length);
+            results[notifTypes.length] = notifType;
+            notifTypes = results;
+            this.info = null;
+        }
+
+    }
+
+
+    /**
+     * Create and return a <code>ModelMBeanNotificationInfo</code> object that
+     * corresponds to the attribute described by this instance.
+     */
+    public MBeanNotificationInfo createNotificationInfo() {
+
+        // Return our cached information (if any)
+        if (info != null)
+            return (info);
+
+        // Create and return a new information object
+        info = new MBeanNotificationInfo
+            (getNotifTypes(), getName(), getDescription());
+        //Descriptor descriptor = info.getDescriptor();
+        //addFields(descriptor);
+        //info.setDescriptor(descriptor);
+        return (info);
+
+    }
+
+
+    /**
+     * Return a string representation of this notification descriptor.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer("NotificationInfo[");
+        sb.append("name=");
+        sb.append(name);
+        sb.append(", description=");
+        sb.append(description);
+        sb.append(", notifTypes=");
+        sb.append(notifTypes.length);
+        sb.append("]");
+        return (sb.toString());
+
+    }
+
+
+}

Added: tomcat/sandbox/java/org/apache/tomcat/util/modeler/OperationInfo.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/tomcat/util/modeler/OperationInfo.java?rev=407661&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/modeler/OperationInfo.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/modeler/OperationInfo.java Thu May 18 16:27:34 2006
@@ -0,0 +1,240 @@
+/*
+ * 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.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+
+
+/**
+ * <p>Internal configuration information for an <code>Operation</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 OperationInfo extends FeatureInfo implements Serializable {
+    static final long serialVersionUID = 4418342922072614875L;
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Standard zero-arguments constructor.
+     */
+    public OperationInfo() {
+
+        super();
+
+    }
+
+
+    /**
+     * Special constructor for setting up getter and setter operations.
+     *
+     * @param name Name of this operation
+     * @param getter Is this a getter (as opposed to a setter)?
+     * @param type Data type of the return value (if this is a getter)
+     *  or the parameter (if this is a setter)
+     * 
+     */
+    public OperationInfo(String name, boolean getter, String type) {
+
+        super();
+        setName(name);
+        if (getter) {
+            setDescription("Attribute getter method");
+            setImpact("INFO");
+            setReturnType(type);
+            setRole("getter");
+        } else {
+            setDescription("Attribute setter method");
+            setImpact("ACTION");
+            setReturnType("void");
+            setRole("setter");
+            addParameter(new ParameterInfo("value", type,
+                                           "New attribute value"));
+        }
+
+    }
+
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The <code>ModelMBeanOperationInfo</code> object that corresponds
+     * to this <code>OperationInfo</code> instance.
+     */
+    transient MBeanOperationInfo info = null;
+    protected String impact = "UNKNOWN";
+    protected String role = "operation";
+    protected String returnType = "void";    // FIXME - Validate
+    protected ParameterInfo parameters[] = new ParameterInfo[0];
+
+
+    // ------------------------------------------------------------- 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 "impact" of this operation, which should be a (case-insensitive)
+     * string value "ACTION", "ACTION_INFO", "INFO", or "UNKNOWN".
+     */
+    public String getImpact() {
+        return (this.impact);
+    }
+
+    public void setImpact(String impact) {
+        if (impact == null)
+            this.impact = null;
+        else
+            this.impact = impact.toUpperCase();
+    }
+
+
+    /**
+     * The role of this operation ("getter", "setter", "operation", or
+     * "constructor").
+     */
+    public String getRole() {
+        return (this.role);
+    }
+
+    public void setRole(String role) {
+        this.role = role;
+    }
+
+
+    /**
+     * The fully qualified Java class name of the return type for this
+     * operation.
+     */
+    public String getReturnType() {
+        return (this.returnType);
+    }
+
+    public void setReturnType(String returnType) {
+        this.returnType = returnType;
+    }
+
+    /**
+     * The set of parameters for this operation.
+     */
+    public ParameterInfo[] getSignature() {
+        return (this.parameters);
+    }
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Add a new parameter to the set of arguments for this operation.
+     *
+     * @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>ModelMBeanOperationInfo</code> object that
+     * corresponds to the attribute described by this instance.
+     */
+    public MBeanOperationInfo createOperationInfo() {
+
+        // 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();
+        int impact = MBeanOperationInfo.UNKNOWN;
+        if ("ACTION".equals(getImpact()))
+            impact = MBeanOperationInfo.ACTION;
+        else if ("ACTION_INFO".equals(getImpact()))
+            impact = MBeanOperationInfo.ACTION_INFO;
+        else if ("INFO".equals(getImpact()))
+            impact = MBeanOperationInfo.INFO;
+
+        info = new MBeanOperationInfo
+            (getName(), getDescription(), parameters,
+             getReturnType(), impact);
+        return (info);
+
+    }
+
+
+    /**
+     * Return a string representation of this operation descriptor.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer("OperationInfo[");
+        sb.append("name=");
+        sb.append(name);
+        sb.append(", description=");
+        sb.append(description);
+        sb.append(", returnType=");
+        sb.append(returnType);
+        sb.append(", parameters=");
+        sb.append(parameters.length);
+        sb.append("]");
+        return (sb.toString());
+
+    }
+
+
+}

Added: tomcat/sandbox/java/org/apache/tomcat/util/modeler/ParameterInfo.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/tomcat/util/modeler/ParameterInfo.java?rev=407661&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/modeler/ParameterInfo.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/modeler/ParameterInfo.java Thu May 18 16:27:34 2006
@@ -0,0 +1,151 @@
+/*
+ * 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.MBeanParameterInfo;
+
+
+/**
+ * <p>Internal configuration information for a <code>Parameter</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 ParameterInfo extends FeatureInfo implements Serializable {
+    static final long serialVersionUID = 2222796006787664020L;
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Standard zero-arguments constructor.
+     */
+    public ParameterInfo() {
+
+        super();
+
+    }
+
+
+    /**
+     * Special constructor for setting up parameters programatically.
+     *
+     * @param name Name of this parameter
+     * @param type Java class of this parameter
+     * @param description Description of this parameter
+     */
+    public ParameterInfo(String name, String type, String description) {
+
+        super();
+        setName(name);
+        setType(type);
+        setDescription(description);
+
+    }
+
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The <code>MBeanParameterInfo</code> object that corresponds
+     * to this <code>ParameterInfo</code> instance.
+     */
+    transient MBeanParameterInfo info = null;
+    protected String type = null;
+
+    // ------------------------------------------------------------- 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 fully qualified Java class name of this parameter.
+     */
+    public String getType() {
+        return (this.type);
+    }
+
+    public void setType(String type) {
+        this.type = type;
+        this.info = null;
+    }
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Create and return a <code>MBeanParameterInfo</code> object that
+     * corresponds to the parameter described by this instance.
+     */
+    public MBeanParameterInfo createParameterInfo() {
+
+        // Return our cached information (if any)
+        if (info != null)
+            return (info);
+
+        // Create and return a new information object
+        info = new MBeanParameterInfo
+            (getName(), getType(), getDescription());
+        return (info);
+
+    }
+
+
+    /**
+     * Return a string representation of this parameter descriptor.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer("ParameterInfo[");
+        sb.append("name=");
+        sb.append(name);
+        sb.append(", description=");
+        sb.append(description);
+        sb.append(", type=");
+        sb.append(type);
+        sb.append("]");
+        return (sb.toString());
+
+    }
+}

Added: tomcat/sandbox/java/org/apache/tomcat/util/modeler/Registry.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/tomcat/util/modeler/Registry.java?rev=407661&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/modeler/Registry.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/modeler/Registry.java Thu May 18 16:27:34 2006
@@ -0,0 +1,1085 @@
+/*
+ * Copyright 2001-2006 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.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.management.DynamicMBean;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.tomcat.util.modeler.modules.ModelerSource;
+
+/*
+   Issues:
+   - exceptions - too many "throws Exception"
+   - double check the interfaces 
+   - start removing the use of the experimental methods in tomcat, then remove
+     the methods ( before 1.1 final )
+   - is the security enough to prevent Registry beeing used to avoid the permission
+    checks in the mbean server ?
+*/ 
+
+/**
+ * Registry for modeler MBeans. 
+ *
+ * This is the main entry point into modeler. It provides methods to create
+ * and manipulate model mbeans and simplify their use.
+ *
+ * Starting with version 1.1, this is no longer a singleton and the static
+ * methods are strongly deprecated. In a container environment we can expect
+ * different applications to use different registries.
+ * 
+ * This class is itself an mbean.
+ * 
+ * IMPORTANT: public methods not marked with @since x.x are experimental or 
+ * internal. Should not be used.  
+ * 
+ * @author Craig R. McClanahan
+ * @author Costin Manolache
+ */
+public class Registry implements RegistryMBean, MBeanRegistration  {
+    /** Experimental support for manifest-based discovery.
+     */
+    public static String MODELER_MANIFEST="/META-INF/mbeans-descriptors.xml";
+
+    /**
+     * The Log instance to which we will write our log messages.
+     */
+    private static Log log = LogFactory.getLog(Registry.class);
+
+    // Support for the factory methods
+    
+    /** Will be used to isolate different apps and enhance security
+     */
+    private static HashMap perLoaderRegistries=null;
+
+    /**
+     * The registry instance created by our factory method the first time
+     * it is called.
+     */
+    private static Registry registry = null;
+
+    // Per registy fields
+    
+    /**
+     * The <code>MBeanServer</code> instance that we will use to register
+     * management beans.
+     */
+    private MBeanServer server = null;
+
+    /**
+     * The set of ManagedBean instances for the beans this registry
+     * knows about, keyed by name.
+     */
+    private HashMap descriptors = new HashMap();
+
+    /** List of managed byeans, keyed by class name
+     */
+    private HashMap descriptorsByClass = new HashMap();
+
+    // map to avoid duplicated searching or loading descriptors 
+    private HashMap searchedPaths=new HashMap();
+    
+    private Object key;
+    private Object guard;
+
+    // Id - small ints to use array access. No reset on stop()
+    private Hashtable idDomains=new Hashtable();
+    private Hashtable ids=new Hashtable();
+
+    
+    // ----------------------------------------------------------- Constructors
+
+    /**
+     */
+     public Registry() {
+        super();
+    }
+
+    // -------------------- Static methods  --------------------
+    // Factories
+    
+    /**
+     * Factory method to create (if necessary) and return our
+     * <code>Registry</code> instance.
+     *
+     * Use this method to obtain a Registry - all other static methods
+     * are deprecated and shouldn't be used.
+     *
+     * The current version uses a static - future versions could use
+     * the thread class loader.
+     * 
+     * @param key Support for application isolation. If null, the context class
+     * loader will be used ( if setUseContextClassLoader is called ) or the 
+     * default registry is returned. 
+     * @param guard Prevent access to the registry by untrusted components
+     *
+     * @since 1.1
+     */
+    public synchronized static Registry getRegistry(Object key, Object guard) {
+        Registry localRegistry;
+        if( perLoaderRegistries!=null ) {
+            if( key==null ) 
+                key=Thread.currentThread().getContextClassLoader();
+            if( key != null ) {
+                localRegistry=(Registry)perLoaderRegistries.get(key);
+                if( localRegistry == null ) {
+                    localRegistry=new Registry();
+                    localRegistry.key=key;
+                    localRegistry.guard=guard;
+                    perLoaderRegistries.put( key, localRegistry );
+                    return localRegistry;
+                }
+                if( localRegistry.guard != null &&
+                        localRegistry.guard != guard ) {
+                    return null; // XXX Should I throw a permission ex ? 
+                }
+                return localRegistry;
+            }
+        }
+
+        // static 
+        if (registry == null) {
+            registry = new Registry();
+        }
+        if( registry.guard != null &&
+                registry.guard != guard ) {
+            return null;
+        }
+        return (registry);
+    }
+    
+    /** Allow containers to isolate apps. Can be called only once.
+     * It  is highly recommended you call this method if using Registry in
+     * a container environment. The default is false for backward compatibility
+     * 
+     * @param enable
+     * @since 1.1
+     */
+    public static void setUseContextClassLoader( boolean enable ) {
+        if( enable ) {
+            perLoaderRegistries=new HashMap();
+        }
+    }
+    
+    // -------------------- Generic methods  --------------------
+
+    /** Set a guard object that will prevent access to this registry 
+     * by unauthorized components
+     * 
+     * @param guard
+     * 
+     * @since 1.1
+     */ 
+    public void setGuard( Object guard ) {
+        if( this.guard!=null ) {
+            return; // already set, only once
+        }
+        this.guard=guard;
+    }
+
+    /** Lifecycle method - clean up the registry metadata.
+     * 
+     * @since 1.1
+     */ 
+    public void stop() {
+        descriptorsByClass = new HashMap();
+        descriptors = new HashMap();
+        searchedPaths=new HashMap();
+    }
+    
+    /** 
+     * Load an extended mlet file. The source can be an URL, File or
+     * InputStream. 
+     * 
+     * All mbeans will be instantiated, registered and the attributes will be 
+     * set. The result is a list of ObjectNames.
+     *
+     * @param source InputStream or URL of the file
+     * @param cl ClassLoader to be used to load the mbeans, or null to use the
+     *        default JMX mechanism ( i.e. all registered loaders )
+     * @return List of ObjectName for the loaded mbeans
+     * @throws Exception
+     * 
+     * @since 1.1
+     */ 
+    public List loadMBeans( Object source, ClassLoader cl )
+            throws Exception
+    {
+        return load("MbeansSource", source, null );
+    }    
+
+
+    /** Load descriptors. The source can be a File or URL or InputStream for the 
+     * descriptors file. In the case of File and URL, if the extension is ".ser"
+     * a serialized version will be loaded. 
+     * 
+     * Also ( experimental for now ) a ClassLoader - in which case META-INF/ will
+     * be used.
+     * 
+     * This method should be used to explicitely load metadata - but this is not
+     * required in most cases. The registerComponent() method will find metadata
+     * in the same pacakge.
+     * 
+     * @param source
+     */ 
+    public void loadMetadata(Object source ) throws Exception {
+        if( source instanceof ClassLoader ) {
+            loadMetaInfDescriptors((ClassLoader)source);
+            return;
+        } else {
+            loadDescriptors( null, source, null );
+        }
+        
+    }
+
+    /** Register a bean by creating a modeler mbean and adding it to the 
+     * MBeanServer.
+     * 
+     * If metadata is not loaded, we'll look up and read a file named
+     * "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package
+     * or parent.
+     *
+     * If the bean is an instance of DynamicMBean. it's metadata will be converted
+     * to a model mbean and we'll wrap it - so modeler services will be supported
+     *
+     * If the metadata is still not found, introspection will be used to extract
+     * it automatically. 
+     * 
+     * If an mbean is already registered under this name, it'll be first
+     * unregistered.
+     * 
+     * If the component implements MBeanRegistration, the methods will be called.
+     * If the method has a method "setRegistry" that takes a RegistryMBean as
+     * parameter, it'll be called with the current registry.
+     * 
+     *
+     * @param bean Object to be registered
+     * @param oname Name used for registration
+     * @param type The type of the mbean, as declared in mbeans-descriptors. If
+     * null, the name of the class will be used. This can be used as a hint or
+     * by subclasses.
+     *
+     * @since 1.1
+     */ 
+    public void registerComponent(Object bean, String oname, String type)
+           throws Exception
+    {
+        registerComponent(bean, new ObjectName(oname), type);        
+    }    
+
+    /** Unregister a component. We'll first check if it is registered,
+     * and mask all errors. This is mostly a helper.
+     * 
+     * @param oname
+     * 
+     * @since 1.1
+     */ 
+    public void unregisterComponent( String oname ) {
+        try {
+            unregisterComponent(new ObjectName(oname));
+        } catch (MalformedObjectNameException e) {
+            log.info("Error creating object name " + e );
+        }
+    }    
+    
+
+    /** Invoke a operation on a list of mbeans. Can be used to implement
+     * lifecycle operations.
+     *
+     * @param mbeans list of ObjectName on which we'll invoke the operations
+     * @param operation  Name of the operation ( init, start, stop, etc)
+     * @param failFirst  If false, exceptions will be ignored
+     * @throws Exception
+     * @since 1.1
+     */
+    public void invoke( List mbeans, String operation, boolean failFirst )
+            throws Exception
+    {
+        if( mbeans==null ) {
+            return;
+        }
+        Iterator itr=mbeans.iterator();
+        while(itr.hasNext()) {
+            Object current=itr.next();
+            ObjectName oN=null;
+            try {
+                if( current instanceof ObjectName) {
+                    oN=(ObjectName)current;
+                }
+                if( current instanceof String ) {
+                    oN=new ObjectName( (String)current );
+                }
+                if( oN==null ) {
+                    continue;
+                }
+                if( getMethodInfo(oN, operation) == null) {
+                    continue;
+                }
+                getMBeanServer().invoke(oN, operation,
+                        new Object[] {}, new String[] {});
+
+            } catch( Exception t ) {
+                if( failFirst ) throw t;
+                log.info("Error initializing " + current + " " + t.toString());
+            }
+        }
+    }
+
+    // -------------------- ID registry --------------------
+
+    /** Return an int ID for faster access. Will be used for notifications
+     * and for other operations we want to optimize. 
+     *
+     * @param domain Namespace 
+     * @param name  Type of the notification
+     * @return  An unique id for the domain:name combination
+     * @since 1.1
+     */
+    public synchronized int getId( String domain, String name) {
+        if( domain==null) {
+            domain="";
+        }
+        Hashtable domainTable=(Hashtable)idDomains.get( domain );
+        if( domainTable == null ) {
+            domainTable=new Hashtable();
+            idDomains.put( domain, domainTable); 
+        }
+        if( name==null ) {
+            name="";
+        }
+        Integer i=(Integer)domainTable.get(name);
+        
+        if( i!= null ) {
+            return i.intValue();
+        }
+
+        int id[]=(int [])ids.get( domain );
+        if( id == null ) {
+            id=new int[1];
+            ids.put( domain, id); 
+        }
+        int code=id[0]++;
+        domainTable.put( name, new Integer( code ));
+        return code;
+    }
+    
+    // -------------------- Metadata   --------------------
+    // methods from 1.0
+
+    /**
+     * Add a new bean metadata to the set of beans known to this registry.
+     * This is used by internal components.
+     *
+     * @param bean The managed bean to be added
+     * @since 1.0
+     */
+    public void addManagedBean(ManagedBean bean) {
+        // XXX Use group + name
+        descriptors.put(bean.getName(), bean);
+        if( bean.getType() != null ) {
+            descriptorsByClass.put( bean.getType(), bean );
+        }
+    }
+
+
+    /**
+     * Find and return the managed bean definition for the specified
+     * bean name, if any; otherwise return <code>null</code>.
+     *
+     * @param name Name of the managed bean to be returned. Since 1.1, both
+     *   short names or the full name of the class can be used.
+     * @since 1.0
+     */
+    public ManagedBean findManagedBean(String name) {
+        // XXX Group ?? Use Group + Type
+        ManagedBean mb=((ManagedBean) descriptors.get(name));
+        if( mb==null )
+            mb=(ManagedBean)descriptorsByClass.get(name);
+        return mb;
+    }
+    
+    /**
+     * Return the set of bean names for all managed beans known to
+     * this registry.
+     *
+     * @since 1.0
+     */
+    public String[] findManagedBeans() {
+        return ((String[]) descriptors.keySet().toArray(new String[0]));
+    }
+
+
+    /**
+     * Return the set of bean names for all managed beans known to
+     * this registry that belong to the specified group.
+     *
+     * @param group Name of the group of interest, or <code>null</code>
+     *  to select beans that do <em>not</em> belong to a group
+     * @since 1.0
+     */
+    public String[] findManagedBeans(String group) {
+
+        ArrayList results = new ArrayList();
+        Iterator items = descriptors.values().iterator();
+        while (items.hasNext()) {
+            ManagedBean item = (ManagedBean) items.next();
+            if ((group == null) && (item.getGroup() == null)) {
+                results.add(item.getName());
+            } else if (group.equals(item.getGroup())) {
+                results.add(item.getName());
+            }
+        }
+        String values[] = new String[results.size()];
+        return ((String[]) results.toArray(values));
+
+    }
+
+
+    /**
+     * Remove an existing bean from the set of beans known to this registry.
+     *
+     * @param bean The managed bean to be removed
+     * @since 1.0
+     */
+    public void removeManagedBean(ManagedBean bean) {
+       // TODO: change this to use group/name
+        descriptors.remove(bean.getName());
+        descriptorsByClass.remove( bean.getType());
+    }
+
+    // -------------------- Deprecated 1.0 methods  --------------------
+    
+    /**
+     * Factory method to create (if necessary) and return our
+     * <code>MBeanServer</code> instance.
+     *
+     * @since 1.0
+     * @deprecated Use the instance method
+     */
+    public static MBeanServer getServer() {
+        return Registry.getRegistry().getMBeanServer();
+    }
+
+    /**
+     * Set the <code>MBeanServer</code> to be utilized for our
+     * registered management beans.
+     *
+     * @param mbeanServer The new <code>MBeanServer</code> instance
+     * @since 1.0
+     * @deprecated Use the instance method
+     */
+    public static void setServer(MBeanServer mbeanServer) {
+        Registry.getRegistry().setMBeanServer(mbeanServer);
+    }
+
+    /**
+     * Load the registry from the XML input found in the specified input
+     * stream.
+     *
+     * @param stream InputStream containing the registry configuration
+     *  information
+     *
+     * @exception Exception if any parsing or processing error occurs
+     * @deprecated use normal class method instead
+     * @since 1.0
+     */
+    public static void loadRegistry(InputStream stream) throws Exception {
+        Registry registry = getRegistry();
+        registry.loadMetadata(stream);
+    }
+
+    /** Get a "singelton" registry, or one per thread if setUseContextLoader 
+     * was called 
+     * 
+     * @deprecated Not enough info - use the method that takes CL and domain
+     * @since 1.0 
+     */ 
+    public synchronized static Registry getRegistry() {
+        return getRegistry(null, null);
+    }    
+
+    // -------------------- Helpers  --------------------
+
+    /** Get the type of an attribute of the object, from the metadata.
+     *
+     * @param oname
+     * @param attName
+     * @return null if metadata about the attribute is not found
+     * @since 1.1
+     */
+    public String getType( ObjectName oname, String attName )
+    {
+        String type=null;
+        MBeanInfo info=null;
+        try {
+            info=server.getMBeanInfo(oname);
+        } catch (Exception e) {
+            log.info( "Can't find metadata for object" + oname );
+            return null;
+        }
+
+        MBeanAttributeInfo attInfo[]=info.getAttributes();
+        for( int i=0; i<attInfo.length; i++ ) {
+            if( attName.equals(attInfo[i].getName())) {
+                type=attInfo[i].getType();
+                return type;
+            }
+        }
+        return null;
+    }
+
+    /** Find the operation info for a method
+     * 
+     * @param oname
+     * @param opName
+     * @return the operation info for the specified operation
+     */ 
+    public MBeanOperationInfo getMethodInfo( ObjectName oname, String opName )
+    {
+        String type=null;
+        MBeanInfo info=null;
+        try {
+            info=server.getMBeanInfo(oname);
+        } catch (Exception e) {
+            log.info( "Can't find metadata " + oname );
+            return null;
+        }
+        MBeanOperationInfo attInfo[]=info.getOperations();
+        for( int i=0; i<attInfo.length; i++ ) {
+            if( opName.equals(attInfo[i].getName())) {
+                return attInfo[i];
+            }
+        }
+        return null;
+    }
+
+    /** Unregister a component. This is just a helper that
+     * avoids exceptions by checking if the mbean is already registered
+     *
+     * @param oname
+     */
+    public void unregisterComponent( ObjectName oname ) {
+        try {
+            if( getMBeanServer().isRegistered(oname)) {
+                getMBeanServer().unregisterMBean(oname);
+            }
+        } catch( Throwable t ) {
+            log.error( "Error unregistering mbean ", t);
+        }
+    }
+
+    /**
+     * Factory method to create (if necessary) and return our
+     * <code>MBeanServer</code> instance.
+     *
+     */
+    public synchronized MBeanServer getMBeanServer() {
+        long t1=System.currentTimeMillis();
+
+        if (server == null) {
+            if( MBeanServerFactory.findMBeanServer(null).size() > 0 ) {
+                server=(MBeanServer)MBeanServerFactory.findMBeanServer(null).get(0);
+                if( log.isDebugEnabled() ) {
+                    log.debug("Using existing MBeanServer " + (System.currentTimeMillis() - t1 ));
+                }
+            } else {
+                server=MBeanServerFactory.createMBeanServer();
+                if( log.isDebugEnabled() ) {
+                    log.debug("Creating MBeanServer"+ (System.currentTimeMillis() - t1 ));
+                }
+            }
+        }
+        return (server);
+    }
+
+    /** Find or load metadata. 
+     */ 
+    public ManagedBean findManagedBean(Object bean, Class beanClass, String type)
+        throws Exception
+    {
+        if( bean!=null && beanClass==null ) {
+            beanClass=bean.getClass();
+        }
+        
+        if( type==null ) {
+            type=beanClass.getName();
+        }
+        
+        // first look for existing descriptor
+        ManagedBean managed = findManagedBean(type);
+
+        // Search for a descriptor in the same package
+        if( managed==null ) {
+            // check package and parent packages
+            if( log.isDebugEnabled() ) {
+                log.debug( "Looking for descriptor ");
+            }
+            findDescriptor( beanClass, type );
+
+            managed=findManagedBean(type);
+        }
+        
+        if( bean instanceof DynamicMBean ) {
+            if( log.isDebugEnabled() ) {
+                log.debug( "Dynamic mbean support ");
+            }
+            // Dynamic mbean
+            loadDescriptors("MbeansDescriptorsDynamicMBeanSource",
+                    bean, type);
+
+            managed=findManagedBean(type);
+        }
+
+        // Still not found - use introspection
+        if( managed==null ) {
+            if( log.isDebugEnabled() ) {
+                log.debug( "Introspecting ");
+            }
+
+            // introspection
+            loadDescriptors("MbeansDescriptorsIntrospectionSource",
+                    beanClass, type);
+
+            managed=findManagedBean(type);
+            if( managed==null ) {
+                log.warn( "No metadata found for " + type );
+                return null;
+            }
+            managed.setName( type );
+            addManagedBean(managed);
+        }
+        return managed;
+    }
+    
+
+    /** EXPERIMENTAL Convert a string to object, based on type. Used by several
+     * components. We could provide some pluggability. It is here to keep
+     * things consistent and avoid duplication in other tasks 
+     * 
+     * @param type Fully qualified class name of the resulting value
+     * @param value String value to be converted
+     * @return Converted value
+     */ 
+    public Object convertValue(String type, String value)
+    {
+        Object objValue=value;
+        
+        if( type==null || "java.lang.String".equals( type )) {
+            // string is default
+            objValue=value;
+        } else if( "javax.management.ObjectName".equals( type ) ||
+                "ObjectName".equals( type )) {
+            try {
+                objValue=new ObjectName( value );
+            } catch (MalformedObjectNameException e) {
+                return null;
+            }
+        } else if( "java.lang.Integer".equals( type ) ||
+                "int".equals( type )) {
+            objValue=new Integer( value );
+        } else if( "java.lang.Long".equals( type ) ||
+                "long".equals( type )) {
+            objValue=new Long( value );
+        } else if( "java.lang.Boolean".equals( type ) ||
+                "boolean".equals( type )) {
+            objValue=new Boolean( value );
+        }
+        return objValue;
+    }
+    
+    /** Experimental.
+     *
+     * @param sourceType
+     * @param source
+     * @param param
+     * @return List of descriptors
+     * @throws Exception
+     * @deprecated bad interface, mixing of metadata and mbeans
+     */
+    public List load( String sourceType, Object source, String param)
+        throws Exception
+    {
+        if( log.isTraceEnabled()) {
+            log.trace("load " + source );
+        }
+        String location=null;
+        String type=null;
+        Object inputsource=null;
+
+        if( source instanceof DynamicMBean ) {
+            sourceType="MbeansDescriptorsDynamicMBeanSource";
+            inputsource=source;
+        } else if( source instanceof URL ) {
+            URL url=(URL)source;
+            location=url.toString();
+            type=param;
+            inputsource=url.openStream();
+            if( sourceType == null ) {
+                sourceType = sourceTypeFromExt(location);
+            }
+        } else if( source instanceof File ) {
+            location=((File)source).getAbsolutePath();
+            inputsource=new FileInputStream((File)source);            
+            type=param;
+            if( sourceType == null ) {
+                sourceType = sourceTypeFromExt(location);
+            }
+        } else if( source instanceof InputStream ) {
+            type=param;
+            inputsource=source;
+        } else if( source instanceof Class ) {
+            location=((Class)source).getName();
+            type=param;
+            inputsource=source;
+            if( sourceType== null ) {
+                sourceType="MbeansDescriptorsIntrospectionSource";
+            }
+        }
+        
+        if( sourceType==null ) {
+            sourceType="MbeansDescriptorsDigesterSource";
+        }
+        ModelerSource ds=getModelerSource(sourceType);
+        List mbeans=ds.loadDescriptors(this, location, type, inputsource);
+
+        return mbeans;
+    }
+
+    private String sourceTypeFromExt( String s ) {
+        if( s.endsWith( ".ser")) {
+            return "MbeansDescriptorsSerSource";
+        }
+        else if( s.endsWith(".xml")) {
+            return "MbeansDescriptorsDigesterSource";
+        }
+        return null;
+    }
+
+    /** Register a component 
+     * XXX make it private 
+     * 
+     * @param bean
+     * @param oname
+     * @param type
+     * @throws Exception
+     */ 
+    public void registerComponent(Object bean, ObjectName oname, String type)
+           throws Exception
+    {
+        if( log.isDebugEnabled() ) {
+            log.debug( "Managed= "+ oname);
+        }
+
+        if( bean ==null ) {
+            log.error("Null component " + oname );
+            return;
+        }
+
+        try {
+            if( type==null ) {
+                type=bean.getClass().getName();
+            }
+
+            ManagedBean managed = findManagedBean(bean.getClass(), type);
+
+            // The real mbean is created and registered
+            DynamicMBean mbean = managed.createMBean(bean);
+
+            if(  getMBeanServer().isRegistered( oname )) {
+                if( log.isDebugEnabled()) {
+                    log.debug("Unregistering existing component " + oname );
+                }
+                getMBeanServer().unregisterMBean( oname );
+            }
+
+            getMBeanServer().registerMBean( mbean, oname);
+        } catch( Exception ex) {
+            log.error("Error registering " + oname, ex );
+            throw ex;
+        }
+    }
+
+    /** Lookup the component descriptor in the package and
+     * in the parent packages.
+     *
+     * @param packageName
+     */
+    public void loadDescriptors( String packageName, ClassLoader classLoader  ) {
+        String res=packageName.replace( '.', '/');
+
+        if( log.isTraceEnabled() ) {
+            log.trace("Finding descriptor " + res );
+        }
+
+        if( searchedPaths.get( packageName ) != null ) {
+            return;
+        }
+        String descriptors=res + "/mbeans-descriptors.ser";
+
+        URL dURL=classLoader.getResource( descriptors );
+
+        if( dURL == null ) {
+            descriptors=res + "/mbeans-descriptors.xml";
+            dURL=classLoader.getResource( descriptors );
+        }
+        if( dURL == null ) {
+            return;
+        }
+
+        log.debug( "Found " + dURL);
+        searchedPaths.put( packageName,  dURL );
+        try {
+            if( descriptors.endsWith(".xml" ))
+                loadDescriptors("MbeansDescriptorsDigesterSource", dURL, null);
+            else
+                loadDescriptors("MbeansDescriptorsSerSource", dURL, null);
+            return;
+        } catch(Exception ex ) {
+            log.error("Error loading " + dURL);
+        }
+
+        return;
+    }
+
+    /** Experimental. Will become private, some code may still use it
+     *
+     * @param sourceType
+     * @param source
+     * @param param
+     * @throws Exception
+     * @deprecated
+     */
+    public void loadDescriptors( String sourceType, Object source, String param)
+        throws Exception
+    {
+        List mbeans=load( sourceType, source, param );
+        if( mbeans == null) return;
+
+        Iterator itr=mbeans.iterator();
+        while( itr.hasNext() ) {
+            Object mb=itr.next();
+            if( mb instanceof ManagedBean) {
+                addManagedBean((ManagedBean)mb);
+            }
+        }
+    }
+
+    /** Discover all META-INF/modeler.xml files in classpath and register
+     * the components
+     *
+     * @since EXPERIMENTAL
+     */
+    private void loadMetaInfDescriptors(ClassLoader cl) {
+        try {
+            Enumeration en=cl.getResources(MODELER_MANIFEST);
+            while( en.hasMoreElements() ) {
+                URL url=(URL)en.nextElement();
+                InputStream is=url.openStream();
+                if( log.isDebugEnabled()) log.debug("Loading " + url);
+                loadDescriptors("MbeansDescriptorsDigesterSource", is, null );
+            }
+        } catch( Exception ex ) {
+            ex.printStackTrace();
+        }
+    }
+
+    /** Lookup the component descriptor in the package and
+     * in the parent packages.
+     *
+     * @param beanClass
+     * @param type
+     */
+    private void findDescriptor( Class beanClass, String type ) {
+        if( type==null ) {
+            type=beanClass.getName();
+        }
+        ClassLoader classLoader=null;
+        if( beanClass!=null ) {
+            classLoader=beanClass.getClassLoader();
+        }
+        if( classLoader==null ) {
+            classLoader=Thread.currentThread().getContextClassLoader();
+        }
+        if( classLoader==null ) {
+            classLoader=this.getClass().getClassLoader();
+        }
+        
+        String className=type;
+        String pkg=className;
+        while( pkg.indexOf( ".") > 0 ) {
+            int lastComp=pkg.lastIndexOf( ".");
+            if( lastComp <= 0 ) return;
+            pkg=pkg.substring(0, lastComp);
+            if( searchedPaths.get( pkg ) != null ) {
+                return;
+            }
+            loadDescriptors(pkg, classLoader);
+        }
+        return;
+    }
+
+    private ModelerSource getModelerSource( String type )
+            throws Exception
+    {
+        if( type==null ) type="MbeansDescriptorsDigesterSource";
+        if( type.indexOf( ".") < 0 ) {
+            type="org.apache.tomcat.util.modeler.modules." + type;
+        }
+
+        Class c=Class.forName( type );
+        ModelerSource ds=(ModelerSource)c.newInstance();
+        return ds;
+    }
+
+
+    // -------------------- Registration  --------------------
+    
+    public ObjectName preRegister(MBeanServer server,
+                                  ObjectName name) throws Exception 
+    {
+        this.server=server;
+        return name;
+    }
+
+    public void postRegister(Boolean registrationDone) {
+    }
+
+    public void preDeregister() throws Exception {
+    }
+
+    public void postDeregister() {
+    }
+
+    
+    
+    
+    // -------------------- DEPRECATED METHODS  --------------------
+    // May still be used in tomcat 
+    // Never part of an official release
+    
+    /** Called by a registry or by the container to unload a loader
+     * @param loader
+     */
+    public void unregisterRegistry(ClassLoader loader ) {
+        // XXX Cleanup ?
+        perLoaderRegistries.remove(loader);
+    }
+
+    public ManagedBean findManagedBean(Class beanClass, String type)
+        throws Exception
+    {
+        return findManagedBean(null, beanClass, type);        
+    }
+    
+    /**
+     * Set the <code>MBeanServer</code> to be utilized for our
+     * registered management beans.
+     *
+     * @param server The new <code>MBeanServer</code> instance
+     */
+    public void setMBeanServer( MBeanServer server ) {
+        this.server=server;
+    }
+
+    public void resetMetadata() {
+        stop();
+    }
+    /**
+     * Load the registry from the XML input found in the specified input
+     * stream.
+     *
+     * @param source Source to be used to load. Can be an InputStream or URL.
+     *
+     * @exception Exception if any parsing or processing error occurs
+     */
+    public void loadDescriptors( Object source )
+            throws Exception
+    {
+        loadDescriptors("MbeansDescriptorsDigesterSource", source, null );
+    }
+
+    /** @deprecated - may still be used in code using pre-1.1 builds
+     */
+    public void registerComponent(Object bean, String domain, String type,
+                                  String name)
+            throws Exception
+    {
+        StringBuffer sb=new StringBuffer();
+        sb.append( domain ).append(":");
+        sb.append( name );
+        String nameStr=sb.toString();
+        ObjectName oname=new ObjectName( nameStr );
+        registerComponent(bean, oname, type );
+    }
+
+    
+
+    // should be removed
+    public void unregisterComponent( String domain, String name ) {
+        try {
+            ObjectName oname=new ObjectName( domain + ":" + name );
+
+            // XXX remove from our tables.
+            getMBeanServer().unregisterMBean( oname );
+        } catch( Throwable t ) {
+            log.error( "Error unregistering mbean ", t );
+        }
+    }
+    
+    public List loadMBeans( Object source )
+            throws Exception
+    {
+        return loadMBeans( source, null );
+    }
+
+
+    /**
+     * Load the registry from a cached .ser file. This is typically 2-3 times
+     * faster than parsing the XML.
+     *
+     * @param source Source to be used to load. Can be an InputStream or URL.
+     *
+     * @exception Exception if any parsing or processing error occurs
+     * @deprecated Loaded automatically or using a File or Url ending in .ser
+     */
+    public void loadCachedDescriptors( Object source )
+            throws Exception
+    {
+        loadDescriptors("MbeansDescriptorsSerSource", source, null );
+    }
+}

Added: tomcat/sandbox/java/org/apache/tomcat/util/modeler/RegistryMBean.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/tomcat/util/modeler/RegistryMBean.java?rev=407661&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/tomcat/util/modeler/RegistryMBean.java (added)
+++ tomcat/sandbox/java/org/apache/tomcat/util/modeler/RegistryMBean.java Thu May 18 16:27:34 2006
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2001-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.List;
+
+/**
+ * Interface for modeler MBeans.
+ * 
+ * This is the main entry point into modeler. It provides methods to create
+ * and manipulate model mbeans and simplify their use.
+ *
+ * Starting with version 1.1, this is no longer a singleton and the static
+ * methods are strongly deprecated. In a container environment we can expect
+ * different applications to use different registries.
+ * 
+ * @author Craig R. McClanahan
+ * @author Costin Manolache
+ * 
+ * @since 1.1
+ */
+public interface RegistryMBean {
+
+    /** 
+     * Load an extended mlet file. The source can be an URL, File or
+     * InputStream. 
+     * 
+     * All mbeans will be instantiated, registered and the attributes will be 
+     * set. The result is a list of ObjectNames.
+     *
+     * @param source InputStream or URL of the file
+     * @param cl ClassLoader to be used to load the mbeans, or null to use the
+     *        default JMX mechanism ( i.e. all registered loaders )
+     * @return List of ObjectName for the loaded mbeans
+     * @throws Exception
+     * 
+     * @since 1.1
+     */ 
+    public List loadMBeans( Object source, ClassLoader cl ) throws Exception;
+
+    /** Invoke an operation on a set of mbeans. 
+     * 
+     * @param mbeans List of ObjectNames
+     * @param operation Operation to perform. Typically "init" "start" "stop" or "destroy"
+     * @param failFirst Behavior in case of exceptions - if false we'll ignore
+     *      errors
+     * @throws Exception
+     */ 
+    public void invoke( List mbeans, String operation, boolean failFirst )
+            throws Exception;
+
+    /** Register a bean by creating a modeler mbean and adding it to the 
+     * MBeanServer.
+     * 
+     * If metadata is not loaded, we'll look up and read a file named
+     * "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package
+     * or parent.
+     *
+     * If the bean is an instance of DynamicMBean. it's metadata will be converted
+     * to a model mbean and we'll wrap it - so modeler services will be supported
+     *
+     * If the metadata is still not found, introspection will be used to extract
+     * it automatically. 
+     * 
+     * If an mbean is already registered under this name, it'll be first
+     * unregistered.
+     * 
+     * If the component implements MBeanRegistration, the methods will be called.
+     * If the method has a method "setRegistry" that takes a RegistryMBean as
+     * parameter, it'll be called with the current registry.
+     * 
+     *
+     * @param bean Object to be registered
+     * @param oname Name used for registration
+     * @param type The type of the mbean, as declared in mbeans-descriptors. If
+     * null, the name of the class will be used. This can be used as a hint or
+     * by subclasses.
+     *
+     * @since 1.1
+     */ 
+    public void registerComponent(Object bean, String oname, String type)
+           throws Exception;
+
+    /** Unregister a component. We'll first check if it is registered,
+     * and mask all errors. This is mostly a helper.
+     * 
+     * @param oname
+     * 
+     * @since 1.1
+     */ 
+    public void unregisterComponent( String oname );
+
+
+     /** Return an int ID for faster access. Will be used for notifications
+      * and for other operations we want to optimize. 
+      *
+      * @param domain Namespace 
+      * @param name  Type of the notification
+      * @return  An unique id for the domain:name combination
+      * @since 1.1
+      */
+    public int getId( String domain, String name);
+
+
+    /** Reset all metadata cached by this registry. Should be called 
+     * to support reloading. Existing mbeans will not be affected or modified.
+     * 
+     * It will be called automatically if the Registry is unregistered.
+     * @since 1.1
+     */ 
+    public void stop();
+
+    /** Load descriptors. The source can be a File, URL pointing to an
+     * mbeans-descriptors.xml.
+     * 
+     * Also ( experimental for now ) a ClassLoader - in which case META-INF/ will
+     * be used.
+     * 
+     * @param source
+     */ 
+    public void loadMetadata(Object source ) throws Exception;
+}



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