8010285: Enforce the requirement of Management Interfaces being public

Reviewed-by: sjiang, dfuchs, mchung
This commit is contained in:
Jaroslav Bachorik 2013-07-11 21:11:03 +02:00
parent a4223b53c1
commit ec6cb721e1
13 changed files with 768 additions and 55 deletions

View File

@ -52,6 +52,7 @@ import javax.management.NotCompliantMBeanException;
import com.sun.jmx.remote.util.EnvHelp; import com.sun.jmx.remote.util.EnvHelp;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import javax.management.AttributeNotFoundException; import javax.management.AttributeNotFoundException;
import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeData;
import sun.reflect.misc.MethodUtil; import sun.reflect.misc.MethodUtil;
@ -64,7 +65,11 @@ import sun.reflect.misc.ReflectUtil;
* @since 1.5 * @since 1.5
*/ */
public class Introspector { public class Introspector {
final public static boolean ALLOW_NONPUBLIC_MBEAN;
static {
String val = AccessController.doPrivileged(new GetPropertyAction("jdk.jmx.mbeans.allowNonPublic"));
ALLOW_NONPUBLIC_MBEAN = Boolean.parseBoolean(val);
}
/* /*
* ------------------------------------------ * ------------------------------------------
@ -223,11 +228,27 @@ public class Introspector {
return testCompliance(baseClass, null); return testCompliance(baseClass, null);
} }
/**
* Tests the given interface class for being a compliant MXBean interface.
* A compliant MXBean interface is any publicly accessible interface
* following the {@link MXBean} conventions.
* @param interfaceClass An interface class to test for the MXBean compliance
* @throws NotCompliantMBeanException Thrown when the tested interface
* is not public or contradicts the {@link MXBean} conventions.
*/
public static void testComplianceMXBeanInterface(Class<?> interfaceClass) public static void testComplianceMXBeanInterface(Class<?> interfaceClass)
throws NotCompliantMBeanException { throws NotCompliantMBeanException {
MXBeanIntrospector.getInstance().getAnalyzer(interfaceClass); MXBeanIntrospector.getInstance().getAnalyzer(interfaceClass);
} }
/**
* Tests the given interface class for being a compliant MBean interface.
* A compliant MBean interface is any publicly accessible interface
* following the {@code MBean} conventions.
* @param interfaceClass An interface class to test for the MBean compliance
* @throws NotCompliantMBeanException Thrown when the tested interface
* is not public or contradicts the {@code MBean} conventions.
*/
public static void testComplianceMBeanInterface(Class<?> interfaceClass) public static void testComplianceMBeanInterface(Class<?> interfaceClass)
throws NotCompliantMBeanException{ throws NotCompliantMBeanException{
StandardMBeanIntrospector.getInstance().getAnalyzer(interfaceClass); StandardMBeanIntrospector.getInstance().getAnalyzer(interfaceClass);
@ -299,18 +320,18 @@ public class Introspector {
* not a JMX compliant Standard MBean. * not a JMX compliant Standard MBean.
*/ */
public static <T> Class<? super T> getStandardMBeanInterface(Class<T> baseClass) public static <T> Class<? super T> getStandardMBeanInterface(Class<T> baseClass)
throws NotCompliantMBeanException { throws NotCompliantMBeanException {
Class<? super T> current = baseClass; Class<? super T> current = baseClass;
Class<? super T> mbeanInterface = null; Class<? super T> mbeanInterface = null;
while (current != null) { while (current != null) {
mbeanInterface = mbeanInterface =
findMBeanInterface(current, current.getName()); findMBeanInterface(current, current.getName());
if (mbeanInterface != null) break; if (mbeanInterface != null) break;
current = current.getSuperclass(); current = current.getSuperclass();
} }
if (mbeanInterface != null) { if (mbeanInterface != null) {
return mbeanInterface; return mbeanInterface;
} else { } else {
final String msg = final String msg =
"Class " + baseClass.getName() + "Class " + baseClass.getName() +
" is not a JMX compliant Standard MBean"; " is not a JMX compliant Standard MBean";
@ -507,8 +528,11 @@ public class Introspector {
} }
Class<?>[] interfaces = c.getInterfaces(); Class<?>[] interfaces = c.getInterfaces();
for (int i = 0;i < interfaces.length; i++) { for (int i = 0;i < interfaces.length; i++) {
if (interfaces[i].getName().equals(clMBeanName)) if (interfaces[i].getName().equals(clMBeanName) &&
(Modifier.isPublic(interfaces[i].getModifiers()) ||
ALLOW_NONPUBLIC_MBEAN)) {
return Util.cast(interfaces[i]); return Util.cast(interfaces[i]);
}
} }
return null; return null;

View File

@ -28,6 +28,8 @@ package com.sun.jmx.mbeanserver;
import static com.sun.jmx.mbeanserver.Util.*; import static com.sun.jmx.mbeanserver.Util.*;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
@ -50,7 +52,6 @@ import javax.management.NotCompliantMBeanException;
* @since 1.6 * @since 1.6
*/ */
class MBeanAnalyzer<M> { class MBeanAnalyzer<M> {
static interface MBeanVisitor<M> { static interface MBeanVisitor<M> {
public void visitAttribute(String attributeName, public void visitAttribute(String attributeName,
M getter, M getter,
@ -107,6 +108,10 @@ class MBeanAnalyzer<M> {
if (!mbeanType.isInterface()) { if (!mbeanType.isInterface()) {
throw new NotCompliantMBeanException("Not an interface: " + throw new NotCompliantMBeanException("Not an interface: " +
mbeanType.getName()); mbeanType.getName());
} else if (!Modifier.isPublic(mbeanType.getModifiers()) &&
!Introspector.ALLOW_NONPUBLIC_MBEAN) {
throw new NotCompliantMBeanException("Interface is not public: " +
mbeanType.getName());
} }
try { try {

View File

@ -160,6 +160,10 @@ public class JMX {
* example, then the return type is {@code MyMBean}. * example, then the return type is {@code MyMBean}.
* *
* @return the new proxy instance. * @return the new proxy instance.
*
* @throws IllegalArgumentException if {@code interfaceClass} is not
* a <a href="package-summary.html#mgIface">compliant MBean
* interface</a>
*/ */
public static <T> T newMBeanProxy(MBeanServerConnection connection, public static <T> T newMBeanProxy(MBeanServerConnection connection,
ObjectName objectName, ObjectName objectName,
@ -200,6 +204,10 @@ public class JMX {
* example, then the return type is {@code MyMBean}. * example, then the return type is {@code MyMBean}.
* *
* @return the new proxy instance. * @return the new proxy instance.
*
* @throws IllegalArgumentException if {@code interfaceClass} is not
* a <a href="package-summary.html#mgIface">compliant MBean
* interface</a>
*/ */
public static <T> T newMBeanProxy(MBeanServerConnection connection, public static <T> T newMBeanProxy(MBeanServerConnection connection,
ObjectName objectName, ObjectName objectName,
@ -298,6 +306,9 @@ public class JMX {
* example, then the return type is {@code MyMXBean}. * example, then the return type is {@code MyMXBean}.
* *
* @return the new proxy instance. * @return the new proxy instance.
*
* @throws IllegalArgumentException if {@code interfaceClass} is not
* a {@link javax.management.MXBean compliant MXBean interface}
*/ */
public static <T> T newMXBeanProxy(MBeanServerConnection connection, public static <T> T newMXBeanProxy(MBeanServerConnection connection,
ObjectName objectName, ObjectName objectName,
@ -338,6 +349,9 @@ public class JMX {
* example, then the return type is {@code MyMXBean}. * example, then the return type is {@code MyMXBean}.
* *
* @return the new proxy instance. * @return the new proxy instance.
*
* @throws IllegalArgumentException if {@code interfaceClass} is not
* a {@link javax.management.MXBean compliant MXBean interface}
*/ */
public static <T> T newMXBeanProxy(MBeanServerConnection connection, public static <T> T newMXBeanProxy(MBeanServerConnection connection,
ObjectName objectName, ObjectName objectName,
@ -348,21 +362,25 @@ public class JMX {
/** /**
* <p>Test whether an interface is an MXBean interface. * <p>Test whether an interface is an MXBean interface.
* An interface is an MXBean interface if it is annotated * An interface is an MXBean interface if it is public,
* {@link MXBean &#64;MXBean} or {@code @MXBean(true)} * annotated {@link MXBean &#64;MXBean} or {@code @MXBean(true)}
* or if it does not have an {@code @MXBean} annotation * or if it does not have an {@code @MXBean} annotation
* and its name ends with "{@code MXBean}".</p> * and its name ends with "{@code MXBean}".</p>
* *
* @param interfaceClass The candidate interface. * @param interfaceClass The candidate interface.
* *
* @return true if {@code interfaceClass} is an interface and * @return true if {@code interfaceClass} is a
* meets the conditions described. * {@link javax.management.MXBean compliant MXBean interface}
* *
* @throws NullPointerException if {@code interfaceClass} is null. * @throws NullPointerException if {@code interfaceClass} is null.
*/ */
public static boolean isMXBeanInterface(Class<?> interfaceClass) { public static boolean isMXBeanInterface(Class<?> interfaceClass) {
if (!interfaceClass.isInterface()) if (!interfaceClass.isInterface())
return false; return false;
if (!Modifier.isPublic(interfaceClass.getModifiers()) &&
!Introspector.ALLOW_NONPUBLIC_MBEAN) {
return false;
}
MXBean a = interfaceClass.getAnnotation(MXBean.class); MXBean a = interfaceClass.getAnnotation(MXBean.class);
if (a != null) if (a != null)
return a.value(); return a.value();
@ -389,9 +407,6 @@ public class JMX {
boolean notificationEmitter, boolean notificationEmitter,
boolean isMXBean) { boolean isMXBean) {
if (System.getSecurityManager() != null) {
checkProxyInterface(interfaceClass);
}
try { try {
if (isMXBean) { if (isMXBean) {
// Check interface for MXBean compliance // Check interface for MXBean compliance
@ -419,17 +434,4 @@ public class JMX {
handler); handler);
return interfaceClass.cast(proxy); return interfaceClass.cast(proxy);
} }
/**
* Checks for the M(X)Bean proxy interface being public and not restricted
* @param interfaceClass MBean proxy interface
* @throws SecurityException when the proxy interface comes from a restricted
* package or is not public
*/
private static void checkProxyInterface(Class<?> interfaceClass) {
if (!Modifier.isPublic(interfaceClass.getModifiers())) {
throw new SecurityException("mbean proxy interface non-public");
}
ReflectUtil.checkPackageAccess(interfaceClass);
}
} }

View File

@ -225,7 +225,7 @@ public class MBeanServerInvocationHandler implements InvocationHandler {
* *
* @return the new proxy instance. * @return the new proxy instance.
* *
* @see JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class) * @see JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class, boolean)
*/ */
public static <T> T newProxyInstance(MBeanServerConnection connection, public static <T> T newProxyInstance(MBeanServerConnection connection,
ObjectName objectName, ObjectName objectName,

View File

@ -54,9 +54,9 @@ import javax.management.openmbean.TabularType;
/** /**
<p>Annotation to mark an interface explicitly as being an MXBean <p>Annotation to mark an interface explicitly as being an MXBean
interface, or as not being an MXBean interface. By default, an interface, or as not being an MXBean interface. By default, an
interface is an MXBean interface if its name ends with {@code interface is an MXBean interface if it is public and its name ends
MXBean}, as in {@code SomethingMXBean}. The following interfaces with {@code MXBean}, as in {@code SomethingMXBean}. The following
are MXBean interfaces:</p> interfaces are MXBean interfaces:</p>
<pre> <pre>
public interface WhatsitMXBean {} public interface WhatsitMXBean {}
@ -71,6 +71,8 @@ import javax.management.openmbean.TabularType;
<p>The following interfaces are not MXBean interfaces:</p> <p>The following interfaces are not MXBean interfaces:</p>
<pre> <pre>
interface NonPublicInterfaceNotMXBean{}
public interface Whatsit3Interface{} public interface Whatsit3Interface{}
&#64;MXBean(false) &#64;MXBean(false)

View File

@ -53,8 +53,8 @@ questions.
<p>The fundamental notion of the JMX API is the <em>MBean</em>. <p>The fundamental notion of the JMX API is the <em>MBean</em>.
An MBean is a named <em>managed object</em> representing a An MBean is a named <em>managed object</em> representing a
resource. It has a <em>management interface</em> consisting resource. It has a <em id="mgIface">management interface</em>
of:</p> which must be <em>public</em> and consist of:</p>
<ul> <ul>
<li>named and typed attributes that can be read and/or <li>named and typed attributes that can be read and/or

View File

@ -147,18 +147,20 @@ public class ManagementFactoryHelper {
} }
} }
// The logging MXBean object is an instance of /**
// PlatformLoggingMXBean and java.util.logging.LoggingMXBean * The logging MXBean object is an instance of
// but it can't directly implement two MXBean interfaces * PlatformLoggingMXBean and java.util.logging.LoggingMXBean
// as a compliant MXBean implements exactly one MXBean interface, * but it can't directly implement two MXBean interfaces
// or if it implements one interface that is a subinterface of * as a compliant MXBean implements exactly one MXBean interface,
// all the others; otherwise, it is a non-compliant MXBean * or if it implements one interface that is a subinterface of
// and MBeanServer will throw NotCompliantMBeanException. * all the others; otherwise, it is a non-compliant MXBean
// See the Definition of an MXBean section in javax.management.MXBean spec. * and MBeanServer will throw NotCompliantMBeanException.
// * See the Definition of an MXBean section in javax.management.MXBean spec.
// To create a compliant logging MXBean, define a LoggingMXBean interface *
// that extend PlatformLoggingMXBean and j.u.l.LoggingMXBean * To create a compliant logging MXBean, define a LoggingMXBean interface
interface LoggingMXBean * that extend PlatformLoggingMXBean and j.u.l.LoggingMXBean
*/
public interface LoggingMXBean
extends PlatformLoggingMXBean, java.util.logging.LoggingMXBean { extends PlatformLoggingMXBean, java.util.logging.LoggingMXBean {
} }

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2013, 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.
*
* 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.
*/
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
/*
* @test
* @bug 8010285
* @summary Test fallback for private MBean interfaces.
* It needs to be a separate class because the "jdk.jmx.mbeans.allowNonPublic"
* system property must be set before c.s.j.m.MBeanAnalyzer has been loaded.
* @author Jaroslav Bachorik
* @run clean MBeanFallbackTest
* @run build MBeanFallbackTest
* @run main MBeanFallbackTest
*/
public class MBeanFallbackTest {
private static interface PrivateMBean {
public int[] getInts();
}
public static class Private implements PrivateMBean {
public int[] getInts() {
return new int[]{1,2,3};
}
}
private static int failures = 0;
public static void main(String[] args) throws Exception {
System.setProperty("jdk.jmx.mbeans.allowNonPublic", "true");
testPrivate(PrivateMBean.class, new Private());
if (failures == 0)
System.out.println("Test passed");
else
throw new Exception("TEST FAILURES: " + failures);
}
private static void fail(String msg) {
failures++;
System.out.println("FAIL: " + msg);
}
private static void success(String msg) {
System.out.println("OK: " + msg);
}
private static void testPrivate(Class<?> iface, Object bean) throws Exception {
try {
System.out.println("Registering a private MBean " +
iface.getName() + " ...");
MBeanServer mbs = MBeanServerFactory.newMBeanServer();
ObjectName on = new ObjectName("test:type=Compliant");
mbs.registerMBean(bean, on);
success("Registered a private MBean - " + iface.getName());
} catch (Exception e) {
Throwable t = e;
while (t != null && !(t instanceof NotCompliantMBeanException)) {
t = t.getCause();
}
if (t != null) {
fail("MBean not registered");
} else {
throw e;
}
}
}
}

View File

@ -0,0 +1,158 @@
/*
* Copyright (c) 2013, 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.
*
* 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.
*/
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
/*
* @test
* @bug 8010285
* @summary General MBean test.
* @author Jaroslav Bachorik
* @run clean MBeanTest
* @run build MBeanTest
* @run main MBeanTest
*/
public class MBeanTest {
private static interface PrivateMBean {
public int[] getInts();
}
public static class Private implements PrivateMBean {
public int[] getInts() {
return new int[]{1,2,3};
}
}
public static interface NonCompliantMBean {
public boolean getInt();
public boolean isInt();
public void setInt(int a);
public void setInt(long b);
}
public static class NonCompliant implements NonCompliantMBean {
public boolean getInt() {
return false;
}
public boolean isInt() {
return true;
}
public void setInt(int a) {
}
public void setInt(long b) {
}
}
public static interface CompliantMBean {
public boolean isFlag();
public int getInt();
public void setInt(int value);
}
public static class Compliant implements CompliantMBean {
public boolean isFlag() {
return false;
}
public int getInt() {
return 1;
}
public void setInt(int value) {
}
}
private static int failures = 0;
public static void main(String[] args) throws Exception {
testCompliant(CompliantMBean.class, new Compliant());
testNonCompliant(PrivateMBean.class, new Private());
testNonCompliant(NonCompliantMBean.class, new NonCompliant());
if (failures == 0)
System.out.println("Test passed");
else
throw new Exception("TEST FAILURES: " + failures);
}
private static void fail(String msg) {
failures++;
System.out.println("FAIL: " + msg);
}
private static void success(String msg) {
System.out.println("OK: " + msg);
}
private static void testNonCompliant(Class<?> iface, Object bean) throws Exception {
try {
System.out.println("Registering a non-compliant MBean " +
iface.getName() + " ...");
MBeanServer mbs = MBeanServerFactory.newMBeanServer();
ObjectName on = new ObjectName("test:type=NonCompliant");
mbs.registerMBean(bean, on);
fail("Registered a non-compliant MBean - " + iface.getName());
} catch (Exception e) {
Throwable t = e;
while (t != null && !(t instanceof NotCompliantMBeanException)) {
t = t.getCause();
}
if (t != null) {
success("MBean not registered");
} else {
throw e;
}
}
}
private static void testCompliant(Class<?> iface, Object bean) throws Exception {
try {
System.out.println("Registering a compliant MBean " +
iface.getName() + " ...");
MBeanServer mbs = MBeanServerFactory.newMBeanServer();
ObjectName on = new ObjectName("test:type=Compliant");
mbs.registerMBean(bean, on);
success("Registered a compliant MBean - " + iface.getName());
} catch (Exception e) {
Throwable t = e;
while (t != null && !(t instanceof NotCompliantMBeanException)) {
t = t.getCause();
}
if (t != null) {
fail("MBean not registered");
} else {
throw e;
}
}
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2005, 2013, 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.
*
* 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.
*/
/*
* @test
* @bug 8010285
* @summary Test for the private MXBean interface fallback.
* It needs to be a separate class because the "jdk.jmx.mbeans.allowNonPublic"
* system property must be set before c.s.j.m.MBeanAnalyzer has been loaded.
* @author Jaroslav Bachorik
* @run clean MXBeanFallbackTest
* @run build MXBeanFallbackTest
* @run main MXBeanFallbackTest
*/
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
public class MXBeanFallbackTest {
public static void main(String[] args) throws Exception {
System.setProperty("jdk.jmx.mbeans.allowNonPublic", "true");
testPrivateMXBean("Private", new Private());
if (failures == 0)
System.out.println("Test passed");
else
throw new Exception("TEST FAILURES: " + failures);
}
private static int failures = 0;
private static interface PrivateMXBean {
public int[] getInts();
}
public static class Private implements PrivateMXBean {
public int[] getInts() {
return new int[]{1,2,3};
}
}
private static void testPrivateMXBean(String type, Object bean) throws Exception {
System.out.println(type + " MXBean test...");
MBeanServer mbs = MBeanServerFactory.newMBeanServer();
ObjectName on = new ObjectName("test:type=" + type);
try {
mbs.registerMBean(bean, on);
success("Private MXBean registered");
} catch (NotCompliantMBeanException e) {
failure("Failed to register the private MXBean - " +
bean.getClass().getInterfaces()[0].getName());
}
}
private static void success(String what) {
System.out.println("OK: " + what);
}
private static void failure(String what) {
System.out.println("FAILED: " + what);
failures++;
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,9 +23,10 @@
/* /*
* @test * @test
* @bug 6175517 6278707 6318827 6305746 6392303 6600709 * @bug 6175517 6278707 6318827 6305746 6392303 6600709 8010285
* @summary General MXBean test. * @summary General MXBean test.
* @author Eamonn McManus * @author Eamonn McManus
* @author Jaroslav Bachorik
* @run clean MXBeanTest MerlinMXBean TigerMXBean * @run clean MXBeanTest MerlinMXBean TigerMXBean
* @run build MXBeanTest MerlinMXBean TigerMXBean * @run build MXBeanTest MerlinMXBean TigerMXBean
* @run main MXBeanTest * @run main MXBeanTest
@ -51,6 +52,7 @@ import javax.management.MBeanServer;
import javax.management.MBeanServerConnection; import javax.management.MBeanServerConnection;
import javax.management.MBeanServerFactory; import javax.management.MBeanServerFactory;
import javax.management.MBeanServerInvocationHandler; import javax.management.MBeanServerInvocationHandler;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName; import javax.management.ObjectName;
import javax.management.StandardMBean; import javax.management.StandardMBean;
import javax.management.openmbean.ArrayType; import javax.management.openmbean.ArrayType;
@ -75,6 +77,8 @@ public class MXBeanTest {
testExplicitMXBean(); testExplicitMXBean();
testSubclassMXBean(); testSubclassMXBean();
testIndirectMXBean(); testIndirectMXBean();
testNonCompliantMXBean("Private", new Private());
testNonCompliantMXBean("NonCompliant", new NonCompliant());
if (failures == 0) if (failures == 0)
System.out.println("Test passed"); System.out.println("Test passed");
@ -84,6 +88,39 @@ public class MXBeanTest {
private static int failures = 0; private static int failures = 0;
private static interface PrivateMXBean {
public int[] getInts();
}
public static class Private implements PrivateMXBean {
public int[] getInts() {
return new int[]{1,2,3};
}
}
public static interface NonCompliantMXBean {
public boolean getInt();
public boolean isInt();
public void setInt(int a);
public void setInt(long b);
}
public static class NonCompliant implements NonCompliantMXBean {
public boolean getInt() {
return false;
}
public boolean isInt() {
return true;
}
public void setInt(int a) {
}
public void setInt(long b) {
}
}
public static interface ExplicitMXBean { public static interface ExplicitMXBean {
public int[] getInts(); public int[] getInts();
} }
@ -110,6 +147,19 @@ public class MXBeanTest {
} }
} }
private static void testNonCompliantMXBean(String type, Object bean) throws Exception {
System.out.println(type + " MXBean test...");
MBeanServer mbs = MBeanServerFactory.newMBeanServer();
ObjectName on = new ObjectName("test:type=" + type);
try {
mbs.registerMBean(bean, on);
failure(bean.getClass().getInterfaces()[0].getName() + " is not a compliant "
+ "MXBean interface");
} catch (NotCompliantMBeanException e) {
success("Non-compliant MXBean not registered");
}
}
private static void testExplicitMXBean() throws Exception { private static void testExplicitMXBean() throws Exception {
System.out.println("Explicit MXBean test..."); System.out.println("Explicit MXBean test...");
MBeanServer mbs = MBeanServerFactory.newMBeanServer(); MBeanServer mbs = MBeanServerFactory.newMBeanServer();

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2013, 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.
*
* 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.
*/
import javax.management.JMX;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
/*
* @test
* @bug 8010285
* @summary Tests the fallback for creating JMX proxies for private interfaces
* It needs to be a separate class because the "jdk.jmx.mbeans.allowNonPublic"
* system property must be set before c.s.j.m.MBeanAnalyzer has been loaded.
* @author Jaroslav Bachorik
* @run clean JMXProxyFallbackTest
* @run build JMXProxyFallbackTest
* @run main JMXProxyFallbackTest
*/
public class JMXProxyFallbackTest {
private static interface PrivateMBean {
public int[] getInts();
}
private static interface PrivateMXBean {
public int[] getInts();
}
public static class Private implements PrivateMXBean, PrivateMBean {
public int[] getInts() {
return new int[]{1,2,3};
}
}
private static int failures = 0;
public static void main(String[] args) throws Exception {
System.setProperty("jdk.jmx.mbeans.allowNonPublic", "true");
testPrivate(PrivateMBean.class);
testPrivate(PrivateMXBean.class);
if (failures == 0)
System.out.println("Test passed");
else
throw new Exception("TEST FAILURES: " + failures);
}
private static void fail(String msg) {
failures++;
System.out.println("FAIL: " + msg);
}
private static void success(String msg) {
System.out.println("OK: " + msg);
}
private static void testPrivate(Class<?> iface) throws Exception {
try {
System.out.println("Creating a proxy for private M(X)Bean " +
iface.getName() + " ...");
MBeanServer mbs = MBeanServerFactory.newMBeanServer();
ObjectName on = new ObjectName("test:type=Proxy");
JMX.newMBeanProxy(mbs, on, iface);
success("Created a proxy for private M(X)Bean - " + iface.getName());
} catch (Exception e) {
Throwable t = e;
while (t != null && !(t instanceof NotCompliantMBeanException)) {
t = t.getCause();
}
if (t != null) {
fail("Proxy not created");
} else {
throw e;
}
}
}
}

View File

@ -0,0 +1,191 @@
/*
* Copyright (c) 2013, 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.
*
* 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.
*/
import javax.management.JMX;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
/*
* @test
* @bug 8010285
* @summary Tests that javax.management.JMX creates proxies only for the
* compliant MBeans/MXBeans
* @author Jaroslav Bachorik
* @run clean JMXProxyTest
* @run build JMXProxyTest
* @run main JMXProxyTest
*/
public class JMXProxyTest {
private static interface PrivateMBean {
public int[] getInts();
}
private static interface PrivateMXBean {
public int[] getInts();
}
public static class Private implements PrivateMXBean, PrivateMBean {
public int[] getInts() {
return new int[]{1,2,3};
}
}
public static interface NonCompliantMBean {
public boolean getInt();
public boolean isInt();
public void setInt(int a);
public void setInt(long b);
}
public static interface NonCompliantMXBean {
public boolean getInt();
public boolean isInt();
public void setInt(int a);
public void setInt(long b);
}
public static class NonCompliant implements NonCompliantMXBean, NonCompliantMBean {
public boolean getInt() {
return false;
}
public boolean isInt() {
return true;
}
public void setInt(int a) {
}
public void setInt(long b) {
}
}
public static interface CompliantMBean {
public boolean isFlag();
public int getInt();
public void setInt(int value);
}
public static interface CompliantMXBean {
public boolean isFlag();
public int getInt();
public void setInt(int value);
}
public static class Compliant implements CompliantMXBean, CompliantMBean {
public boolean isFlag() {
return false;
}
public int getInt() {
return 1;
}
public void setInt(int value) {
}
}
private static int failures = 0;
public static void main(String[] args) throws Exception {
testCompliant(CompliantMBean.class, false);
testCompliant(CompliantMXBean.class, true);
testNonCompliant(PrivateMBean.class, false);
testNonCompliant(PrivateMXBean.class, true);
testNonCompliant(NonCompliantMBean.class, false);
testNonCompliant(NonCompliantMXBean.class, true);
if (failures == 0)
System.out.println("Test passed");
else
throw new Exception("TEST FAILURES: " + failures);
}
private static void fail(String msg) {
failures++;
System.out.println("FAIL: " + msg);
}
private static void success(String msg) {
System.out.println("OK: " + msg);
}
private static void testNonCompliant(Class<?> iface, boolean isMx) throws Exception {
try {
System.out.println("Creating a proxy for non-compliant " +
(isMx ? "MXBean" : "MBean") + " " +
iface.getName() + " ...");
MBeanServer mbs = MBeanServerFactory.newMBeanServer();
ObjectName on = new ObjectName("test:type=Proxy");
if (isMx) {
JMX.newMXBeanProxy(mbs, on, iface);
} else {
JMX.newMBeanProxy(mbs, on, iface);
}
fail("Created a proxy for non-compliant " +
(isMx ? "MXBean" : "MBean") + " - " + iface.getName());
} catch (Exception e) {
Throwable t = e;
while (t != null && !(t instanceof NotCompliantMBeanException)) {
t = t.getCause();
}
if (t != null) {
success("Proxy not created");
} else {
throw e;
}
}
}
private static void testCompliant(Class<?> iface, boolean isMx) throws Exception {
try {
System.out.println("Creating a proxy for compliant " +
(isMx ? "MXBean" : "MBean") + " " +
iface.getName() + " ...");
MBeanServer mbs = MBeanServerFactory.newMBeanServer();
ObjectName on = new ObjectName("test:type=Proxy");
if (isMx) {
JMX.newMXBeanProxy(mbs, on, iface);
} else {
JMX.newMBeanProxy(mbs, on, iface);
}
success("Created a proxy for compliant " +
(isMx ? "MXBean" : "MBean") + " - " + iface.getName());
} catch (Exception e) {
Throwable t = e;
while (t != null && !(t instanceof NotCompliantMBeanException)) {
t = t.getCause();
}
if (t != null) {
fail("Proxy not created");
} else {
throw e;
}
}
}
}