/*
 * Portions Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
/*
 * @author    IBM Corp.
 *
 * Copyright IBM Corp. 1999-2000.  All rights reserved.
 */

package javax.management.modelmbean;

import static com.sun.jmx.defaults.JmxProperties.MODELMBEAN_LOGGER;
import com.sun.jmx.mbeanserver.GetPropertyAction;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.security.AccessController;
import java.util.logging.Level;

import javax.management.Descriptor;
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.RuntimeOperationsException;

/**
 * This class represents the meta data for ModelMBeans.  Descriptors have been
 * added on the meta data objects.
 * <P>
 * Java resources wishing to be manageable instantiate the ModelMBean using the
 * MBeanServer's createMBean method.  The resource then sets the ModelMBeanInfo
 * and Descriptors for the ModelMBean instance. The attributes and operations
 * exposed via the ModelMBeanInfo for the ModelMBean are accessible
 * from MBeans, connectors/adaptors like other MBeans. Through the Descriptors,
 * values and methods in the managed application can be defined and mapped to
 * attributes and operations of the ModelMBean.
 * This mapping can be defined during development in a file or dynamically and
 * programmatically at runtime.
 * <P>
 * Every ModelMBean which is instantiated in the MBeanServer becomes manageable:
 * its attributes and operations
 * become remotely accessible through the connectors/adaptors connected to that
 * MBeanServer.
 * A Java object cannot be registered in the MBeanServer unless it is a JMX
 * compliant MBean.
 * By instantiating a ModelMBean, resources are guaranteed that the MBean is
 * valid.
 *
 * MBeanException and RuntimeOperationsException must be thrown on every public
 * method.  This allows for wrapping exceptions from distributed
 * communications (RMI, EJB, etc.)
 *
 * <p>The <b>serialVersionUID</b> of this class is
 * <code>-1935722590756516193L</code>.
 *
 * @since 1.5
 */
@SuppressWarnings("serial")
public class ModelMBeanInfoSupport extends MBeanInfo implements ModelMBeanInfo {

    // Serialization compatibility stuff:
    // Two serial forms are supported in this class. The selected form depends
    // on system property "jmx.serial.form":
    //  - "1.0" for JMX 1.0
    //  - any other value for JMX 1.1 and higher
    //
    // Serial version for old serial form
    private static final long oldSerialVersionUID = -3944083498453227709L;
    //
    // Serial version for new serial form
    private static final long newSerialVersionUID = -1935722590756516193L;
    //
    // Serializable fields in old serial form
    private static final ObjectStreamField[] oldSerialPersistentFields =
    {
        new ObjectStreamField("modelMBeanDescriptor", Descriptor.class),
                new ObjectStreamField("mmbAttributes", MBeanAttributeInfo[].class),
                new ObjectStreamField("mmbConstructors", MBeanConstructorInfo[].class),
                new ObjectStreamField("mmbNotifications", MBeanNotificationInfo[].class),
                new ObjectStreamField("mmbOperations", MBeanOperationInfo[].class),
                new ObjectStreamField("currClass", String.class)
    };
    //
    // Serializable fields in new serial form
    private static final ObjectStreamField[] newSerialPersistentFields =
    {
        new ObjectStreamField("modelMBeanDescriptor", Descriptor.class),
                new ObjectStreamField("modelMBeanAttributes", MBeanAttributeInfo[].class),
                new ObjectStreamField("modelMBeanConstructors", MBeanConstructorInfo[].class),
                new ObjectStreamField("modelMBeanNotifications", MBeanNotificationInfo[].class),
                new ObjectStreamField("modelMBeanOperations", MBeanOperationInfo[].class)
    };
    //
    // Actual serial version and serial form
    private static final long serialVersionUID;
    /**
     * @serialField modelMBeanDescriptor Descriptor The descriptor containing
     *              MBean wide policy
     * @serialField modelMBeanAttributes ModelMBeanAttributeInfo[] The array of
     *              {@link ModelMBeanAttributeInfo} objects which
     *              have descriptors
     * @serialField modelMBeanConstructors MBeanConstructorInfo[] The array of
     *              {@link ModelMBeanConstructorInfo} objects which
     *              have descriptors
     * @serialField modelMBeanNotifications MBeanNotificationInfo[] The array of
     *              {@link ModelMBeanNotificationInfo} objects which
     *              have descriptors
     * @serialField modelMBeanOperations MBeanOperationInfo[] The array of
     *              {@link ModelMBeanOperationInfo} objects which
     *              have descriptors
     */
    private static final ObjectStreamField[] serialPersistentFields;
    private static boolean compat = false;
    static {
        try {
            GetPropertyAction act = new GetPropertyAction("jmx.serial.form");
            String form = AccessController.doPrivileged(act);
            compat = (form != null && form.equals("1.0"));
        } catch (Exception e) {
            // OK: No compat with 1.0
        }
        if (compat) {
            serialPersistentFields = oldSerialPersistentFields;
            serialVersionUID = oldSerialVersionUID;
        } else {
            serialPersistentFields = newSerialPersistentFields;
            serialVersionUID = newSerialVersionUID;
        }
    }
    //
    // END Serialization compatibility stuff

    /**
     * @serial The descriptor containing MBean wide policy
     */
    private Descriptor modelMBeanDescriptor = null;

    /* The following fields always have the same values as the
       fields inherited from MBeanInfo and are retained only for
       compatibility.  By rewriting the serialization code we could
       get rid of them.

       These fields can't be final because they are assigned to by
       readObject().  */

    /**
     * @serial The array of {@link ModelMBeanAttributeInfo} objects which
     *         have descriptors
     */
    private MBeanAttributeInfo[] modelMBeanAttributes;

    /**
     * @serial The array of {@link ModelMBeanConstructorInfo} objects which
     *         have descriptors
     */
    private MBeanConstructorInfo[] modelMBeanConstructors;

    /**
     * @serial The array of {@link ModelMBeanNotificationInfo} objects which
     *         have descriptors
     */
    private MBeanNotificationInfo[] modelMBeanNotifications;

    /**
     * @serial The array of {@link ModelMBeanOperationInfo} objects which
     *         have descriptors
     */
    private MBeanOperationInfo[] modelMBeanOperations;

    private static final String ATTR = "attribute";
    private static final String OPER = "operation";
    private static final String NOTF = "notification";
    private static final String CONS = "constructor";
    private static final String MMB = "mbean";
    private static final String ALL = "all";
    private static final String currClass = "ModelMBeanInfoSupport";

    /**
     * Constructs a ModelMBeanInfoSupport which is a duplicate of the given
     * ModelMBeanInfo.  The returned object is a shallow copy of the given
     * object.  Neither the Descriptor nor the contained arrays
     * ({@code ModelMBeanAttributeInfo[]} etc) are cloned.  This method is
     * chiefly of interest to modify the Descriptor of the returned instance
     * via {@link #setDescriptor setDescriptor} without affecting the
     * Descriptor of the original object.
     *
     * @param mbi the ModelMBeanInfo instance from which the ModelMBeanInfo
     * being created is initialized.
     */
    public ModelMBeanInfoSupport(ModelMBeanInfo  mbi) {
        super(mbi.getClassName(),
                mbi.getDescription(),
                mbi.getAttributes(),
                mbi.getConstructors(),
                mbi.getOperations(),
                mbi.getNotifications());

        modelMBeanAttributes = mbi.getAttributes();
        modelMBeanConstructors = mbi.getConstructors();
        modelMBeanOperations = mbi.getOperations();
        modelMBeanNotifications = mbi.getNotifications();

        try {
            Descriptor mbeandescriptor = mbi.getMBeanDescriptor();
            modelMBeanDescriptor = validDescriptor(mbeandescriptor);
        } catch (MBeanException mbe) {
            modelMBeanDescriptor = validDescriptor(null);
            if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
                MODELMBEAN_LOGGER.logp(Level.FINER,
                        ModelMBeanInfoSupport.class.getName(),
                        "ModelMBeanInfo(ModelMBeanInfo)",
                        "Could not get a valid modelMBeanDescriptor, " +
                        "setting a default Descriptor");
            }
        }

        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "ModelMBeanInfo(ModelMBeanInfo)", "Exit");
        }
    }

    /**
     * Creates a ModelMBeanInfoSupport with the provided information,
     * but the descriptor is a default.
     * The default descriptor is: name=className, descriptorType="mbean",
     * displayName=className, persistPolicy="never", log="F", visibility="1"
     *
     * @param className classname of the MBean
     * @param description human readable description of the
     * ModelMBean
     * @param attributes array of ModelMBeanAttributeInfo objects
     * which have descriptors
     * @param constructors array of ModelMBeanConstructorInfo
     * objects which have descriptors
     * @param operations array of ModelMBeanOperationInfo objects
     * which have descriptors
     * @param notifications array of ModelMBeanNotificationInfo
     * objects which have descriptors
     */
    public ModelMBeanInfoSupport(String className,
            String description,
            ModelMBeanAttributeInfo[] attributes,
            ModelMBeanConstructorInfo[] constructors,
            ModelMBeanOperationInfo[] operations,
            ModelMBeanNotificationInfo[] notifications) {
        this(className, description, attributes, constructors,
                operations, notifications, null);
    }

    /**
     * Creates a ModelMBeanInfoSupport with the provided information
     * and the descriptor given in parameter.
     *
     * @param className classname of the MBean
     * @param description human readable description of the
     * ModelMBean
     * @param attributes array of ModelMBeanAttributeInfo objects
     * which have descriptors
     * @param constructors array of ModelMBeanConstructorInfo
     * objects which have descriptor
     * @param operations array of ModelMBeanOperationInfo objects
     * which have descriptor
     * @param notifications array of ModelMBeanNotificationInfo
     * objects which have descriptor
     * @param mbeandescriptor descriptor to be used as the
     * MBeanDescriptor containing MBean wide policy. If the
     * descriptor is null, a default descriptor will be constructed.
     * The default descriptor is:
     * name=className, descriptorType="mbean", displayName=className,
     * persistPolicy="never", log="F", visibility="1".  If the descriptor
     * does not contain all of these fields, the missing ones are
     * added with these default values.
     *
     * @exception RuntimeOperationsException Wraps an
     * IllegalArgumentException for invalid descriptor passed in
     * parameter.  (see {@link #getMBeanDescriptor
     * getMBeanDescriptor} for the definition of a valid MBean
     * descriptor.)
     */

    public ModelMBeanInfoSupport(String    className,
            String description,
            ModelMBeanAttributeInfo[] attributes,
            ModelMBeanConstructorInfo[] constructors,
            ModelMBeanOperationInfo[] operations,
            ModelMBeanNotificationInfo[] notifications,
            Descriptor mbeandescriptor) {
        super(className,
                description,
                (attributes != null) ? attributes : NO_ATTRIBUTES,
                (constructors != null) ? constructors : NO_CONSTRUCTORS,
                (operations != null) ? operations : NO_OPERATIONS,
                (notifications != null) ? notifications : NO_NOTIFICATIONS);
        /* The values saved here are possibly null, but we
           check this everywhere they are referenced.  If at
           some stage we replace null with an empty array
           here, as we do in the superclass constructor
           parameters, then we must also do this in
           readObject().  */
        modelMBeanAttributes = attributes;
        modelMBeanConstructors = constructors;
        modelMBeanOperations = operations;
        modelMBeanNotifications = notifications;
        modelMBeanDescriptor = validDescriptor(mbeandescriptor);
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "ModelMBeanInfoSupport(String,String,ModelMBeanAttributeInfo[]," +
                    "ModelMBeanConstructorInfo[],ModelMBeanOperationInfo[]," +
                    "ModelMBeanNotificationInfo[],Descriptor)",
                    "Exit");
        }
    }

    private static final ModelMBeanAttributeInfo[] NO_ATTRIBUTES =
            new ModelMBeanAttributeInfo[0];
    private static final ModelMBeanConstructorInfo[] NO_CONSTRUCTORS =
            new ModelMBeanConstructorInfo[0];
    private static final ModelMBeanNotificationInfo[] NO_NOTIFICATIONS =
            new ModelMBeanNotificationInfo[0];
    private static final ModelMBeanOperationInfo[] NO_OPERATIONS =
            new ModelMBeanOperationInfo[0];

    // Java doc inherited from MOdelMBeanInfo interface

    /**
     * Returns a shallow clone of this instance.  Neither the Descriptor nor
     * the contained arrays ({@code ModelMBeanAttributeInfo[]} etc) are
     * cloned.  This method is chiefly of interest to modify the Descriptor
     * of the clone via {@link #setDescriptor setDescriptor} without affecting
     * the Descriptor of the original object.
     *
     * @return a shallow clone of this instance.
     */
    public Object clone() {
        return(new ModelMBeanInfoSupport(this));
    }


    public Descriptor[] getDescriptors(String inDescriptorType)
    throws MBeanException, RuntimeOperationsException {
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "getDescriptors(String)", "Entry");
        }

        if ((inDescriptorType == null) || (inDescriptorType.isEmpty())) {
            inDescriptorType = "all";
        }

        // if no descriptors of that type, will return empty array
        //
        final Descriptor[] retList;

        if (inDescriptorType.equalsIgnoreCase(MMB)) {
            retList = new Descriptor[] {modelMBeanDescriptor};
        } else if (inDescriptorType.equalsIgnoreCase(ATTR)) {
            final MBeanAttributeInfo[] attrList = modelMBeanAttributes;
            int numAttrs = 0;
            if (attrList != null) numAttrs = attrList.length;

            retList = new Descriptor[numAttrs];
            for (int i=0; i < numAttrs; i++) {
                retList[i] = (((ModelMBeanAttributeInfo)
                    attrList[i]).getDescriptor());
            }
        } else if (inDescriptorType.equalsIgnoreCase(OPER)) {
            final MBeanOperationInfo[] operList = modelMBeanOperations;
            int numOpers = 0;
            if (operList != null) numOpers = operList.length;

            retList = new Descriptor[numOpers];
            for (int i=0; i < numOpers; i++) {
                retList[i] = (((ModelMBeanOperationInfo)
                    operList[i]).getDescriptor());
            }
        } else if (inDescriptorType.equalsIgnoreCase(CONS)) {
            final MBeanConstructorInfo[] consList =  modelMBeanConstructors;
            int numCons = 0;
            if (consList != null) numCons = consList.length;

            retList = new Descriptor[numCons];
            for (int i=0; i < numCons; i++) {
                retList[i] = (((ModelMBeanConstructorInfo)
                    consList[i]).getDescriptor());
            }
        } else if (inDescriptorType.equalsIgnoreCase(NOTF)) {
            final MBeanNotificationInfo[] notifList = modelMBeanNotifications;
            int numNotifs = 0;
            if (notifList != null) numNotifs = notifList.length;

            retList = new Descriptor[numNotifs];
            for (int i=0; i < numNotifs; i++) {
                retList[i] = (((ModelMBeanNotificationInfo)
                    notifList[i]).getDescriptor());
            }
        } else if (inDescriptorType.equalsIgnoreCase(ALL)) {

            final MBeanAttributeInfo[] attrList = modelMBeanAttributes;
            int numAttrs = 0;
            if (attrList != null) numAttrs = attrList.length;

            final MBeanOperationInfo[] operList = modelMBeanOperations;
            int numOpers = 0;
            if (operList != null) numOpers = operList.length;

            final MBeanConstructorInfo[] consList = modelMBeanConstructors;
            int numCons = 0;
            if (consList != null) numCons = consList.length;

            final MBeanNotificationInfo[] notifList = modelMBeanNotifications;
            int numNotifs = 0;
            if (notifList != null) numNotifs = notifList.length;

            int count = numAttrs + numCons + numOpers + numNotifs + 1;
            retList = new Descriptor[count];

            retList[count-1] = modelMBeanDescriptor;

            int j=0;
            for (int i=0; i < numAttrs; i++) {
                retList[j] = (((ModelMBeanAttributeInfo)
                    attrList[i]).getDescriptor());
                j++;
            }
            for (int i=0; i < numCons; i++) {
                retList[j] = (((ModelMBeanConstructorInfo)
                    consList[i]).getDescriptor());
                j++;
            }
            for (int i=0; i < numOpers; i++) {
                retList[j] = (((ModelMBeanOperationInfo)operList[i]).
                        getDescriptor());
                j++;
            }
            for (int i=0; i < numNotifs; i++) {
                retList[j] = (((ModelMBeanNotificationInfo)notifList[i]).
                        getDescriptor());
                j++;
            }
        } else {
            final IllegalArgumentException iae =
                    new IllegalArgumentException("Descriptor Type is invalid");
            final String msg = "Exception occurred trying to find"+
                    " the descriptors of the MBean";
            throw new RuntimeOperationsException(iae,msg);
        }
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "getDescriptors(String)", "Exit");
        }

        return retList;
    }


    public void setDescriptors(Descriptor[] inDescriptors)
    throws MBeanException, RuntimeOperationsException {
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "setDescriptors(Descriptor[])", "Entry");
        }
        if (inDescriptors==null) {
            // throw RuntimeOperationsException - invalid descriptor
            throw new RuntimeOperationsException(
                    new IllegalArgumentException("Descriptor list is invalid"),
                    "Exception occurred trying to set the descriptors " +
                    "of the MBeanInfo");
        }
        if (inDescriptors.length == 0) { // empty list, no-op
            return;
        }
        for (int j=0; j < inDescriptors.length; j++) {
            setDescriptor(inDescriptors[j],null);
        }
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "setDescriptors(Descriptor[])", "Exit");
        }

    }


    /**
     * Returns a Descriptor requested by name.
     *
     * @param inDescriptorName The name of the descriptor.
     *
     * @return Descriptor containing a descriptor for the ModelMBean with the
     *         same name. If no descriptor is found, null is returned.
     *
     * @exception MBeanException Wraps a distributed communication Exception.
     * @exception RuntimeOperationsException Wraps an IllegalArgumentException
     *            for null name.
     *
     * @see #setDescriptor
     */

    public Descriptor getDescriptor(String inDescriptorName)
    throws MBeanException, RuntimeOperationsException {
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "getDescriptor(String)", "Entry");
        }
        return(getDescriptor(inDescriptorName, null));
    }


    public Descriptor getDescriptor(String inDescriptorName,
            String inDescriptorType)
            throws MBeanException, RuntimeOperationsException {
        if (inDescriptorName==null) {
            // throw RuntimeOperationsException - invalid descriptor
            throw new RuntimeOperationsException(
                    new IllegalArgumentException("Descriptor is invalid"),
                    "Exception occurred trying to set the descriptors of " +
                    "the MBeanInfo");
        }

        if (MMB.equalsIgnoreCase(inDescriptorType)) {
            return (Descriptor) modelMBeanDescriptor.clone();
        }

            /* The logic here is a bit convoluted, because we are
               dealing with two possible cases, depending on whether
               inDescriptorType is null.  If it's not null, then only
               one of the following ifs will run, and it will either
               return a descriptor or null.  If inDescriptorType is
               null, then all of the following ifs will run until one
               of them finds a descriptor.  */
        if (ATTR.equalsIgnoreCase(inDescriptorType) || inDescriptorType == null) {
            ModelMBeanAttributeInfo attr = getAttribute(inDescriptorName);
            if (attr != null)
                return attr.getDescriptor();
            if (inDescriptorType != null)
                return null;
        }
        if (OPER.equalsIgnoreCase(inDescriptorType) || inDescriptorType == null) {
            ModelMBeanOperationInfo oper = getOperation(inDescriptorName);
            if (oper != null)
                return oper.getDescriptor();
            if (inDescriptorType != null)
                return null;
        }
        if (CONS.equalsIgnoreCase(inDescriptorType) || inDescriptorType == null) {
            ModelMBeanConstructorInfo oper =
                    getConstructor(inDescriptorName);
            if (oper != null)
                return oper.getDescriptor();
            if (inDescriptorType != null)
                return null;
        }
        if (NOTF.equalsIgnoreCase(inDescriptorType) || inDescriptorType == null) {
            ModelMBeanNotificationInfo notif =
                    getNotification(inDescriptorName);
            if (notif != null)
                return notif.getDescriptor();
            if (inDescriptorType != null)
                return null;
        }
        if (inDescriptorType == null)
            return null;
        throw new RuntimeOperationsException(
                new IllegalArgumentException("Descriptor Type is invalid"),
                "Exception occurred trying to find the descriptors of the MBean");

    }



    public void setDescriptor(Descriptor inDescriptor,
            String inDescriptorType)
            throws MBeanException, RuntimeOperationsException {
        final String excMsg =
                "Exception occurred trying to set the descriptors of the MBean";
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "setDescriptor(Descriptor,String)", "Entry");
        }

        if (inDescriptor==null) {
            inDescriptor = new DescriptorSupport();
        }

        if ((inDescriptorType == null) || (inDescriptorType.isEmpty())) {
            inDescriptorType =
                    (String) inDescriptor.getFieldValue("descriptorType");

            if (inDescriptorType == null) {
                   MODELMBEAN_LOGGER.logp(Level.FINER,
                                ModelMBeanInfoSupport.class.getName(),
                                "setDescriptor(Descriptor,String)",
                                "descriptorType null in both String parameter and Descriptor, defaulting to "+ MMB);
                inDescriptorType = MMB;
            }
        }

        String inDescriptorName =
                (String) inDescriptor.getFieldValue("name");
        if (inDescriptorName == null) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                                ModelMBeanInfoSupport.class.getName(),
                                "setDescriptor(Descriptor,String)",
                                "descriptor name null, defaulting to "+ this.getClassName());
            inDescriptorName = this.getClassName();
        }
        boolean found = false;
        if (inDescriptorType.equalsIgnoreCase(MMB)) {
            setMBeanDescriptor(inDescriptor);
            found = true;
        } else if (inDescriptorType.equalsIgnoreCase(ATTR)) {
            MBeanAttributeInfo[] attrList =  modelMBeanAttributes;
            int numAttrs = 0;
            if (attrList != null) numAttrs = attrList.length;

            for (int i=0; i < numAttrs; i++) {
                if (inDescriptorName.equals(attrList[i].getName())) {
                    found = true;
                    ModelMBeanAttributeInfo mmbai =
                            (ModelMBeanAttributeInfo) attrList[i];
                    mmbai.setDescriptor(inDescriptor);
                    if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
                        StringBuilder strb = new StringBuilder()
                        .append("Setting descriptor to ").append(inDescriptor)
                        .append("\t\n local: AttributeInfo descriptor is ")
                        .append(mmbai.getDescriptor())
                        .append("\t\n modelMBeanInfo: AttributeInfo descriptor is ")
                        .append(this.getDescriptor(inDescriptorName,"attribute"));
                        MODELMBEAN_LOGGER.logp(Level.FINER,
                                ModelMBeanInfoSupport.class.getName(),
                                "setDescriptor(Descriptor,String)",
                                strb.toString());
                    }
                }
            }
        } else if (inDescriptorType.equalsIgnoreCase(OPER)) {
            MBeanOperationInfo[] operList =  modelMBeanOperations;
            int numOpers = 0;
            if (operList != null) numOpers = operList.length;

            for (int i=0; i < numOpers; i++) {
                if (inDescriptorName.equals(operList[i].getName())) {
                    found = true;
                    ModelMBeanOperationInfo mmboi =
                            (ModelMBeanOperationInfo) operList[i];
                    mmboi.setDescriptor(inDescriptor);
                }
            }
        } else if (inDescriptorType.equalsIgnoreCase(CONS)) {
            MBeanConstructorInfo[] consList =  modelMBeanConstructors;
            int numCons = 0;
            if (consList != null) numCons = consList.length;

            for (int i=0; i < numCons; i++) {
                if (inDescriptorName.equals(consList[i].getName())) {
                    found = true;
                    ModelMBeanConstructorInfo mmbci =
                            (ModelMBeanConstructorInfo) consList[i];
                    mmbci.setDescriptor(inDescriptor);
                }
            }
        } else if (inDescriptorType.equalsIgnoreCase(NOTF)) {
            MBeanNotificationInfo[] notifList =  modelMBeanNotifications;
            int numNotifs = 0;
            if (notifList != null) numNotifs = notifList.length;

            for (int i=0; i < numNotifs; i++) {
                if (inDescriptorName.equals(notifList[i].getName())) {
                    found = true;
                    ModelMBeanNotificationInfo mmbni =
                            (ModelMBeanNotificationInfo) notifList[i];
                    mmbni.setDescriptor(inDescriptor);
                }
            }
        } else {
            RuntimeException iae =
                    new IllegalArgumentException("Invalid descriptor type: " +
                    inDescriptorType);
            throw new RuntimeOperationsException(iae, excMsg);
        }

        if (!found) {
            RuntimeException iae =
                    new IllegalArgumentException("Descriptor name is invalid: " +
                    "type=" + inDescriptorType +
                    "; name=" + inDescriptorName);
            throw new RuntimeOperationsException(iae, excMsg);
        }
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "setDescriptor(Descriptor,String)", "Exit");
        }

    }


    public ModelMBeanAttributeInfo getAttribute(String inName)
    throws MBeanException, RuntimeOperationsException {
        ModelMBeanAttributeInfo retInfo = null;
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "getAttribute(String)", "Entry");
        }
        if (inName == null) {
            throw new RuntimeOperationsException(
                    new IllegalArgumentException("Attribute Name is null"),
                    "Exception occurred trying to get the " +
                    "ModelMBeanAttributeInfo of the MBean");
        }
        MBeanAttributeInfo[] attrList = modelMBeanAttributes;
        int numAttrs = 0;
        if (attrList != null) numAttrs = attrList.length;

        for (int i=0; (i < numAttrs) && (retInfo == null); i++) {
            if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
                final StringBuilder strb = new StringBuilder()
                .append("\t\n this.getAttributes() MBeanAttributeInfo Array ")
                .append(i).append(":")
                .append(((ModelMBeanAttributeInfo)attrList[i]).getDescriptor())
                .append("\t\n this.modelMBeanAttributes MBeanAttributeInfo Array ")
                .append(i).append(":")
                .append(((ModelMBeanAttributeInfo)modelMBeanAttributes[i]).getDescriptor());
                MODELMBEAN_LOGGER.logp(Level.FINER,
                        ModelMBeanInfoSupport.class.getName(),
                        "getAttribute(String)", strb.toString());
            }
            if (inName.equals(attrList[i].getName())) {
                retInfo = ((ModelMBeanAttributeInfo)attrList[i].clone());
            }
        }
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "getAttribute(String)", "Exit");
        }

        return retInfo;
    }



    public ModelMBeanOperationInfo getOperation(String inName)
    throws MBeanException, RuntimeOperationsException {
        ModelMBeanOperationInfo retInfo = null;
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "getOperation(String)", "Entry");
        }
        if (inName == null) {
            throw new RuntimeOperationsException(
                    new IllegalArgumentException("inName is null"),
                    "Exception occurred trying to get the " +
                    "ModelMBeanOperationInfo of the MBean");
        }
        MBeanOperationInfo[] operList = modelMBeanOperations; //this.getOperations();
        int numOpers = 0;
        if (operList != null) numOpers = operList.length;

        for (int i=0; (i < numOpers) && (retInfo == null); i++) {
            if (inName.equals(operList[i].getName())) {
                retInfo = ((ModelMBeanOperationInfo) operList[i].clone());
            }
        }
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "getOperation(String)", "Exit");
        }

        return retInfo;
    }

    /**
     * Returns the ModelMBeanConstructorInfo requested by name.
     * If no ModelMBeanConstructorInfo exists for this name null is returned.
     *
     * @param inName the name of the constructor.
     *
     * @return the constructor info for the named constructor, or null
     * if there is none.
     *
     * @exception MBeanException Wraps a distributed communication Exception.
     * @exception RuntimeOperationsException Wraps an IllegalArgumentException
     *            for a null constructor name.
     */

    public ModelMBeanConstructorInfo getConstructor(String inName)
    throws MBeanException, RuntimeOperationsException {
        ModelMBeanConstructorInfo retInfo = null;
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "getConstructor(String)", "Entry");
        }
        if (inName == null) {
            throw new RuntimeOperationsException(
                    new IllegalArgumentException("Constructor name is null"),
                    "Exception occurred trying to get the " +
                    "ModelMBeanConstructorInfo of the MBean");
        }
        MBeanConstructorInfo[] consList = modelMBeanConstructors; //this.getConstructors();
        int numCons = 0;
        if (consList != null) numCons = consList.length;

        for (int i=0; (i < numCons) && (retInfo == null); i++) {
            if (inName.equals(consList[i].getName())) {
                retInfo = ((ModelMBeanConstructorInfo) consList[i].clone());
            }
        }
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "getConstructor(String)", "Exit");
        }

        return retInfo;
    }


    public ModelMBeanNotificationInfo getNotification(String inName)
    throws MBeanException, RuntimeOperationsException {
        ModelMBeanNotificationInfo retInfo = null;
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "getNotification(String)", "Entry");
        }
        if (inName == null) {
            throw new RuntimeOperationsException(
                    new IllegalArgumentException("Notification name is null"),
                    "Exception occurred trying to get the " +
                    "ModelMBeanNotificationInfo of the MBean");
        }
        MBeanNotificationInfo[] notifList = modelMBeanNotifications; //this.getNotifications();
        int numNotifs = 0;
        if (notifList != null) numNotifs = notifList.length;

        for (int i=0; (i < numNotifs) && (retInfo == null); i++) {
            if (inName.equals(notifList[i].getName())) {
                retInfo = ((ModelMBeanNotificationInfo) notifList[i].clone());
            }
        }
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "getNotification(String)", "Exit");
        }

        return retInfo;
    }


    /* We override MBeanInfo.getDescriptor() to return our descriptor. */
    /**
     * @since 1.6
     */
    @Override
    public Descriptor getDescriptor() {
        return getMBeanDescriptorNoException();
    }

    public Descriptor getMBeanDescriptor() throws MBeanException {
        return getMBeanDescriptorNoException();
    }

    private Descriptor getMBeanDescriptorNoException() {
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "getMBeanDescriptorNoException()", "Entry");
        }

        if (modelMBeanDescriptor == null)
            modelMBeanDescriptor = validDescriptor(null);

        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "getMBeanDescriptorNoException()",
                    "Exit, returning: " + modelMBeanDescriptor);
        }
        return (Descriptor) modelMBeanDescriptor.clone();
    }

    public void setMBeanDescriptor(Descriptor inMBeanDescriptor)
    throws MBeanException, RuntimeOperationsException {
        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
            MODELMBEAN_LOGGER.logp(Level.FINER,
                    ModelMBeanInfoSupport.class.getName(),
                    "setMBeanDescriptor(Descriptor)", "Entry");
        }
        modelMBeanDescriptor = validDescriptor(inMBeanDescriptor);
    }


    /**
     * Clones the passed in Descriptor, sets default values, and checks for validity.
     * If the Descriptor is invalid (for instance by having the wrong "name"),
     * this indicates programming error and a RuntimeOperationsException will be thrown.
     *
     * The following fields will be defaulted if they are not already set:
     * displayName=className,name=className,descriptorType="mbean",
     * persistPolicy="never", log="F", visibility="1"
     *
     * @param in Descriptor to be checked, or null which is equivalent to
     * an empty Descriptor.
     * @exception RuntimeOperationsException if Descriptor is invalid
     */
    private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException {
        Descriptor clone = null;
        if (in == null) {
            clone = new DescriptorSupport();
            MODELMBEAN_LOGGER.finer("Null Descriptor, creating new.");
        } else {
            clone = (Descriptor) in.clone();
        }

        //Setting defaults.
        if (clone.getFieldValue("name")==null) {
            clone.setField("name", this.getClassName());
            MODELMBEAN_LOGGER.finer("Defaulting Descriptor name to " + this.getClassName());
        }
        if (clone.getFieldValue("descriptorType")==null) {
            clone.setField("descriptorType", MMB);
            MODELMBEAN_LOGGER.finer("Defaulting descriptorType to \"" + MMB + "\"");
        }
        if (clone.getFieldValue("displayName") == null) {
            clone.setField("displayName",this.getClassName());
            MODELMBEAN_LOGGER.finer("Defaulting Descriptor displayName to " + this.getClassName());
        }
        if (clone.getFieldValue("persistPolicy") == null) {
            clone.setField("persistPolicy","never");
            MODELMBEAN_LOGGER.finer("Defaulting Descriptor persistPolicy to \"never\"");
        }
        if (clone.getFieldValue("log") == null) {
            clone.setField("log","F");
            MODELMBEAN_LOGGER.finer("Defaulting Descriptor \"log\" field to \"F\"");
        }
        if (clone.getFieldValue("visibility") == null) {
            clone.setField("visibility","1");
            MODELMBEAN_LOGGER.finer("Defaulting Descriptor visibility to 1");
        }

        //Checking validity
        if (!clone.isValid()) {
             throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
                "The isValid() method of the Descriptor object itself returned false,"+
                "one or more required fields are invalid. Descriptor:" + clone.toString());
        }

        if (! ((String)clone.getFieldValue("descriptorType")).equalsIgnoreCase(MMB)) {
                 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
                "The Descriptor \"descriptorType\" field does not match the object described. " +
                 " Expected: "+ MMB + " , was: " + clone.getFieldValue("descriptorType"));
        }

        return clone;
    }




    /**
     * Deserializes a {@link ModelMBeanInfoSupport} from an {@link ObjectInputStream}.
     */
    private void readObject(ObjectInputStream in)
    throws IOException, ClassNotFoundException {
        if (compat) {
            // Read an object serialized in the old serial form
            //
            ObjectInputStream.GetField fields = in.readFields();
            modelMBeanDescriptor =
                    (Descriptor) fields.get("modelMBeanDescriptor", null);
            if (fields.defaulted("modelMBeanDescriptor")) {
                throw new NullPointerException("modelMBeanDescriptor");
            }
            modelMBeanAttributes =
                    (MBeanAttributeInfo[]) fields.get("mmbAttributes", null);
            if (fields.defaulted("mmbAttributes")) {
                throw new NullPointerException("mmbAttributes");
            }
            modelMBeanConstructors =
                    (MBeanConstructorInfo[]) fields.get("mmbConstructors", null);
            if (fields.defaulted("mmbConstructors")) {
                throw new NullPointerException("mmbConstructors");
            }
            modelMBeanNotifications =
                    (MBeanNotificationInfo[]) fields.get("mmbNotifications", null);
            if (fields.defaulted("mmbNotifications")) {
                throw new NullPointerException("mmbNotifications");
            }
            modelMBeanOperations =
                    (MBeanOperationInfo[]) fields.get("mmbOperations", null);
            if (fields.defaulted("mmbOperations")) {
                throw new NullPointerException("mmbOperations");
            }
        } else {
            // Read an object serialized in the new serial form
            //
            in.defaultReadObject();
        }
    }


    /**
     * Serializes a {@link ModelMBeanInfoSupport} to an {@link ObjectOutputStream}.
     */
    private void writeObject(ObjectOutputStream out)
    throws IOException {
        if (compat) {
            // Serializes this instance in the old serial form
            //
            ObjectOutputStream.PutField fields = out.putFields();
            fields.put("modelMBeanDescriptor", modelMBeanDescriptor);
            fields.put("mmbAttributes", modelMBeanAttributes);
            fields.put("mmbConstructors", modelMBeanConstructors);
            fields.put("mmbNotifications", modelMBeanNotifications);
            fields.put("mmbOperations", modelMBeanOperations);
            fields.put("currClass", currClass);
            out.writeFields();
        } else {
            // Serializes this instance in the new serial form
            //
            out.defaultWriteObject();
        }
    }


}
