# HG changeset patch # User jbachorik # Date 1373569863 -7200 # Node ID b359f8adc8ad3b826f87b56938fa1aabdaa2d65f # Parent 8561f20987270fb03a0cdc351f968a5aba65bebf 8010285: Enforce the requirement of Management Interfaces being public Reviewed-by: sjiang, dfuchs, mchung diff -r 8561f2098727 -r b359f8adc8ad jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Thu Jul 11 11:43:23 2013 -0700 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Thu Jul 11 21:11:03 2013 +0200 @@ -52,6 +52,7 @@ import com.sun.jmx.remote.util.EnvHelp; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; +import java.security.AccessController; import javax.management.AttributeNotFoundException; import javax.management.openmbean.CompositeData; import sun.reflect.misc.MethodUtil; @@ -64,7 +65,11 @@ * @since 1.5 */ 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 @@ 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) throws NotCompliantMBeanException { 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) throws NotCompliantMBeanException{ StandardMBeanIntrospector.getInstance().getAnalyzer(interfaceClass); @@ -299,18 +320,18 @@ * not a JMX compliant Standard MBean. */ public static Class getStandardMBeanInterface(Class baseClass) - throws NotCompliantMBeanException { - Class current = baseClass; - Class mbeanInterface = null; - while (current != null) { - mbeanInterface = - findMBeanInterface(current, current.getName()); - if (mbeanInterface != null) break; - current = current.getSuperclass(); - } - if (mbeanInterface != null) { - return mbeanInterface; - } else { + throws NotCompliantMBeanException { + Class current = baseClass; + Class mbeanInterface = null; + while (current != null) { + mbeanInterface = + findMBeanInterface(current, current.getName()); + if (mbeanInterface != null) break; + current = current.getSuperclass(); + } + if (mbeanInterface != null) { + return mbeanInterface; + } else { final String msg = "Class " + baseClass.getName() + " is not a JMX compliant Standard MBean"; @@ -507,8 +528,11 @@ } Class[] interfaces = c.getInterfaces(); 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 null; diff -r 8561f2098727 -r b359f8adc8ad jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java Thu Jul 11 11:43:23 2013 -0700 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java Thu Jul 11 21:11:03 2013 +0200 @@ -28,6 +28,8 @@ import static com.sun.jmx.mbeanserver.Util.*; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.security.AccessController; import java.util.Arrays; import java.util.Comparator; import java.util.List; @@ -50,7 +52,6 @@ * @since 1.6 */ class MBeanAnalyzer { - static interface MBeanVisitor { public void visitAttribute(String attributeName, M getter, @@ -107,6 +108,10 @@ if (!mbeanType.isInterface()) { throw new NotCompliantMBeanException("Not an interface: " + mbeanType.getName()); + } else if (!Modifier.isPublic(mbeanType.getModifiers()) && + !Introspector.ALLOW_NONPUBLIC_MBEAN) { + throw new NotCompliantMBeanException("Interface is not public: " + + mbeanType.getName()); } try { diff -r 8561f2098727 -r b359f8adc8ad jdk/src/share/classes/javax/management/JMX.java --- a/jdk/src/share/classes/javax/management/JMX.java Thu Jul 11 11:43:23 2013 -0700 +++ b/jdk/src/share/classes/javax/management/JMX.java Thu Jul 11 21:11:03 2013 +0200 @@ -160,6 +160,10 @@ * example, then the return type is {@code MyMBean}. * * @return the new proxy instance. + * + * @throws IllegalArgumentException if {@code interfaceClass} is not + * a compliant MBean + * interface */ public static T newMBeanProxy(MBeanServerConnection connection, ObjectName objectName, @@ -200,6 +204,10 @@ * example, then the return type is {@code MyMBean}. * * @return the new proxy instance. + * + * @throws IllegalArgumentException if {@code interfaceClass} is not + * a compliant MBean + * interface */ public static T newMBeanProxy(MBeanServerConnection connection, ObjectName objectName, @@ -298,6 +306,9 @@ * example, then the return type is {@code MyMXBean}. * * @return the new proxy instance. + * + * @throws IllegalArgumentException if {@code interfaceClass} is not + * a {@link javax.management.MXBean compliant MXBean interface} */ public static T newMXBeanProxy(MBeanServerConnection connection, ObjectName objectName, @@ -338,6 +349,9 @@ * example, then the return type is {@code MyMXBean}. * * @return the new proxy instance. + * + * @throws IllegalArgumentException if {@code interfaceClass} is not + * a {@link javax.management.MXBean compliant MXBean interface} */ public static T newMXBeanProxy(MBeanServerConnection connection, ObjectName objectName, @@ -348,21 +362,25 @@ /** *

Test whether an interface is an MXBean interface. - * An interface is an MXBean interface if it is annotated - * {@link MXBean @MXBean} or {@code @MXBean(true)} + * An interface is an MXBean interface if it is public, + * annotated {@link MXBean @MXBean} or {@code @MXBean(true)} * or if it does not have an {@code @MXBean} annotation * and its name ends with "{@code MXBean}".

* * @param interfaceClass The candidate interface. * - * @return true if {@code interfaceClass} is an interface and - * meets the conditions described. + * @return true if {@code interfaceClass} is a + * {@link javax.management.MXBean compliant MXBean interface} * * @throws NullPointerException if {@code interfaceClass} is null. */ public static boolean isMXBeanInterface(Class interfaceClass) { if (!interfaceClass.isInterface()) return false; + if (!Modifier.isPublic(interfaceClass.getModifiers()) && + !Introspector.ALLOW_NONPUBLIC_MBEAN) { + return false; + } MXBean a = interfaceClass.getAnnotation(MXBean.class); if (a != null) return a.value(); @@ -389,9 +407,6 @@ boolean notificationEmitter, boolean isMXBean) { - if (System.getSecurityManager() != null) { - checkProxyInterface(interfaceClass); - } try { if (isMXBean) { // Check interface for MXBean compliance @@ -419,17 +434,4 @@ handler); 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); - } } diff -r 8561f2098727 -r b359f8adc8ad jdk/src/share/classes/javax/management/MBeanServerInvocationHandler.java --- a/jdk/src/share/classes/javax/management/MBeanServerInvocationHandler.java Thu Jul 11 11:43:23 2013 -0700 +++ b/jdk/src/share/classes/javax/management/MBeanServerInvocationHandler.java Thu Jul 11 21:11:03 2013 +0200 @@ -225,7 +225,7 @@ * * @return the new proxy instance. * - * @see JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class) + * @see JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class, boolean) */ public static T newProxyInstance(MBeanServerConnection connection, ObjectName objectName, diff -r 8561f2098727 -r b359f8adc8ad jdk/src/share/classes/javax/management/MXBean.java --- a/jdk/src/share/classes/javax/management/MXBean.java Thu Jul 11 11:43:23 2013 -0700 +++ b/jdk/src/share/classes/javax/management/MXBean.java Thu Jul 11 21:11:03 2013 +0200 @@ -54,9 +54,9 @@ /**

Annotation to mark an interface explicitly as being an MXBean interface, or as not being an MXBean interface. By default, an - interface is an MXBean interface if its name ends with {@code - MXBean}, as in {@code SomethingMXBean}. The following interfaces - are MXBean interfaces:

+ interface is an MXBean interface if it is public and its name ends + with {@code MXBean}, as in {@code SomethingMXBean}. The following + interfaces are MXBean interfaces:

     public interface WhatsitMXBean {}
@@ -71,6 +71,8 @@
     

The following interfaces are not MXBean interfaces:

+    interface NonPublicInterfaceNotMXBean{}
+
     public interface Whatsit3Interface{}
 
     @MXBean(false)
diff -r 8561f2098727 -r b359f8adc8ad jdk/src/share/classes/javax/management/package.html
--- a/jdk/src/share/classes/javax/management/package.html	Thu Jul 11 11:43:23 2013 -0700
+++ b/jdk/src/share/classes/javax/management/package.html	Thu Jul 11 21:11:03 2013 +0200
@@ -53,8 +53,8 @@
 
         

The fundamental notion of the JMX API is the MBean. An MBean is a named managed object representing a - resource. It has a management interface consisting - of:

+ resource. It has a management interface + which must be public and consist of:

  • named and typed attributes that can be read and/or diff -r 8561f2098727 -r b359f8adc8ad jdk/src/share/classes/sun/management/ManagementFactoryHelper.java --- a/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java Thu Jul 11 11:43:23 2013 -0700 +++ b/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java Thu Jul 11 21:11:03 2013 +0200 @@ -147,18 +147,20 @@ } } - // The logging MXBean object is an instance of - // PlatformLoggingMXBean and java.util.logging.LoggingMXBean - // but it can't directly implement two MXBean interfaces - // as a compliant MXBean implements exactly one MXBean interface, - // or if it implements one interface that is a subinterface of - // all the others; otherwise, it is a non-compliant MXBean - // 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 - interface LoggingMXBean + /** + * The logging MXBean object is an instance of + * PlatformLoggingMXBean and java.util.logging.LoggingMXBean + * but it can't directly implement two MXBean interfaces + * as a compliant MXBean implements exactly one MXBean interface, + * or if it implements one interface that is a subinterface of + * all the others; otherwise, it is a non-compliant MXBean + * 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 + */ + public interface LoggingMXBean extends PlatformLoggingMXBean, java.util.logging.LoggingMXBean { } diff -r 8561f2098727 -r b359f8adc8ad jdk/test/javax/management/MBeanServer/MBeanFallbackTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/management/MBeanServer/MBeanFallbackTest.java Thu Jul 11 21:11:03 2013 +0200 @@ -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; + } + } + } +} diff -r 8561f2098727 -r b359f8adc8ad jdk/test/javax/management/MBeanServer/MBeanTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/management/MBeanServer/MBeanTest.java Thu Jul 11 21:11:03 2013 +0200 @@ -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; + } + } + } +} diff -r 8561f2098727 -r b359f8adc8ad jdk/test/javax/management/mxbean/MXBeanFallbackTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/management/mxbean/MXBeanFallbackTest.java Thu Jul 11 21:11:03 2013 +0200 @@ -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++; + } +} diff -r 8561f2098727 -r b359f8adc8ad jdk/test/javax/management/mxbean/MXBeanTest.java --- a/jdk/test/javax/management/mxbean/MXBeanTest.java Thu Jul 11 11:43:23 2013 -0700 +++ b/jdk/test/javax/management/mxbean/MXBeanTest.java Thu Jul 11 21:11:03 2013 +0200 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,10 @@ /* * @test - * @bug 6175517 6278707 6318827 6305746 6392303 6600709 + * @bug 6175517 6278707 6318827 6305746 6392303 6600709 8010285 * @summary General MXBean test. * @author Eamonn McManus + * @author Jaroslav Bachorik * @run clean MXBeanTest MerlinMXBean TigerMXBean * @run build MXBeanTest MerlinMXBean TigerMXBean * @run main MXBeanTest @@ -51,6 +52,7 @@ import javax.management.MBeanServerConnection; import javax.management.MBeanServerFactory; import javax.management.MBeanServerInvocationHandler; +import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import javax.management.StandardMBean; import javax.management.openmbean.ArrayType; @@ -75,6 +77,8 @@ testExplicitMXBean(); testSubclassMXBean(); testIndirectMXBean(); + testNonCompliantMXBean("Private", new Private()); + testNonCompliantMXBean("NonCompliant", new NonCompliant()); if (failures == 0) System.out.println("Test passed"); @@ -84,6 +88,39 @@ 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 int[] getInts(); } @@ -110,6 +147,19 @@ } } + 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 { System.out.println("Explicit MXBean test..."); MBeanServer mbs = MBeanServerFactory.newMBeanServer(); diff -r 8561f2098727 -r b359f8adc8ad jdk/test/javax/management/proxy/JMXProxyFallbackTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/management/proxy/JMXProxyFallbackTest.java Thu Jul 11 21:11:03 2013 +0200 @@ -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; + } + } + } +} diff -r 8561f2098727 -r b359f8adc8ad jdk/test/javax/management/proxy/JMXProxyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/management/proxy/JMXProxyTest.java Thu Jul 11 21:11:03 2013 +0200 @@ -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; + } + } + } +}