Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/javax/management/remote/mandatory/loading/MethodResultTest.java
38867 views
/*1* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 489847826* @summary Tests client default class loader used before JSR 160 loader27* @author Eamonn McManus28* @run clean MethodResultTest29* @run build MethodResultTest30* @run main MethodResultTest31*/3233import java.io.*;34import java.net.*;35import java.util.*;36import javax.management.*;37import javax.management.remote.*;3839/*40This test checks that the class loader that is used to deserialize41the return values from remote MBean server operations is indeed the42one specified by the user. The only MBean server operations that43matter are those than can return an arbitrary Object. We don't44care about getMBeanCount or queryNames or whatever because their45return values are always of classes loaded by the bootstrap loader.46But for the operations getAttribute, getAttributes, setAttributes,47and invoke, the return value can include any Java class. This is48also true of getMBeanInfo, since the return value can be an exotic49subclass of MBeanInfo, or a ModelMBeanInfo that refers to an50arbitrary Object. The JMX Remote API spec requires that these51return values be deserialized using the class loader supplied by52the user (default is context class loader). In particular it must53not be deserialized using the system class loader, which it will be54with RMI unless special precautions are taken.55*/56public class MethodResultTest {57public static void main(String[] args) throws Exception {58Class thisClass = MethodResultTest.class;59Class exoticClass = Exotic.class;60String exoticClassName = Exotic.class.getName();61ClassLoader testClassLoader = thisClass.getClassLoader();62if (!(testClassLoader instanceof URLClassLoader)) {63System.out.println("TEST INVALID: Not loaded by a " +64"URLClassLoader: " + testClassLoader);65System.exit(1);66}6768URLClassLoader tcl = (URLClassLoader) testClassLoader;69URL[] urls = tcl.getURLs();70ClassLoader shadowLoader =71new ShadowLoader(urls, testClassLoader,72new String[] {exoticClassName,73ExoticMBeanInfo.class.getName(),74ExoticException.class.getName()});75Class cl = shadowLoader.loadClass(exoticClassName);76if (cl == exoticClass) {77System.out.println("TEST INVALID: Shadow class loader loaded " +78"same class as test class loader");79System.exit(1);80}81Thread.currentThread().setContextClassLoader(shadowLoader);8283ObjectName on = new ObjectName("a:b=c");84MBeanServer mbs = MBeanServerFactory.newMBeanServer();85mbs.createMBean(Thing.class.getName(), on);8687final String[] protos = {"rmi", "iiop", "jmxmp"};8889boolean ok = true;90for (int i = 0; i < protos.length; i++) {91try {92ok &= test(protos[i], mbs, on);93System.out.println();94} catch (Exception e) {95System.out.println("TEST FAILED WITH EXCEPTION:");96e.printStackTrace(System.out);97ok = false;98}99}100101if (ok)102System.out.println("Test passed");103else {104System.out.println("TEST FAILED");105System.exit(1);106}107}108109private static boolean test(String proto, MBeanServer mbs, ObjectName on)110throws Exception {111System.out.println("Testing for protocol " + proto);112113JMXConnectorServer cs;114JMXServiceURL url = new JMXServiceURL(proto, null, 0);115try {116cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null,117mbs);118} catch (MalformedURLException e) {119System.out.println("System does not recognize URL: " + url +120"; ignoring");121return true;122}123cs.start();124JMXServiceURL addr = cs.getAddress();125JMXConnector client = JMXConnectorFactory.connect(addr);126MBeanServerConnection mbsc = client.getMBeanServerConnection();127Object getAttributeExotic = mbsc.getAttribute(on, "Exotic");128AttributeList getAttrs =129mbsc.getAttributes(on, new String[] {"Exotic"});130AttributeList setAttrs = new AttributeList();131setAttrs.add(new Attribute("Exotic", new Exotic()));132setAttrs = mbsc.setAttributes(on, setAttrs);133Object invokeExotic =134mbsc.invoke(on, "anExotic", new Object[] {}, new String[] {});135MBeanInfo exoticMBI = mbsc.getMBeanInfo(on);136137mbsc.setAttribute(on, new Attribute("Exception", Boolean.TRUE));138Exception139getAttributeException, setAttributeException, invokeException;140try {141try {142mbsc.getAttribute(on, "Exotic");143throw noException("getAttribute");144} catch (Exception e) {145getAttributeException = e;146}147try {148mbsc.setAttribute(on, new Attribute("Exotic", new Exotic()));149throw noException("setAttribute");150} catch (Exception e) {151setAttributeException = e;152}153try {154mbsc.invoke(on, "anExotic", new Object[] {}, new String[] {});155throw noException("invoke");156} catch (Exception e) {157invokeException = e;158}159} finally {160mbsc.setAttribute(on, new Attribute("Exception", Boolean.FALSE));161}162client.close();163cs.stop();164165boolean ok = true;166167ok &= checkAttrs("getAttributes", getAttrs);168ok &= checkAttrs("setAttributes", setAttrs);169170ok &= checkType("getAttribute", getAttributeExotic, Exotic.class);171ok &= checkType("getAttributes", attrValue(getAttrs), Exotic.class);172ok &= checkType("setAttributes", attrValue(setAttrs), Exotic.class);173ok &= checkType("invoke", invokeExotic, Exotic.class);174ok &= checkType("getMBeanInfo", exoticMBI, ExoticMBeanInfo.class);175176ok &= checkExceptionType("getAttribute", getAttributeException,177ExoticException.class);178ok &= checkExceptionType("setAttribute", setAttributeException,179ExoticException.class);180ok &= checkExceptionType("invoke", invokeException,181ExoticException.class);182183if (ok)184System.out.println("Test passes for protocol " + proto);185return ok;186}187188private static Exception noException(String what) {189final String msg =190"Operation " + what + " returned when exception expected";191return new IllegalStateException(msg);192}193194private static Object attrValue(AttributeList attrs) {195return ((Attribute) attrs.get(0)).getValue();196}197198private static boolean checkType(String what, Object object,199Class wrongClass) {200return checkType(what, object, wrongClass, false);201}202203private static boolean checkType(String what, Object object,204Class wrongClass, boolean isException) {205final String type = isException ? "exception" : "object";206final String rendered = isException ? "thrown" : "returned";207System.out.println("For " + type + " " + rendered + " by " + what +208":");209if (wrongClass.isInstance(object)) {210System.out.println("TEST FAILS: " + type + " loaded by test " +211"classloader");212return false;213}214String className = object.getClass().getName();215if (!className.equals(wrongClass.getName())) {216System.out.println("TEST FAILS: " + rendered + " " + type +217" has wrong class name: " + className);218return false;219}220System.out.println("Test passes: " + rendered + " " + type +221" has same class name but is not same class");222return true;223}224225private static boolean checkExceptionType(String what, Exception exception,226Class wrongClass) {227if (!(exception instanceof MBeanException)) {228System.out.println("Exception thrown by " + what + " is not an " +229MBeanException.class.getName() +230":");231exception.printStackTrace(System.out);232return false;233}234235exception = ((MBeanException) exception).getTargetException();236237return checkType(what, exception, wrongClass, true);238}239240private static boolean checkAttrs(String what, AttributeList attrs) {241if (attrs.size() != 1) {242System.out.println("TEST FAILS: list returned by " + what +243" does not have size 1: " + attrs);244return false;245}246Attribute attr = (Attribute) attrs.get(0);247if (!"Exotic".equals(attr.getName())) {248System.out.println("TEST FAILS: " + what + " returned wrong " +249"attribute: " + attr);250return false;251}252253return true;254}255256public static class Thing257extends StandardMBean implements ThingMBean {258public Thing() throws NotCompliantMBeanException {259super(ThingMBean.class);260}261262public Exotic getExotic() throws ExoticException {263if (exception)264throw new ExoticException();265return new Exotic();266}267268public void setExotic(Exotic x) throws ExoticException {269if (exception)270throw new ExoticException();271}272273public Exotic anExotic() throws ExoticException {274if (exception)275throw new ExoticException();276return new Exotic();277}278279public void cacheMBeanInfo(MBeanInfo mbi) {280if (mbi != null)281mbi = new ExoticMBeanInfo(mbi);282super.cacheMBeanInfo(mbi);283}284285public void setException(boolean x) {286this.exception = x;287}288289private boolean exception;290}291292public static interface ThingMBean {293public Exotic getExotic() throws ExoticException;294public void setExotic(Exotic x) throws ExoticException;295public Exotic anExotic() throws ExoticException;296public void setException(boolean x);297}298299public static class Exotic implements Serializable {}300301public static class ExoticException extends Exception {}302303public static class ExoticMBeanInfo extends MBeanInfo {304public ExoticMBeanInfo(MBeanInfo mbi) {305super(mbi.getClassName(),306mbi.getDescription(),307mbi.getAttributes(),308mbi.getConstructors(),309mbi.getOperations(),310mbi.getNotifications());311}312}313314private static class ShadowLoader extends URLClassLoader {315ShadowLoader(URL[] urls, ClassLoader realLoader,316String[] shadowClassNames) {317super(urls, null);318this.realLoader = realLoader;319this.shadowClassNames = Arrays.asList(shadowClassNames);320}321322protected Class findClass(String name) throws ClassNotFoundException {323if (shadowClassNames.contains(name))324return super.findClass(name);325else326return realLoader.loadClass(name);327}328329private final ClassLoader realLoader;330private final List shadowClassNames;331}332}333334335