| /* |
| * Copyright (c) 2003, 2015, 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 4950756 |
| * @summary Test that RequiredModelMBean.invoke will not invoke methods |
| * from the RequiredModelMBean class itself if they are not in the |
| * ModelMBeanInfo |
| * @author Eamonn McManus |
| * |
| * @run clean RequiredModelMBeanMethodTest |
| * @run build RequiredModelMBeanMethodTest |
| * @run main RequiredModelMBeanMethodTest |
| */ |
| |
| import java.lang.reflect.*; |
| import javax.management.*; |
| import javax.management.modelmbean.*; |
| |
| /* |
| * We do the same test with a number of different operations: |
| * |
| * - A plain operation that is directed to the managed resource in the |
| * usual way. We give it some parameters so we can test that the |
| * class loading logic for signature parameters is reasonable. |
| * |
| * - An operation (removeNotificationListener) that is directed to the |
| * RequiredModelMBean itself. We use this particular operation because |
| * it will throw an exception, which allows us to check that it did in |
| * fact execute. |
| * |
| * - An operation (load()) that has the same signature as a |
| * RequiredModelMBean operation but is directed to the resource |
| * because of a "class" field in the descriptor. |
| * |
| * - An operation (store()) that has the same signature as a |
| * RequiredModelMBean operation but is directed to the resource |
| * because of a "targetObject" field in the descriptor. |
| * |
| * In each case we check that the operation does not work if it is not |
| * in the ModelMBeanInfo, and does work if it is. |
| */ |
| public class RequiredModelMBeanMethodTest { |
| public static void main(String[] args) throws Exception { |
| boolean ok = true; |
| MBeanServer mbs = MBeanServerFactory.createMBeanServer(); |
| |
| Descriptor tralalaDescriptor = |
| new DescriptorSupport(new String[] { |
| "name=tralala", |
| "descriptorType=operation", |
| "role=operation", |
| "targetType=ObjectReference", |
| }); |
| Method tralalaMethod = |
| Resource.class.getMethod("tralala", |
| new Class[] {int.class, Resource.class}); |
| ModelMBeanOperationInfo tralalaInfo = |
| new ModelMBeanOperationInfo("tralala descr", tralalaMethod, |
| tralalaDescriptor); |
| |
| Method remACNLMethod = |
| RequiredModelMBean.class.getMethod("removeAttributeChangeNotificationListener", |
| new Class[] { |
| NotificationListener.class, |
| String.class |
| }); |
| ModelMBeanOperationInfo remACNLInfo = |
| new ModelMBeanOperationInfo("remACNL descr", remACNLMethod); |
| |
| Descriptor loadDescriptor = |
| new DescriptorSupport(new String[] { |
| "name=load", |
| "descriptorType=operation", |
| "role=operation", |
| "targetType=ObjectReference", |
| "class=" + Resource.class.getName(), |
| }); |
| ModelMBeanOperationInfo loadInfo = |
| new ModelMBeanOperationInfo("load", "load descr", |
| new MBeanParameterInfo[0], |
| "void", ModelMBeanOperationInfo.ACTION, |
| loadDescriptor); |
| |
| Descriptor storeDescriptor = |
| new DescriptorSupport(new String[] { |
| "name=store", |
| "descriptorType=operation", |
| "role=operation", |
| "targetType=ObjectReference", |
| }); |
| storeDescriptor.setField("targetObject", resource); |
| ModelMBeanOperationInfo storeInfo = |
| new ModelMBeanOperationInfo("store", "store descr", |
| new MBeanParameterInfo[0], |
| "void", ModelMBeanOperationInfo.ACTION, |
| storeDescriptor); |
| |
| ModelMBeanInfo emptyMMBI = |
| new ModelMBeanInfoSupport(Resource.class.getName(), |
| "empty descr", |
| null, null, null, null); |
| ModelMBean emptyMMB = new RequiredModelMBean(emptyMMBI); |
| emptyMMB.setManagedResource(resource, "ObjectReference"); |
| ObjectName emptyMMBName = new ObjectName("test:type=Empty"); |
| mbs.registerMBean(emptyMMB, emptyMMBName); |
| |
| System.out.println("Testing that we cannot call methods not in the " + |
| "ModelMBeanInfo"); |
| try { |
| boolean thisok = test(mbs, emptyMMBName, false); |
| if (thisok) |
| System.out.println("...OK"); |
| else |
| ok = false; |
| } catch (Exception e) { |
| System.out.println("TEST FAILED: Caught exception:"); |
| e.printStackTrace(System.out); |
| ok = false; |
| } |
| |
| ModelMBeanOperationInfo[] opInfos = { |
| tralalaInfo, remACNLInfo, loadInfo, storeInfo, |
| }; |
| ModelMBeanInfo fullMMBI = |
| new ModelMBeanInfoSupport(Resource.class.getName(), |
| "full descr", |
| null, null, opInfos, null); |
| ModelMBean fullMMB = new RequiredModelMBean(fullMMBI); |
| fullMMB.setManagedResource(resource, "ObjectReference"); |
| ObjectName fullMMBName = new ObjectName("test:type=Full"); |
| mbs.registerMBean(fullMMB, fullMMBName); |
| |
| |
| System.out.println(); |
| System.out.println("Testing that we can call methods in the " + |
| "ModelMBeanInfo"); |
| System.out.println(" and that \"class\" or \"targetObject\" in " + |
| "descriptor directs methods to resource"); |
| try { |
| boolean thisok = test(mbs, fullMMBName, true); |
| if (thisok) |
| System.out.println("...OK"); |
| else |
| ok = false; |
| } catch (Exception e) { |
| System.out.println("TEST FAILED: Caught exception:"); |
| e.printStackTrace(System.out); |
| ok = false; |
| } |
| |
| if (ok) { |
| if (!resource.loadCalled || !resource.storeCalled) { |
| System.out.println("TEST FAILED: not called:" + |
| (resource.loadCalled ? "" : " load") + |
| (resource.storeCalled ? "" : " store")); |
| ok = false; |
| } |
| } |
| |
| // Test the invoke("class.method") form |
| if (ok) { |
| System.out.println("Testing invoke(\"class.method\")"); |
| resource.loadCalled = false; |
| mbs.invoke(fullMMBName, Resource.class.getName() + ".load", |
| null, null); |
| if (!resource.loadCalled) { |
| System.out.println("TEST FAILED: load not called"); |
| ok = false; |
| } |
| try { |
| mbs.invoke(fullMMBName, |
| RequiredModelMBean.class.getName() + |
| ".removeAttributeChangeNotificationListener", |
| new Object[] {boringListener, null}, |
| new String[] { |
| NotificationListener.class.getName(), |
| String.class.getName(), |
| }); |
| System.out.println("TEST FAILED: removeNotificationListener" + |
| " returned successfully but " + |
| "should not have"); |
| ok = false; |
| } catch (MBeanException e) { |
| final Exception target = e.getTargetException(); |
| if (target instanceof ListenerNotFoundException) { |
| // OK: there is no such listener |
| } else |
| throw e; |
| } |
| } |
| |
| if (ok) |
| System.out.println("Test passed"); |
| else { |
| System.out.println("TEST FAILED"); |
| System.exit(1); |
| } |
| } |
| |
| private static boolean test(MBeanServer mbs, ObjectName name, |
| boolean shouldWork) |
| throws Exception { |
| |
| boolean ok = true; |
| |
| final String[] names = { |
| "tralala", |
| "removeAttributeChangeNotificationListener", |
| "load", |
| "store", |
| }; |
| |
| for (int i = 0; i < 4; i++) { |
| boolean thisok = true; |
| try { |
| switch (i) { |
| case 0: |
| String tralala = (String) |
| mbs.invoke(name, names[i], |
| new Object[] {new Integer(5), resource}, |
| new String[] {"int", |
| Resource.class.getName()}); |
| if (!"tralala".equals(tralala)) { |
| System.out.println("TEST FAILED: tralala returned: " + |
| tralala); |
| thisok = false; |
| } |
| break; |
| case 1: |
| try { |
| mbs.invoke(name, |
| names[i], |
| new Object[] {boringListener, null}, |
| new String[] { |
| NotificationListener.class.getName(), |
| String.class.getName(), |
| }); |
| System.out.println("TEST FAILED: " + names[i] + |
| " returned successfully but " + |
| "should not have"); |
| thisok = false; |
| } catch (MBeanException e) { |
| final Exception target = e.getTargetException(); |
| if (target instanceof ListenerNotFoundException) { |
| // OK: there is no such listener |
| } else |
| throw e; |
| } |
| break; |
| case 2: |
| case 3: |
| mbs.invoke(name, |
| names[i], |
| new Object[0], |
| new String[0]); |
| break; |
| default: |
| throw new AssertionError(); |
| } |
| |
| thisok = shouldWork; |
| if (!shouldWork) { |
| System.out.println("TEST FAILED: " + names[i] + |
| " worked but should not"); |
| } |
| } catch (MBeanException e) { |
| if (shouldWork) { |
| System.out.println("TEST FAILED: " + names[i] + ": " + e); |
| e.printStackTrace(System.out); |
| thisok = false; |
| } else { |
| Exception target = e.getTargetException(); |
| if (!(target instanceof ServiceNotFoundException)) { |
| System.out.println("TEST FAILED: " + names[i] + |
| ": wrong exception: " + target); |
| thisok = false; |
| } |
| } |
| } catch (Exception e) { |
| System.out.println("TEST FAILED: " + names[i] + ": " + e); |
| e.printStackTrace(System.out); |
| thisok = false; |
| } |
| |
| if (thisok) |
| System.out.println("OK: " + names[i]); |
| else |
| ok = false; |
| } |
| |
| return ok; |
| } |
| |
| public static class Resource { |
| public String tralala(int x, Resource y) { |
| if (x != 5 || y != this) |
| return "wrong params: " + x + " " + y; |
| return "tralala"; |
| } |
| |
| public void load() { |
| loadCalled = true; |
| } |
| |
| public void store() { |
| storeCalled = true; |
| } |
| |
| boolean loadCalled, storeCalled; |
| } |
| |
| private static Resource resource = new Resource(); |
| |
| private static NotificationListener boringListener = |
| new NotificationListener() { |
| public void handleNotification(Notification n, Object h) { |
| } |
| }; |
| } |