//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.jmx;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InvalidAttributeValueException;
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.MBeanParameterInfo;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.modelmbean.ModelMBean;

import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.ManagedOperation;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

/** 
 * ObjectMBean.
 * <p>
 * A dynamic MBean that can wrap an arbitary Object instance.
 * the attributes and methods exposed by this bean are controlled by
 * the merge of property bundles discovered by names related to all
 * superclasses and all superinterfaces.
 * <p>
 * Attributes and methods exported may be "Object" and must exist on the
 * wrapped object, or "MBean" and must exist on a subclass of OBjectMBean
 * or "MObject" which exists on the wrapped object, but whose values are
 * converted to MBean object names.
 */
public class ObjectMBean implements DynamicMBean
{
    private static final Logger LOG = Log.getLogger(ObjectMBean.class);

    private static Class<?>[] OBJ_ARG = new Class[]{Object.class};

    protected Object _managed;
    private MBeanInfo _info;
    private Map<String, Method> _getters=new HashMap<String, Method>();
    private Map<String, Method> _setters=new HashMap<String, Method>();
    private Map<String, Method> _methods=new HashMap<String, Method>();

    // set of attributes mined from influence hierarchy
    private Set<String> _attributes = new HashSet<String>();

    // set of attributes that are automatically converted to ObjectName
    // as they represent other managed beans which can be linked to
    private Set<String> _convert=new HashSet<String>();
    private ClassLoader _loader;
    private MBeanContainer _mbeanContainer;

    private static String OBJECT_NAME_CLASS = ObjectName.class.getName();
    private static String OBJECT_NAME_ARRAY_CLASS = ObjectName[].class.getName();

    /* ------------------------------------------------------------ */
    /**
     * Create MBean for Object. Attempts to create an MBean for the object by searching the package
     * and class name space. For example an object of the type
     *
     * <PRE>
     * class com.acme.MyClass extends com.acme.util.BaseClass implements com.acme.Iface
     * </PRE>
     *
     * Then this method would look for the following classes:
     * <UL>
     * <LI>com.acme.jmx.MyClassMBean
     * <LI>com.acme.util.jmx.BaseClassMBean
     * <LI>org.eclipse.jetty.jmx.ObjectMBean
     * </UL>
     *
     * @param o The object
     * @return A new instance of an MBean for the object or null.
     */
    public static Object mbeanFor(Object o)
    {
        try
        {
            Class<?> oClass = o.getClass();
            Object mbean = null;

            while ( mbean == null && oClass != null )
            {
                String pName = oClass.getPackage().getName();
                String cName = oClass.getName().substring(pName.length() + 1);
                String mName = pName + ".jmx." + cName + "MBean";

                try
                {
                    Class<?> mClass = (Object.class.equals(oClass))?oClass=ObjectMBean.class:Loader.loadClass(oClass,mName);

                    if (LOG.isDebugEnabled())
                        LOG.debug("ObjectMbean: mbeanFor {} mClass={}", o, mClass);

                    try
                    {
                        Constructor<?> constructor = mClass.getConstructor(OBJ_ARG);
                        mbean=constructor.newInstance(new Object[]{o});
                    }
                    catch(Exception e)
                    {
                        LOG.ignore(e);
                        if (ModelMBean.class.isAssignableFrom(mClass))
                        {
                            mbean=mClass.newInstance();
                            ((ModelMBean)mbean).setManagedResource(o, "objectReference");
                        }
                    }

                    if (LOG.isDebugEnabled())
                        LOG.debug("mbeanFor {} is {}", o, mbean);

                    return mbean;
                }
                catch (ClassNotFoundException e)
                {
                    // The code below was modified to fix bugs 332200 and JETTY-1416
                    // The issue was caused by additional information added to the
                    // message after the class name when running in Apache Felix,
                    // as well as before the class name when running in JBoss.
                    if (e.getMessage().contains(mName))
                        LOG.ignore(e);
                    else
                        LOG.warn(e);
                }
                catch (Error e)
                {
                    LOG.warn(e);
                    mbean = null;
                }
                catch (Exception e)
                {
                    LOG.warn(e);
                    mbean = null;
                }

                oClass = oClass.getSuperclass();
            }
        }
        catch (Exception e)
        {
            LOG.ignore(e);
        }

        return null;
    }


    public ObjectMBean(Object managedObject)
    {
        _managed = managedObject;
        _loader = Thread.currentThread().getContextClassLoader();
    }

    public Object getManagedObject()
    {
        return _managed;
    }

    public ObjectName getObjectName()
    {
        return null;
    }

    public String getObjectContextBasis()
    {
        return null;
    }

    public String getObjectNameBasis()
    {
        return null;
    }

    protected void setMBeanContainer(MBeanContainer container)
    {
       this._mbeanContainer = container;
    }

    public MBeanContainer getMBeanContainer ()
    {
        return this._mbeanContainer;
    }


    public MBeanInfo getMBeanInfo()
    {
        try
        {
            if (_info==null)
            {
                // Start with blank lazy lists attributes etc.
                String desc=null;
                List<MBeanAttributeInfo> attributes = new ArrayList<MBeanAttributeInfo>();
                List<MBeanConstructorInfo> constructors = new ArrayList<MBeanConstructorInfo>();
                List<MBeanOperationInfo> operations = new ArrayList<MBeanOperationInfo>();
                List<MBeanNotificationInfo> notifications = new ArrayList<MBeanNotificationInfo>();

                // Find list of classes that can influence the mbean
                Class<?> o_class=_managed.getClass();
                List<Class<?>> influences = new ArrayList<Class<?>>();
                influences.add(this.getClass()); // always add MBean itself
                influences = findInfluences(influences, _managed.getClass());

                if (LOG.isDebugEnabled())
                    LOG.debug("Influence Count: {}", influences.size() );

                // Process Type Annotations
                ManagedObject primary = o_class.getAnnotation( ManagedObject.class);

                if ( primary != null )
                {
                    desc = primary.value();
                }
                else
                {
                    if (LOG.isDebugEnabled())
                        LOG.debug("No @ManagedObject declared on {}", _managed.getClass());
                }


                // For each influence
                for (int i=0;i<influences.size();i++)
                {
                    Class<?> oClass = influences.get(i);

                    ManagedObject typeAnnotation = oClass.getAnnotation( ManagedObject.class );

                    if (LOG.isDebugEnabled())
                        LOG.debug("Influenced by: " + oClass.getCanonicalName() );

                    if ( typeAnnotation == null )
                    {
                        if (LOG.isDebugEnabled())
                            LOG.debug("Annotations not found for: {}", oClass.getCanonicalName() );
                        continue;
                    }

                    // Process Method Annotations

                    for (Method method : oClass.getDeclaredMethods())
                    {
                        ManagedAttribute methodAttributeAnnotation = method.getAnnotation(ManagedAttribute.class);

                        if (methodAttributeAnnotation != null)
                        {
                            // TODO sort out how a proper name could get here, its a method name as an attribute at this point.
                            if (LOG.isDebugEnabled())
                                LOG.debug("Attribute Annotation found for: {}", method.getName());
                            MBeanAttributeInfo mai = defineAttribute(method,methodAttributeAnnotation);
                            if ( mai != null )
                            {
                                attributes.add(mai);
                            }
                        }

                        ManagedOperation methodOperationAnnotation = method.getAnnotation(ManagedOperation.class);

                        if (methodOperationAnnotation != null)
                        {
                            if (LOG.isDebugEnabled())
                                LOG.debug("Method Annotation found for: {}", method.getName());
                            MBeanOperationInfo oi = defineOperation(method,methodOperationAnnotation);
                            if (oi != null)
                            {
                                operations.add(oi);
                            }
                        }
                    }

                }

                _info = new MBeanInfo(o_class.getName(),
                                desc,
                                (MBeanAttributeInfo[])attributes.toArray(new MBeanAttributeInfo[attributes.size()]),
                                (MBeanConstructorInfo[])constructors.toArray(new MBeanConstructorInfo[constructors.size()]),
                                (MBeanOperationInfo[])operations.toArray(new MBeanOperationInfo[operations.size()]),
                                (MBeanNotificationInfo[])notifications.toArray(new MBeanNotificationInfo[notifications.size()]));
            }
        }
        catch(RuntimeException e)
        {
            LOG.warn(e);
            throw e;
        }
        return _info;
    }


    /* ------------------------------------------------------------ */
    public Object getAttribute(String name) throws AttributeNotFoundException, MBeanException, ReflectionException
    {
        Method getter = (Method) _getters.get(name);
        if (getter == null)
        {
            throw new AttributeNotFoundException(name);
        }

        try
        {
            Object o = _managed;
            if (getter.getDeclaringClass().isInstance(this))
                o = this; // mbean method

            // get the attribute
            Object r=getter.invoke(o, (java.lang.Object[]) null);

            // convert to ObjectName if the type has the @ManagedObject annotation
            if (r!=null )
            {
                if (r.getClass().isArray())
                {
                    if (r.getClass().getComponentType().isAnnotationPresent(ManagedObject.class))
                    {
                        ObjectName[] on = new ObjectName[Array.getLength(r)];
                        for (int i = 0; i < on.length; i++)
                        {
                            on[i] = _mbeanContainer.findMBean(Array.get(r,i));
                        }
                        r = on;
                    }
                }
                else if (r instanceof Collection<?>)
                {
                    @SuppressWarnings("unchecked")
                    Collection<Object> c = (Collection<Object>)r;

                    if (!c.isEmpty() && c.iterator().next().getClass().isAnnotationPresent(ManagedObject.class))
                    {
                        // check the first thing out

                        ObjectName[] on = new ObjectName[c.size()];
                        int i = 0;
                        for (Object obj : c)
                        {
                            on[i++] = _mbeanContainer.findMBean(obj);
                        }
                        r = on;
                    }
                }
                else
                {
                    Class<?> clazz = r.getClass();
                    
                    while (clazz != null)
                    {
                        if (clazz.isAnnotationPresent(ManagedObject.class))
                        {
                            ObjectName mbean = _mbeanContainer.findMBean(r);

                            if (mbean != null)
                            {    
                                return mbean;
                            }
                            else
                            {
                                return null;
                            }
                        }                   
                        clazz = clazz.getSuperclass();
                    }              
                }
            }

            return r;
        }
        catch (IllegalAccessException e)
        {
            LOG.warn(Log.EXCEPTION, e);
            throw new AttributeNotFoundException(e.toString());
        }
        catch (InvocationTargetException e)
        {
            LOG.warn(Log.EXCEPTION, e);
            throw new ReflectionException(new Exception(e.getCause()));
        }
    }

    /* ------------------------------------------------------------ */
    public AttributeList getAttributes(String[] names)
    {
        AttributeList results = new AttributeList(names.length);
        for (int i = 0; i < names.length; i++)
        {
            try
            {
                results.add(new Attribute(names[i], getAttribute(names[i])));
            }
            catch (Exception e)
            {
                LOG.warn(Log.EXCEPTION, e);
            }
        }
        return results;
    }

    /* ------------------------------------------------------------ */
    public void setAttribute(Attribute attr) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException
    {
        if (attr == null)
            return;

        if (LOG.isDebugEnabled())
            LOG.debug("setAttribute " + _managed + ":" +attr.getName() + "=" + attr.getValue());
        Method setter = (Method) _setters.get(attr.getName());
        if (setter == null)
            throw new AttributeNotFoundException(attr.getName());
        try
        {
            Object o = _managed;
            if (setter.getDeclaringClass().isInstance(this))
                o = this;

            // get the value
            Object value = attr.getValue();

            // convert from ObjectName if need be
            if (value!=null && _convert.contains(attr.getName()))
            {
                if (value.getClass().isArray())
                {
                    Class<?> t=setter.getParameterTypes()[0].getComponentType();
                    Object na = Array.newInstance(t,Array.getLength(value));
                    for (int i=Array.getLength(value);i-->0;)
                        Array.set(na, i, _mbeanContainer.findBean((ObjectName)Array.get(value, i)));
                    value=na;
                }
                else
                    value=_mbeanContainer.findBean((ObjectName)value);
            }

            // do the setting
            setter.invoke(o, new Object[]{ value });
        }
        catch (IllegalAccessException e)
        {
            LOG.warn(Log.EXCEPTION, e);
            throw new AttributeNotFoundException(e.toString());
        }
        catch (InvocationTargetException e)
        {
            LOG.warn(Log.EXCEPTION, e);
            throw new ReflectionException(new Exception(e.getCause()));
        }
    }

    /* ------------------------------------------------------------ */
    public AttributeList setAttributes(AttributeList attrs)
    {
        if (LOG.isDebugEnabled())
            LOG.debug("setAttributes");

        AttributeList results = new AttributeList(attrs.size());
        Iterator<Object> iter = attrs.iterator();
        while (iter.hasNext())
        {
            try
            {
                Attribute attr = (Attribute) iter.next();
                setAttribute(attr);
                results.add(new Attribute(attr.getName(), getAttribute(attr.getName())));
            }
            catch (Exception e)
            {
                LOG.warn(Log.EXCEPTION, e);
            }
        }
        return results;
    }

    /* ------------------------------------------------------------ */
    public Object invoke(String name, Object[] params, String[] signature) throws MBeanException, ReflectionException
    {
        if (LOG.isDebugEnabled())
            LOG.debug("ObjectMBean:invoke " + name);

        String methodKey = name + "(";
        if (signature != null)
            for (int i = 0; i < signature.length; i++)
                methodKey += (i > 0 ? "," : "") + signature[i];
        methodKey += ")";

        ClassLoader old_loader=Thread.currentThread().getContextClassLoader();
        try
        {
            Thread.currentThread().setContextClassLoader(_loader);
            Method method = (Method) _methods.get(methodKey);
            if (method == null)
                throw new NoSuchMethodException(methodKey);

            Object o = _managed;

            if (method.getDeclaringClass().isInstance(this))
            {
                o = this;
            }
            return method.invoke(o, params);
        }
        catch (NoSuchMethodException e)
        {
            LOG.warn(Log.EXCEPTION, e);
            throw new ReflectionException(e);
        }
        catch (IllegalAccessException e)
        {
            LOG.warn(Log.EXCEPTION, e);
            throw new MBeanException(e);
        }
        catch (InvocationTargetException e)
        {
            LOG.warn(Log.EXCEPTION, e);
            throw new ReflectionException(new Exception(e.getCause()));
        }
        finally
        {
            Thread.currentThread().setContextClassLoader(old_loader);
        }
    }

    private static List<Class<?>> findInfluences(List<Class<?>> influences, Class<?> aClass)
    {
        if (aClass != null)
        {
            if (!influences.contains(aClass))
            {
                // This class is a new influence
                influences.add(aClass);
            }

            // So are the super classes
            influences = findInfluences(influences,aClass.getSuperclass());

            // So are the interfaces
            Class<?>[] ifs = aClass.getInterfaces();
            for (int i = 0; ifs != null && i < ifs.length; i++)
            {
                influences = findInfluences(influences,ifs[i]);
            }
        }

        return influences;
    }

    /* ------------------------------------------------------------ */
    /**
     * TODO update to new behavior
     *
     * Define an attribute on the managed object. The meta data is defined by looking for standard
     * getter and setter methods. Descriptions are obtained with a call to findDescription with the
     * attribute name.
     *
     * @param method the method to define
     * @param attributeAnnotation "description" or "access:description" or "type:access:description"  where type is
     * one of: <ul>
     * <li>"Object" The field/method is on the managed object.
     * <li>"MBean" The field/method is on the mbean proxy object
     * <li>"MObject" The field/method is on the managed object and value should be converted to MBean reference
     * <li>"MMBean" The field/method is on the mbean proxy object and value should be converted to MBean reference
     * </ul>
     * the access is either "RW" or "RO".
     * @return the mbean attribute info for the method
     */
    public MBeanAttributeInfo defineAttribute(Method method, ManagedAttribute attributeAnnotation)
    {
        // determine the name of the managed attribute
        String name = attributeAnnotation.name();

        if ("".equals(name))
        {
            name = toVariableName(method.getName());
        }

        if ( _attributes.contains(name))
        {
            return null; // we have an attribute named this already
        }

        String description = attributeAnnotation.value();
        boolean readonly = attributeAnnotation.readonly();
        boolean onMBean = attributeAnnotation.proxied();

        boolean convert = false;

        // determine if we should convert
        Class<?> return_type = method.getReturnType();

        // get the component type
        Class<?> component_type = return_type;
        while ( component_type.isArray() )
        {
            component_type = component_type.getComponentType();
        }
           
        // Test to see if the returnType or any of its super classes are managed objects
        convert = isAnnotationPresent(component_type, ManagedObject.class);       
        
        String uName = name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1);
        Class<?> oClass = onMBean ? this.getClass() : _managed.getClass();

        if (LOG.isDebugEnabled())
            LOG.debug("defineAttribute {} {}:{}:{}:{}",name,onMBean,readonly,oClass,description);

        Method setter = null;

        // dig out a setter if one exists
        if (!readonly)
        {
            String declaredSetter = attributeAnnotation.setter();

            if (LOG.isDebugEnabled())
                LOG.debug("DeclaredSetter: {}", declaredSetter);

            Method[] methods = oClass.getMethods();
            for (int m = 0; m < methods.length; m++)
            {
                if ((methods[m].getModifiers() & Modifier.PUBLIC) == 0)
                    continue;

                if (!"".equals(declaredSetter))
                {

                    // look for a declared setter
                    if (methods[m].getName().equals(declaredSetter) && methods[m].getParameterCount() == 1)
                    {
                        if (setter != null)
                        {
                            LOG.warn("Multiple setters for mbean attr {} in {}", name, oClass);
                            continue;
                        }
                        setter = methods[m];
                        if ( !component_type.equals(methods[m].getParameterTypes()[0]))
                        {
                            LOG.warn("Type conflict for mbean attr {} in {}", name, oClass);
                            continue;
                        }
                        if (LOG.isDebugEnabled())
                            LOG.debug("Declared Setter: " + declaredSetter);
                    }
                }

                // look for a setter
                if ( methods[m].getName().equals("set" + uName) && methods[m].getParameterCount() == 1)
                {
                    if (setter != null)
                    {
                        LOG.warn("Multiple setters for mbean attr {} in {}", name, oClass);
                        continue;
                    }
                    setter = methods[m];
                    if ( !return_type.equals(methods[m].getParameterTypes()[0]))
                    {                            
                        LOG.warn("Type conflict for mbean attr {} in {}", name, oClass);
                        continue;
                    }
                }
            }
        }

        if (convert)
        {
            if (component_type==null)
            {
                LOG.warn("No mbean type for {} on {}", name, _managed.getClass());
                return null;
            }

            if (component_type.isPrimitive() && !component_type.isArray())
            {
                LOG.warn("Cannot convert mbean primative {}", name);
                return null;
            }
            if (LOG.isDebugEnabled())
                LOG.debug("passed convert checks {} for type {}", name, component_type);
        }

        try
        {
            // Remember the methods
            _getters.put(name, method);
            _setters.put(name, setter);

            MBeanAttributeInfo info=null;
            if (convert)
            {
                _convert.add(name);

                if (component_type.isArray())
                {
                    info= new MBeanAttributeInfo(name,OBJECT_NAME_ARRAY_CLASS,description,true,setter!=null,method.getName().startsWith("is"));
                }
                else
                {
                    info= new MBeanAttributeInfo(name,OBJECT_NAME_CLASS,description,true,setter!=null,method.getName().startsWith("is"));
                }
            }
            else
            {
                info= new MBeanAttributeInfo(name,description,method,setter);
            }

            _attributes.add(name);
            
            return info;
        }
        catch (Exception e)
        {
            LOG.warn(e);
            throw new IllegalArgumentException(e.toString());
        }
    }


    /* ------------------------------------------------------------ */
    /**
     *  TODO update to new behavior
     *
     * Define an operation on the managed object. Defines an operation with parameters. Refection is
     * used to determine find the method and it's return type. The description of the method is
     * found with a call to findDescription on "name(signature)". The name and description of each
     * parameter is found with a call to findDescription with "name(signature)[n]", the returned
     * description is for the last parameter of the partial signature and is assumed to start with
     * the parameter name, followed by a colon.
     *
     * @param metaData "description" or "impact:description" or "type:impact:description", type is
     * the "Object","MBean", "MMBean" or "MObject" to indicate the method is on the object, the MBean or on the
     * object but converted to an MBean reference, and impact is either "ACTION","INFO","ACTION_INFO" or "UNKNOWN".
     */
    private MBeanOperationInfo defineOperation(Method method, ManagedOperation methodAnnotation)
    {
        String description = methodAnnotation.value();
        boolean onMBean = methodAnnotation.proxied();

        boolean convert = false;

        // determine if we should convert
        Class<?> returnType = method.getReturnType();

        if ( returnType.isArray() )
        {
            if (LOG.isDebugEnabled())
                LOG.debug("returnType is array, get component type");
            returnType = returnType.getComponentType();
        }

        if ( returnType.isAnnotationPresent(ManagedObject.class))
        {
            convert = true;
        }

        String impactName = methodAnnotation.impact();

        if (LOG.isDebugEnabled())
            LOG.debug("defineOperation {} {}:{}:{}", method.getName(), onMBean, impactName, description);

        String signature = method.getName();

        try
        {
            // Resolve the impact
            int impact=MBeanOperationInfo.UNKNOWN;
            if (impactName==null || impactName.equals("UNKNOWN"))
                impact=MBeanOperationInfo.UNKNOWN;
            else if (impactName.equals("ACTION"))
                impact=MBeanOperationInfo.ACTION;
            else if (impactName.equals("INFO"))
                impact=MBeanOperationInfo.INFO;
            else if (impactName.equals("ACTION_INFO"))
                impact=MBeanOperationInfo.ACTION_INFO;
            else
                LOG.warn("Unknown impact '"+impactName+"' for "+signature);


            Annotation[][] allParameterAnnotations = method.getParameterAnnotations();
            Class<?>[] methodTypes = method.getParameterTypes();
            MBeanParameterInfo[] pInfo = new MBeanParameterInfo[allParameterAnnotations.length];

            for ( int i = 0 ; i < allParameterAnnotations.length ; ++i )
            {
                Annotation[] parameterAnnotations = allParameterAnnotations[i];

                for ( Annotation anno : parameterAnnotations )
                {
                    if ( anno instanceof Name )
                    {
                        Name nameAnnotation = (Name) anno;

                        pInfo[i] = new MBeanParameterInfo(nameAnnotation.value(),methodTypes[i].getName(),nameAnnotation.description());
                    }
                }
            }

            signature += "(";
            for ( int i = 0 ; i < methodTypes.length ; ++i )
            {
                signature += methodTypes[i].getName();

                if ( i != methodTypes.length - 1 )
                {
                    signature += ",";
                }
            }
            signature += ")";

            Class<?> returnClass = method.getReturnType();

            if (LOG.isDebugEnabled())
                LOG.debug("Method Cache: " + signature );

            if ( _methods.containsKey(signature) )
            {
                return null; // we have an operation for this already
            }

            _methods.put(signature, method);
            if (convert)
                _convert.add(signature);

            return new MBeanOperationInfo(method.getName(), description, pInfo, returnClass.isPrimitive() ? TypeUtil.toName(returnClass) : (returnClass.getName()), impact);
        }
        catch (Exception e)
        {
            LOG.warn("Operation '"+signature+"'", e);
            throw new IllegalArgumentException(e.toString());
        }

    }

    protected String toVariableName( String methodName )
    {
        String variableName = methodName;

        if ( methodName.startsWith("get") || methodName.startsWith("set") )
        {
            variableName = variableName.substring(3);
        }
        else if ( methodName.startsWith("is") )
        {
            variableName = variableName.substring(2);
        }

        variableName = variableName.substring(0,1).toLowerCase(Locale.ENGLISH) + variableName.substring(1);

        return variableName;
    }
    
    protected boolean isAnnotationPresent(Class<?> clazz, Class<? extends Annotation> annotation)
    {
        Class<?> test = clazz;
        
        while (test != null )
        {  
            if ( test.isAnnotationPresent(annotation))
            {
                return true;
            }
            else
            {
                test = test.getSuperclass();
            }
        }
        return false;
    }
}
