8010285: Enforce the requirement of Management Interfaces being public
Reviewed-by: sjiang, dfuchs, mchung
--- 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 <T> Class<? super T> getStandardMBeanInterface(Class<T> baseClass)
- throws NotCompliantMBeanException {
- Class<? super T> current = baseClass;
- Class<? super T> 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<? super T> current = baseClass;
+ Class<? super T> 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;
--- 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<M> {
-
static interface MBeanVisitor<M> {
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 {
--- 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 <a href="package-summary.html#mgIface">compliant MBean
+ * interface</a>
*/
public static <T> 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 <a href="package-summary.html#mgIface">compliant MBean
+ * interface</a>
*/
public static <T> 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> 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> T newMXBeanProxy(MBeanServerConnection connection,
ObjectName objectName,
@@ -348,21 +362,25 @@
/**
* <p>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}".</p>
*
* @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);
- }
}
--- 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> T newProxyInstance(MBeanServerConnection connection,
ObjectName objectName,
--- 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 @@
/**
<p>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:</p>
+ 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:</p>
<pre>
public interface WhatsitMXBean {}
@@ -71,6 +71,8 @@
<p>The following interfaces are not MXBean interfaces:</p>
<pre>
+ interface NonPublicInterfaceNotMXBean{}
+
public interface Whatsit3Interface{}
@MXBean(false)
--- 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 @@
<p>The fundamental notion of the JMX API is the <em>MBean</em>.
An MBean is a named <em>managed object</em> representing a
- resource. It has a <em>management interface</em> consisting
- of:</p>
+ resource. It has a <em id="mgIface">management interface</em>
+ which must be <em>public</em> and consist of:</p>
<ul>
<li>named and typed attributes that can be read and/or
--- 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 {
}
--- /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;
+ }
+ }
+ }
+}
--- /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;
+ }
+ }
+ }
+}
--- /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++;
+ }
+}
--- 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();
--- /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;
+ }
+ }
+ }
+}
--- /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;
+ }
+ }
+ }
+}