/*
 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.jmx.mbeanserver;


import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import com.sun.jmx.mbeanserver.MXBeanMappingFactory;

/**
 * Base class for MBeans.  There is one instance of this class for
 * every Standard MBean and every MXBean.  We try to limit the amount
 * of information per instance so we can handle very large numbers of
 * MBeans comfortably.
 *
 * @param <M> either Method or ConvertingMethod, for Standard MBeans
 * and MXBeans respectively.
 *
 * @since 1.6
 */
/*
 * We maintain a couple of caches to increase sharing between
 * different MBeans of the same type and also to reduce creation time
 * for the second and subsequent instances of the same type.
 *
 * The first cache maps from an MBean interface to a PerInterface
 * object containing information parsed out of the interface.  The
 * interface is either a Standard MBean interface or an MXBean
 * interface, and there is one cache for each case.
 *
 * The PerInterface includes an MBeanInfo.  This contains the
 * attributes and operations parsed out of the interface's methods,
 * plus a basic Descriptor for the interface containing at least the
 * interfaceClassName field and any fields derived from annotations on
 * the interface.  This MBeanInfo can never be the MBeanInfo for any
 * actual MBean, because an MBeanInfo's getClassName() is the name of
 * a concrete class and we don't know what the class will be.
 * Furthermore a real MBeanInfo may need to add constructors and/or
 * notifications to the MBeanInfo.
 *
 * The PerInterface also contains an MBeanDispatcher which is able to
 * route getAttribute, setAttribute, and invoke to the appropriate
 * method of the interface, including doing any necessary translation
 * of parameters and return values for MXBeans.
 *
 * The PerInterface also contains the original Class for the interface.
 *
 * We need to be careful about references.  When there are no MBeans
 * with a given interface, there must not be any strong references to
 * the interface Class.  Otherwise it could never be garbage collected,
 * and neither could its ClassLoader or any other classes loaded by
 * its ClassLoader.  Therefore the cache must wrap the PerInterface
 * in a WeakReference.  Each instance of MBeanSupport has a strong
 * reference to its PerInterface, which prevents PerInterface instances
 * from being garbage-collected prematurely.
 *
 * The second cache maps from a concrete class and an MBean interface
 * that that class implements to the MBeanInfo for that class and
 * interface.  (The ability to specify an interface separately comes
 * from the class StandardMBean.  MBeans registered directly in the
 * MBean Server will always have the same interface here.)
 *
 * The MBeanInfo in this second cache will be the MBeanInfo from the
 * PerInterface cache for the given itnerface, but with the
 * getClassName() having the concrete class's name, and the public
 * constructors based on the concrete class's constructors.  This
 * MBeanInfo can be shared between all instances of the concrete class
 * specifying the same interface, except instances that are
 * NotificationBroadcasters.  NotificationBroadcasters supply the
 * MBeanNotificationInfo[] in the MBeanInfo based on the instance
 * method NotificationBroadcaster.getNotificationInfo(), so two
 * instances of the same concrete class do not necessarily have the
 * same MBeanNotificationInfo[].  Currently we do not try to detect
 * when they do, although it would probably be worthwhile doing that
 * since it is a very common case.
 *
 * Standard MBeans additionally have the property that
 * getNotificationInfo() must in principle be called every time
 * getMBeanInfo() is called for the MBean, since the returned array is
 * allowed to change over time.  We attempt to reduce the cost of
 * doing this by detecting when the Standard MBean is a subclass of
 * NotificationBroadcasterSupport that does not override
 * getNotificationInfo(), meaning that the MBeanNotificationInfo[] is
 * the one that was supplied to the constructor.  MXBeans do not have
 * this problem because their getNotificationInfo() method is called
 * only once.
 *
 */
public abstract class MBeanSupport<M>
        implements DynamicMBean2, MBeanRegistration {

    <T> MBeanSupport(T resource, Class<T> mbeanInterfaceType)
            throws NotCompliantMBeanException {
        if (mbeanInterfaceType == null)
            throw new NotCompliantMBeanException("Null MBean interface");
        if (!mbeanInterfaceType.isInstance(resource)) {
            final String msg =
                "Resource class " + resource.getClass().getName() +
                " is not an instance of " + mbeanInterfaceType.getName();
            throw new NotCompliantMBeanException(msg);
        }
        this.resource = resource;
        MBeanIntrospector<M> introspector = getMBeanIntrospector();
        this.perInterface = introspector.getPerInterface(mbeanInterfaceType);
        this.mbeanInfo = introspector.getMBeanInfo(resource, perInterface);
    }

    /** Return the appropriate introspector for this type of MBean. */
    abstract MBeanIntrospector<M> getMBeanIntrospector();

    /**
     * Return a cookie for this MBean.  This cookie will be passed to
     * MBean method invocations where it can supply additional information
     * to the invocation.  For example, with MXBeans it can be used to
     * supply the MXBeanLookup context for resolving inter-MXBean references.
     */
    abstract Object getCookie();

    public final boolean isMXBean() {
        return perInterface.isMXBean();
    }

    // Methods that javax.management.StandardMBean should call from its
    // preRegister and postRegister, given that it is not supposed to
    // call the contained object's preRegister etc methods even if it has them
    public abstract void register(MBeanServer mbs, ObjectName name)
            throws Exception;
    public abstract void unregister();

    public final ObjectName preRegister(MBeanServer server, ObjectName name)
            throws Exception {
        if (resource instanceof MBeanRegistration)
            name = ((MBeanRegistration) resource).preRegister(server, name);
        return name;
    }

    public final void preRegister2(MBeanServer server, ObjectName name)
            throws Exception {
        register(server, name);
    }

    public final void registerFailed() {
        unregister();
    }

    public final void postRegister(Boolean registrationDone) {
        if (resource instanceof MBeanRegistration)
            ((MBeanRegistration) resource).postRegister(registrationDone);
    }

    public final void preDeregister() throws Exception {
        if (resource instanceof MBeanRegistration)
            ((MBeanRegistration) resource).preDeregister();
    }

    public final void postDeregister() {
        // Undo any work from registration.  We do this in postDeregister
        // not preDeregister, because if the user preDeregister throws an
        // exception then the MBean is not unregistered.
        try {
            unregister();
        } finally {
            if (resource instanceof MBeanRegistration)
                ((MBeanRegistration) resource).postDeregister();
        }
    }

    public final Object getAttribute(String attribute)
            throws AttributeNotFoundException,
                   MBeanException,
                   ReflectionException {
        return perInterface.getAttribute(resource, attribute, getCookie());
    }

    public final AttributeList getAttributes(String[] attributes) {
        final AttributeList result = new AttributeList(attributes.length);
        for (String attrName : attributes) {
            try {
                final Object attrValue = getAttribute(attrName);
                result.add(new Attribute(attrName, attrValue));
            } catch (Exception e) {
                // OK: attribute is not included in returned list, per spec
                // XXX: log the exception
            }
        }
        return result;
    }

    public final void setAttribute(Attribute attribute)
            throws AttributeNotFoundException,
                   InvalidAttributeValueException,
                   MBeanException,
                   ReflectionException {
        final String name = attribute.getName();
        final Object value = attribute.getValue();
        perInterface.setAttribute(resource, name, value, getCookie());
    }

    public final AttributeList setAttributes(AttributeList attributes) {
        final AttributeList result = new AttributeList(attributes.size());
        for (Object attrObj : attributes) {
            // We can't use AttributeList.asList because it has side-effects
            Attribute attr = (Attribute) attrObj;
            try {
                setAttribute(attr);
                result.add(new Attribute(attr.getName(), attr.getValue()));
            } catch (Exception e) {
                // OK: attribute is not included in returned list, per spec
                // XXX: log the exception
            }
        }
        return result;
    }

    public final Object invoke(String operation, Object[] params,
                         String[] signature)
            throws MBeanException, ReflectionException {
        return perInterface.invoke(resource, operation, params, signature,
                                   getCookie());
    }

    // Overridden by StandardMBeanSupport
    public MBeanInfo getMBeanInfo() {
        return mbeanInfo;
    }

    public final String getClassName() {
        return resource.getClass().getName();
    }

    public final Object getResource() {
        return resource;
    }

    public final Class<?> getMBeanInterface() {
        return perInterface.getMBeanInterface();
    }

    private final MBeanInfo mbeanInfo;
    private final Object resource;
    private final PerInterface<M> perInterface;
}
