From ec6cb721e1ff4e4d43bc89f87986ab52ffe0284d Mon Sep 17 00:00:00 2001
From: Jaroslav Bachorik
Date: Thu, 11 Jul 2013 21:11:03 +0200
Subject: [PATCH] 8010285: Enforce the requirement of Management Interfaces
being public
Reviewed-by: sjiang, dfuchs, mchung
---
.../com/sun/jmx/mbeanserver/Introspector.java | 52 +++--
.../sun/jmx/mbeanserver/MBeanAnalyzer.java | 7 +-
.../share/classes/javax/management/JMX.java | 42 ++--
.../MBeanServerInvocationHandler.java | 2 +-
.../classes/javax/management/MXBean.java | 8 +-
.../classes/javax/management/package.html | 4 +-
.../management/ManagementFactoryHelper.java | 26 +--
.../MBeanServer/MBeanFallbackTest.java | 94 +++++++++
.../management/MBeanServer/MBeanTest.java | 158 +++++++++++++++
.../management/mxbean/MXBeanFallbackTest.java | 85 ++++++++
.../javax/management/mxbean/MXBeanTest.java | 54 ++++-
.../proxy/JMXProxyFallbackTest.java | 100 +++++++++
.../javax/management/proxy/JMXProxyTest.java | 191 ++++++++++++++++++
13 files changed, 768 insertions(+), 55 deletions(-)
create mode 100644 jdk/test/javax/management/MBeanServer/MBeanFallbackTest.java
create mode 100644 jdk/test/javax/management/MBeanServer/MBeanTest.java
create mode 100644 jdk/test/javax/management/mxbean/MXBeanFallbackTest.java
create mode 100644 jdk/test/javax/management/proxy/JMXProxyFallbackTest.java
create mode 100644 jdk/test/javax/management/proxy/JMXProxyTest.java
diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java
index 732c280f7dd..0e08177d7f2 100644
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java
+++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java
@@ -52,6 +52,7 @@ import javax.management.NotCompliantMBeanException;
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 @@ import sun.reflect.misc.ReflectUtil;
* @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 @@ public class Introspector {
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 @@ public class Introspector {
* not a JMX compliant Standard MBean.
*/
public static Class super T> getStandardMBeanInterface(Class 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 @@ public class Introspector {
}
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 --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java
index 5e5375d0974..d7d06a04a73 100644
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java
+++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java
@@ -28,6 +28,8 @@ package com.sun.jmx.mbeanserver;
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 @@ import javax.management.NotCompliantMBeanException;
* @since 1.6
*/
class MBeanAnalyzer {
-
static interface MBeanVisitor {
public void visitAttribute(String attributeName,
M getter,
@@ -107,6 +108,10 @@ class MBeanAnalyzer {
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 --git a/jdk/src/share/classes/javax/management/JMX.java b/jdk/src/share/classes/javax/management/JMX.java
index 7f8cc411964..fe5d9093ac2 100644
--- a/jdk/src/share/classes/javax/management/JMX.java
+++ b/jdk/src/share/classes/javax/management/JMX.java
@@ -160,6 +160,10 @@ public class JMX {
* 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 @@ public class JMX {
* 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 @@ public class JMX {
* 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 @@ public class JMX {
* 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 @@ public class JMX {
/**
* 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 @@ public class JMX {
boolean notificationEmitter,
boolean isMXBean) {
- if (System.getSecurityManager() != null) {
- checkProxyInterface(interfaceClass);
- }
try {
if (isMXBean) {
// Check interface for MXBean compliance
@@ -419,17 +434,4 @@ public class JMX {
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 --git a/jdk/src/share/classes/javax/management/MBeanServerInvocationHandler.java b/jdk/src/share/classes/javax/management/MBeanServerInvocationHandler.java
index bc174fb303f..485dec8b59c 100644
--- a/jdk/src/share/classes/javax/management/MBeanServerInvocationHandler.java
+++ b/jdk/src/share/classes/javax/management/MBeanServerInvocationHandler.java
@@ -225,7 +225,7 @@ public class MBeanServerInvocationHandler implements InvocationHandler {
*
* @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 --git a/jdk/src/share/classes/javax/management/MXBean.java b/jdk/src/share/classes/javax/management/MXBean.java
index 4ff10d360af..e4c920651bc 100644
--- a/jdk/src/share/classes/javax/management/MXBean.java
+++ b/jdk/src/share/classes/javax/management/MXBean.java
@@ -54,9 +54,9 @@ import javax.management.openmbean.TabularType;
/**
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 @@ import javax.management.openmbean.TabularType;
The following interfaces are not MXBean interfaces:
+ interface NonPublicInterfaceNotMXBean{}
+
public interface Whatsit3Interface{}
@MXBean(false)
diff --git a/jdk/src/share/classes/javax/management/package.html b/jdk/src/share/classes/javax/management/package.html
index 4c9b012cf22..9cd9ef81766 100644
--- a/jdk/src/share/classes/javax/management/package.html
+++ b/jdk/src/share/classes/javax/management/package.html
@@ -53,8 +53,8 @@ questions.
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 --git a/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java b/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java
index 6e875a27914..43079e986d6 100644
--- a/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java
+++ b/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java
@@ -147,18 +147,20 @@ public class ManagementFactoryHelper {
}
}
- // 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 --git a/jdk/test/javax/management/MBeanServer/MBeanFallbackTest.java b/jdk/test/javax/management/MBeanServer/MBeanFallbackTest.java
new file mode 100644
index 00000000000..dcb5e1803a4
--- /dev/null
+++ b/jdk/test/javax/management/MBeanServer/MBeanFallbackTest.java
@@ -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 --git a/jdk/test/javax/management/MBeanServer/MBeanTest.java b/jdk/test/javax/management/MBeanServer/MBeanTest.java
new file mode 100644
index 00000000000..1ac50573e5f
--- /dev/null
+++ b/jdk/test/javax/management/MBeanServer/MBeanTest.java
@@ -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 --git a/jdk/test/javax/management/mxbean/MXBeanFallbackTest.java b/jdk/test/javax/management/mxbean/MXBeanFallbackTest.java
new file mode 100644
index 00000000000..388ffc9373d
--- /dev/null
+++ b/jdk/test/javax/management/mxbean/MXBeanFallbackTest.java
@@ -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 --git a/jdk/test/javax/management/mxbean/MXBeanTest.java b/jdk/test/javax/management/mxbean/MXBeanTest.java
index 7d1c79c9597..ecafe49adbb 100644
--- a/jdk/test/javax/management/mxbean/MXBeanTest.java
+++ b/jdk/test/javax/management/mxbean/MXBeanTest.java
@@ -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.MBeanServer;
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 @@ public class MXBeanTest {
testExplicitMXBean();
testSubclassMXBean();
testIndirectMXBean();
+ testNonCompliantMXBean("Private", new Private());
+ testNonCompliantMXBean("NonCompliant", new NonCompliant());
if (failures == 0)
System.out.println("Test passed");
@@ -84,6 +88,39 @@ public class MXBeanTest {
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 @@ 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 {
System.out.println("Explicit MXBean test...");
MBeanServer mbs = MBeanServerFactory.newMBeanServer();
diff --git a/jdk/test/javax/management/proxy/JMXProxyFallbackTest.java b/jdk/test/javax/management/proxy/JMXProxyFallbackTest.java
new file mode 100644
index 00000000000..d1243593c11
--- /dev/null
+++ b/jdk/test/javax/management/proxy/JMXProxyFallbackTest.java
@@ -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 --git a/jdk/test/javax/management/proxy/JMXProxyTest.java b/jdk/test/javax/management/proxy/JMXProxyTest.java
new file mode 100644
index 00000000000..0eb53cdebdb
--- /dev/null
+++ b/jdk/test/javax/management/proxy/JMXProxyTest.java
@@ -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;
+ }
+ }
+ }
+}