0N/A/*
2362N/A * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage com.sun.jmx.mbeanserver;
0N/A
0N/Aimport static com.sun.jmx.mbeanserver.Util.*;
0N/A
0N/Aimport java.util.Iterator;
0N/Aimport java.util.Set;
0N/A
0N/Aimport javax.management.InstanceAlreadyExistsException;
0N/Aimport javax.management.JMX;
0N/Aimport javax.management.MBeanServer;
0N/Aimport javax.management.NotCompliantMBeanException;
0N/Aimport javax.management.ObjectName;
0N/A
0N/A/**
0N/A * Base class for MXBeans.
0N/A *
0N/A * @since 1.6
0N/A */
0N/Apublic class MXBeanSupport extends MBeanSupport<ConvertingMethod> {
0N/A
0N/A /**
0N/A <p>Construct an MXBean that wraps the given resource using the
0N/A given MXBean interface.</p>
0N/A
0N/A @param resource the underlying resource for the new MXBean.
0N/A
0N/A @param mxbeanInterface the interface to be used to determine
0N/A the MXBean's management interface.
0N/A
0N/A @param <T> a type parameter that allows the compiler to check
0N/A that {@code resource} implements {@code mxbeanInterface},
0N/A provided that {@code mxbeanInterface} is a class constant like
0N/A {@code SomeMXBean.class}.
0N/A
0N/A @throws IllegalArgumentException if {@code resource} is null or
0N/A if it does not implement the class {@code mxbeanInterface} or if
0N/A that class is not a valid MXBean interface.
0N/A */
1790N/A public <T> MXBeanSupport(T resource, Class<T> mxbeanInterface)
0N/A throws NotCompliantMBeanException {
1790N/A super(resource, mxbeanInterface);
0N/A }
0N/A
0N/A @Override
1790N/A MBeanIntrospector<ConvertingMethod> getMBeanIntrospector() {
1790N/A return MXBeanIntrospector.getInstance();
0N/A }
0N/A
0N/A @Override
0N/A Object getCookie() {
0N/A return mxbeanLookup;
0N/A }
0N/A
353N/A static <T> Class<? super T> findMXBeanInterface(Class<T> resourceClass) {
0N/A if (resourceClass == null)
0N/A throw new IllegalArgumentException("Null resource class");
0N/A final Set<Class<?>> intfs = transitiveInterfaces(resourceClass);
0N/A final Set<Class<?>> candidates = newSet();
0N/A for (Class<?> intf : intfs) {
0N/A if (JMX.isMXBeanInterface(intf))
0N/A candidates.add(intf);
0N/A }
0N/A reduce:
0N/A while (candidates.size() > 1) {
0N/A for (Class<?> intf : candidates) {
0N/A for (Iterator<Class<?>> it = candidates.iterator(); it.hasNext();
0N/A ) {
0N/A final Class<?> intf2 = it.next();
0N/A if (intf != intf2 && intf2.isAssignableFrom(intf)) {
0N/A it.remove();
0N/A continue reduce;
0N/A }
0N/A }
0N/A }
0N/A final String msg =
0N/A "Class " + resourceClass.getName() + " implements more than " +
0N/A "one MXBean interface: " + candidates;
0N/A throw new IllegalArgumentException(msg);
0N/A }
0N/A if (candidates.iterator().hasNext()) {
353N/A return Util.cast(candidates.iterator().next());
0N/A } else {
0N/A final String msg =
0N/A "Class " + resourceClass.getName() +
0N/A " is not a JMX compliant MXBean";
0N/A throw new IllegalArgumentException(msg);
0N/A }
0N/A }
0N/A
0N/A /* Return all interfaces inherited by this class, directly or
0N/A * indirectly through the parent class and interfaces.
0N/A */
353N/A private static Set<Class<?>> transitiveInterfaces(Class<?> c) {
0N/A Set<Class<?>> set = newSet();
0N/A transitiveInterfaces(c, set);
0N/A return set;
0N/A }
0N/A private static void transitiveInterfaces(Class<?> c, Set<Class<?>> intfs) {
0N/A if (c == null)
0N/A return;
0N/A if (c.isInterface())
0N/A intfs.add(c);
0N/A transitiveInterfaces(c.getSuperclass(), intfs);
353N/A for (Class<?> sup : c.getInterfaces())
0N/A transitiveInterfaces(sup, intfs);
0N/A }
0N/A
0N/A /*
0N/A * The sequence of events for tracking inter-MXBean references is
0N/A * relatively complicated. We use the magical preRegister2 method
0N/A * which the MBeanServer knows about. The steps during registration
0N/A * are:
0N/A * (1) Call user preRegister, if any. If exception, abandon.
0N/A * (2) Call preRegister2 and hence this register method. If exception,
0N/A * call postRegister(false) and abandon.
0N/A * (3) Try to register the MBean. If exception, call registerFailed()
0N/A * which will call the unregister method. (Also call postRegister(false).)
0N/A * (4) If we get this far, we can call postRegister(true).
0N/A *
0N/A * When we are wrapped in an instance of javax.management.StandardMBean,
0N/A * things are simpler. That class calls this method from its preRegister,
0N/A * and propagates any exception. There is no user preRegister in this case.
0N/A * If this method succeeds but registration subsequently fails,
0N/A * StandardMBean calls unregister from its postRegister(false) method.
0N/A */
0N/A @Override
0N/A public void register(MBeanServer server, ObjectName name)
0N/A throws InstanceAlreadyExistsException {
0N/A if (name == null)
0N/A throw new IllegalArgumentException("Null object name");
0N/A // eventually we could have some logic to supply a default name
0N/A
0N/A synchronized (lock) {
1790N/A this.mxbeanLookup = MXBeanLookup.lookupFor(server);
1790N/A this.mxbeanLookup.addReference(name, getResource());
0N/A this.objectName = name;
0N/A }
0N/A }
0N/A
0N/A @Override
0N/A public void unregister() {
0N/A synchronized (lock) {
353N/A if (mxbeanLookup != null) {
1790N/A if (mxbeanLookup.removeReference(objectName, getResource()))
353N/A objectName = null;
353N/A }
0N/A }
0N/A }
353N/A private final Object lock = new Object(); // for mxbeanLookup and objectName
0N/A
1790N/A private MXBeanLookup mxbeanLookup;
0N/A private ObjectName objectName;
0N/A}