1 /* 2 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 4950756 27 * @summary Test that RequiredModelMBean.invoke will not invoke methods 28 * from the RequiredModelMBean class itself if they are not in the 29 * ModelMBeanInfo 30 * @author Eamonn McManus 31 * @run clean RequiredModelMBeanMethodTest 32 * @run build RequiredModelMBeanMethodTest 33 * @run main RequiredModelMBeanMethodTest 34 */ 35 36 import java.lang.reflect.*; 37 import javax.management.*; 38 import javax.management.modelmbean.*; 39 40 /* 41 * We do the same test with a number of different operations: 42 * 43 * - A plain operation that is directed to the managed resource in the 44 * usual way. We give it some parameters so we can test that the 45 * class loading logic for signature parameters is reasonable. 46 * 47 * - An operation (removeNotificationListener) that is directed to the 48 * RequiredModelMBean itself. We use this particular operation because 49 * it will throw an exception, which allows us to check that it did in 50 * fact execute. 51 * 52 * - An operation (load()) that has the same signature as a 53 * RequiredModelMBean operation but is directed to the resource 54 * because of a "class" field in the descriptor. 55 * 56 * - An operation (store()) that has the same signature as a 57 * RequiredModelMBean operation but is directed to the resource 58 * because of a "targetObject" field in the descriptor. 59 * 60 * In each case we check that the operation does not work if it is not 61 * in the ModelMBeanInfo, and does work if it is. 62 */ 63 public class RequiredModelMBeanMethodTest { 64 public static void main(String[] args) throws Exception { 65 boolean ok = true; 66 MBeanServer mbs = MBeanServerFactory.createMBeanServer(); 67 68 Descriptor tralalaDescriptor = 69 new DescriptorSupport(new String[] { 70 "name=tralala", 71 "descriptorType=operation", 72 "role=operation", 73 "targetType=ObjectReference", 74 }); 75 Method tralalaMethod = 76 Resource.class.getMethod("tralala", 77 new Class[] {int.class, Resource.class}); 78 ModelMBeanOperationInfo tralalaInfo = 79 new ModelMBeanOperationInfo("tralala descr", tralalaMethod, 80 tralalaDescriptor); 81 82 Method remACNLMethod = 83 RequiredModelMBean.class.getMethod("removeAttributeChangeNotificationListener", 84 new Class[] { 85 NotificationListener.class, 86 String.class 87 }); 88 ModelMBeanOperationInfo remACNLInfo = 89 new ModelMBeanOperationInfo("remACNL descr", remACNLMethod); 90 91 Descriptor loadDescriptor = 92 new DescriptorSupport(new String[] { 93 "name=load", 94 "descriptorType=operation", 95 "role=operation", 96 "targetType=ObjectReference", 97 "class=" + Resource.class.getName(), 98 }); 99 ModelMBeanOperationInfo loadInfo = 100 new ModelMBeanOperationInfo("load", "load descr", 101 new MBeanParameterInfo[0], 102 "void", ModelMBeanOperationInfo.ACTION, 103 loadDescriptor); 104 105 Descriptor storeDescriptor = 106 new DescriptorSupport(new String[] { 107 "name=store", 108 "descriptorType=operation", 109 "role=operation", 110 "targetType=ObjectReference", 111 }); 112 storeDescriptor.setField("targetObject", resource); 113 ModelMBeanOperationInfo storeInfo = 114 new ModelMBeanOperationInfo("store", "store descr", 115 new MBeanParameterInfo[0], 116 "void", ModelMBeanOperationInfo.ACTION, 117 storeDescriptor); 118 119 ModelMBeanInfo emptyMMBI = 120 new ModelMBeanInfoSupport(Resource.class.getName(), 121 "empty descr", 122 null, null, null, null); 123 ModelMBean emptyMMB = new RequiredModelMBean(emptyMMBI); 124 emptyMMB.setManagedResource(resource, "ObjectReference"); 125 ObjectName emptyMMBName = new ObjectName("test:type=Empty"); 126 mbs.registerMBean(emptyMMB, emptyMMBName); 127 128 System.out.println("Testing that we cannot call methods not in the " + 129 "ModelMBeanInfo"); 130 try { 131 boolean thisok = test(mbs, emptyMMBName, false); 132 if (thisok) 133 System.out.println("...OK"); 134 else 135 ok = false; 136 } catch (Exception e) { 137 System.out.println("TEST FAILED: Caught exception:"); 138 e.printStackTrace(System.out); 139 ok = false; 140 } 141 142 ModelMBeanOperationInfo[] opInfos = { 143 tralalaInfo, remACNLInfo, loadInfo, storeInfo, 144 }; 145 ModelMBeanInfo fullMMBI = 146 new ModelMBeanInfoSupport(Resource.class.getName(), 147 "full descr", 148 null, null, opInfos, null); 149 ModelMBean fullMMB = new RequiredModelMBean(fullMMBI); 150 fullMMB.setManagedResource(resource, "ObjectReference"); 151 ObjectName fullMMBName = new ObjectName("test:type=Full"); 152 mbs.registerMBean(fullMMB, fullMMBName); 153 154 155 System.out.println(); 156 System.out.println("Testing that we can call methods in the " + 157 "ModelMBeanInfo"); 158 System.out.println(" and that \"class\" or \"targetObject\" in " + 159 "descriptor directs methods to resource"); 160 try { 161 boolean thisok = test(mbs, fullMMBName, true); 162 if (thisok) 163 System.out.println("...OK"); 164 else 165 ok = false; 166 } catch (Exception e) { 167 System.out.println("TEST FAILED: Caught exception:"); 168 e.printStackTrace(System.out); 169 ok = false; 170 } 171 172 if (ok) { 173 if (!resource.loadCalled || !resource.storeCalled) { 174 System.out.println("TEST FAILED: not called:" + 175 (resource.loadCalled ? "" : " load") + 176 (resource.storeCalled ? "" : " store")); 177 ok = false; 178 } 179 } 180 181 // Test the invoke("class.method") form 182 if (ok) { 183 System.out.println("Testing invoke(\"class.method\")"); 184 resource.loadCalled = false; 185 mbs.invoke(fullMMBName, Resource.class.getName() + ".load", 186 null, null); 187 if (!resource.loadCalled) { 188 System.out.println("TEST FAILED: load not called"); 189 ok = false; 190 } 191 try { 192 mbs.invoke(fullMMBName, 193 RequiredModelMBean.class.getName() + 194 ".removeAttributeChangeNotificationListener", 195 new Object[] {boringListener, null}, 196 new String[] { 197 NotificationListener.class.getName(), 198 String.class.getName(), 199 }); 200 System.out.println("TEST FAILED: removeNotificationListener" + 201 " returned successfully but " + 202 "should not have"); 203 ok = false; 204 } catch (MBeanException e) { 205 final Exception target = e.getTargetException(); 206 if (target instanceof ListenerNotFoundException) { 207 // OK: there is no such listener 208 } else 209 throw e; 210 } 211 } 212 213 if (ok) 214 System.out.println("Test passed"); 215 else { 216 System.out.println("TEST FAILED"); 217 System.exit(1); 218 } 219 } 220 221 private static boolean test(MBeanServer mbs, ObjectName name, 222 boolean shouldWork) 223 throws Exception { 224 225 boolean ok = true; 226 227 final String[] names = { 228 "tralala", 229 "removeAttributeChangeNotificationListener", 230 "load", 231 "store", 232 }; 233 234 for (int i = 0; i < 4; i++) { 235 boolean thisok = true; 236 try { 237 switch (i) { 238 case 0: 239 String tralala = (String) 240 mbs.invoke(name, names[i], 241 new Object[] {new Integer(5), resource}, 242 new String[] {"int", 243 Resource.class.getName()}); 244 if (!"tralala".equals(tralala)) { 245 System.out.println("TEST FAILED: tralala returned: " + 246 tralala); 247 thisok = false; 248 } 249 break; 250 case 1: 251 try { 252 mbs.invoke(name, 253 names[i], 254 new Object[] {boringListener, null}, 255 new String[] { 256 NotificationListener.class.getName(), 257 String.class.getName(), 258 }); 259 System.out.println("TEST FAILED: " + names[i] + 260 " returned successfully but " + 261 "should not have"); 262 thisok = false; 263 } catch (MBeanException e) { 264 final Exception target = e.getTargetException(); 265 if (target instanceof ListenerNotFoundException) { 266 // OK: there is no such listener 267 } else 268 throw e; 269 } 270 break; 271 case 2: 272 case 3: 273 mbs.invoke(name, 274 names[i], 275 new Object[0], 276 new String[0]); 277 break; 278 default: 279 throw new AssertionError(); 280 } 281 282 thisok = shouldWork; 283 if (!shouldWork) { 284 System.out.println("TEST FAILED: " + names[i] + 285 " worked but should not"); 286 } 287 } catch (MBeanException e) { 288 if (shouldWork) { 289 System.out.println("TEST FAILED: " + names[i] + ": " + e); 290 e.printStackTrace(System.out); 291 thisok = false; 292 } else { 293 Exception target = e.getTargetException(); 294 if (!(target instanceof ServiceNotFoundException)) { 295 System.out.println("TEST FAILED: " + names[i] + 296 ": wrong exception: " + target); 297 thisok = false; 298 } 299 } 300 } catch (Exception e) { 301 System.out.println("TEST FAILED: " + names[i] + ": " + e); 302 e.printStackTrace(System.out); 303 thisok = false; 304 } 305 306 if (thisok) 307 System.out.println("OK: " + names[i]); 308 else 309 ok = false; 310 } 311 312 return ok; 313 } 314 315 public static class Resource { 316 public String tralala(int x, Resource y) { 317 if (x != 5 || y != this) 318 return "wrong params: " + x + " " + y; 319 return "tralala"; 320 } 321 322 public void load() { 323 loadCalled = true; 324 } 325 326 public void store() { 327 storeCalled = true; 328 } 329 330 boolean loadCalled, storeCalled; 331 } 332 333 private static Resource resource = new Resource(); 334 335 private static NotificationListener boringListener = 336 new NotificationListener() { 337 public void handleNotification(Notification n, Object h) { 338 } 339 }; 340 }