/*
 * Copyright 2005-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.
 */

package com.sun.jmx.mbeanserver;

import static com.sun.jmx.mbeanserver.Util.*;

import java.util.Iterator;
import java.util.Set;

import javax.management.InstanceAlreadyExistsException;
import javax.management.JMX;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;

/**
 * Base class for MXBeans.
 *
 * @since 1.6
 */
public class MXBeanSupport extends MBeanSupport<ConvertingMethod> {

    /**
       <p>Construct an MXBean that wraps the given resource using the
       given MXBean interface.</p>

       @param resource the underlying resource for the new MXBean.

       @param mxbeanInterface the interface to be used to determine
       the MXBean's management interface.

       @param <T> a type parameter that allows the compiler to check
       that {@code resource} implements {@code mxbeanInterface},
       provided that {@code mxbeanInterface} is a class constant like
       {@code SomeMXBean.class}.

       @throws IllegalArgumentException if {@code resource} is null or
       if it does not implement the class {@code mxbeanInterface} or if
       that class is not a valid MXBean interface.
    */
    public <T> MXBeanSupport(T resource, Class<T> mxbeanInterface)
            throws NotCompliantMBeanException {
        super(resource, mxbeanInterface);
    }

    @Override
    MBeanIntrospector<ConvertingMethod> getMBeanIntrospector() {
        return MXBeanIntrospector.getInstance();
    }

    @Override
    Object getCookie() {
        return mxbeanLookup;
    }

    static Class<?> findMXBeanInterface(Class<?> resourceClass)
        throws IllegalArgumentException {
        if (resourceClass == null)
            throw new IllegalArgumentException("Null resource class");
        final Set<Class<?>> intfs = transitiveInterfaces(resourceClass);
        final Set<Class<?>> candidates = newSet();
        for (Class<?> intf : intfs) {
            if (JMX.isMXBeanInterface(intf))
                candidates.add(intf);
        }
    reduce:
        while (candidates.size() > 1) {
            for (Class<?> intf : candidates) {
                for (Iterator<Class<?>> it = candidates.iterator(); it.hasNext();
                    ) {
                    final Class<?> intf2 = it.next();
                    if (intf != intf2 && intf2.isAssignableFrom(intf)) {
                        it.remove();
                        continue reduce;
                    }
                }
            }
            final String msg =
                "Class " + resourceClass.getName() + " implements more than " +
                "one MXBean interface: " + candidates;
            throw new IllegalArgumentException(msg);
        }
        if (candidates.iterator().hasNext()) {
            return candidates.iterator().next();
        } else {
            final String msg =
                "Class " + resourceClass.getName() +
                " is not a JMX compliant MXBean";
            throw new IllegalArgumentException(msg);
        }
    }

    /* Return all interfaces inherited by this class, directly or
     * indirectly through the parent class and interfaces.
     */
    private static Set<Class<?>> transitiveInterfaces(Class c) {
        Set<Class<?>> set = newSet();
        transitiveInterfaces(c, set);
        return set;
    }
    private static void transitiveInterfaces(Class<?> c, Set<Class<?>> intfs) {
        if (c == null)
            return;
        if (c.isInterface())
            intfs.add(c);
        transitiveInterfaces(c.getSuperclass(), intfs);
        for (Class sup : c.getInterfaces())
            transitiveInterfaces(sup, intfs);
    }

    /*
     * The sequence of events for tracking inter-MXBean references is
     * relatively complicated.  We use the magical preRegister2 method
     * which the MBeanServer knows about.  The steps during registration
     * are:
     * (1) Call user preRegister, if any.  If exception, abandon.
     * (2) Call preRegister2 and hence this register method.  If exception,
     * call postRegister(false) and abandon.
     * (3) Try to register the MBean.  If exception, call registerFailed()
     * which will call the unregister method.  (Also call postRegister(false).)
     * (4) If we get this far, we can call postRegister(true).
     *
     * When we are wrapped in an instance of javax.management.StandardMBean,
     * things are simpler.  That class calls this method from its preRegister,
     * and propagates any exception.  There is no user preRegister in this case.
     * If this method succeeds but registration subsequently fails,
     * StandardMBean calls unregister from its postRegister(false) method.
     */
    @Override
    public void register(MBeanServer server, ObjectName name)
            throws InstanceAlreadyExistsException {
        if (name == null)
            throw new IllegalArgumentException("Null object name");
        // eventually we could have some logic to supply a default name

        synchronized (lock) {
            if (this.objectName != null) {
                final String msg =
                    "MXBean already registered with name " + this.objectName;
                throw new InstanceAlreadyExistsException(msg);
            }
            this.mxbeanLookup = MXBeanLookup.lookupFor(server);
            this.mxbeanLookup.addReference(name, getResource());
            this.objectName = name;
        }
    }

    @Override
    public void unregister() {
        synchronized (lock) {
            if (mxbeanLookup.removeReference(objectName, getResource()))
                objectName = null;
        }
    }

    private Object lock = new Object(); // for mxbeanLookup and objectName
    private MXBeanLookup mxbeanLookup;
    private ObjectName objectName;
}
