1 /* 2 * Copyright (c) 2003, 2015, 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 4874819 27 * @summary Test that MBeanInfo classes no longer throw an 28 * IllegalArgumentException when attribute names, operation names, and 29 * Java type names do not strictly follow the expected Java syntax. 30 * @author Eamonn McManus, Daniel Fuchs 31 * 32 * @run clean SimpleModelMBeanCommand 33 * @run build SimpleModelMBeanCommand 34 * @run main/othervm/java.security.policy=policy SimpleModelMBeanCommand 35 */ 36 37 import java.lang.reflect.*; 38 import java.util.*; 39 import javax.management.*; 40 import javax.management.modelmbean.*; 41 42 public class SimpleModelMBeanCommand { 43 44 public static class Resource { 45 public int getNumber() { 46 return number; 47 } 48 49 public void setNumber(int n) { 50 number = n; 51 } 52 53 public int addOne(int x) { 54 return x + 1; 55 } 56 57 public Object[] getArray() { 58 return (Object[]) array.clone(); 59 } 60 61 // doesn't look like an attribute so not seen by caching logic 62 public void tweakArray(Object[] array) { 63 this.array = (Object[]) array.clone(); 64 } 65 66 private int number = 1234; 67 private Object[] array = {"hello", "world"}; 68 } 69 70 public static void main(String[] args) { 71 int errorCount = 0; 72 for (int i = 0; i < NTESTS; i++) { 73 try { 74 System.out.println("Test " + i + ":"); 75 test(i); 76 } catch (Throwable e) { 77 errorCount++; 78 boolean first = true; 79 do { 80 System.err.println(first ? "Exception:" : "Caused by:"); 81 first = false; 82 e.printStackTrace(); 83 Throwable nexte; 84 nexte = e.getCause(); 85 if (nexte == null) { // old JMX 86 if (e instanceof MBeanException) 87 nexte = ((MBeanException) e).getTargetException(); 88 } 89 e = nexte; 90 } while (e != null); 91 } 92 } 93 if (errorCount == 0) { 94 System.out.println("All ModelMBean tests successfuly passed"); 95 System.out.println("Bye! Bye!"); 96 // JTReg doesn't like System.exit(0); 97 return; 98 } else { 99 System.err.println("ERROR: " + errorCount + " tests failed"); 100 System.exit(errorCount); 101 } 102 103 } 104 105 private static void test(int testno) throws Exception { 106 // com.sun.jmx.trace.TraceImplementation.init(2); 107 Resource resource = new Resource(); 108 Class resourceClass = Resource.class; 109 Class rmmbClass = RequiredModelMBean.class; 110 Method setManagedResource = 111 rmmbClass.getMethod("setManagedResource", 112 new Class[] {Object.class, 113 String.class}); 114 Method sendNotification = 115 rmmbClass.getMethod("sendNotification", 116 new Class[] {Notification.class}); 117 Method addAttributeChangeNL = 118 rmmbClass.getMethod("addAttributeChangeNotificationListener", 119 new Class[] {NotificationListener.class, 120 String.class, 121 Object.class}); 122 Method getArray = resourceClass.getMethod("getArray", new Class[0]); 123 Method getNumber = resourceClass.getMethod("getNumber", new Class[0]); 124 Method setNumber = 125 resourceClass.getMethod("setNumber", new Class[] {Integer.TYPE}); 126 Method tweakArray = 127 resourceClass.getMethod("tweakArray", 128 new Class[] {Object[].class}); 129 Method addOne = 130 resourceClass.getMethod("addOne", new Class[] {Integer.TYPE}); 131 MBeanServer mbs = MBeanServerFactory.newMBeanServer(); 132 ObjectName on = new ObjectName("a:b=c"); 133 Descriptor attrDescr = new DescriptorSupport(); 134 attrDescr.setField("name", "Array"); 135 attrDescr.setField("descriptorType", "attribute"); 136 attrDescr.setField("getMethod", "getArray"); 137 ModelMBeanAttributeInfo attrInfo = 138 new ModelMBeanAttributeInfo("Array", "array attr", getArray, 139 null, attrDescr); 140 Descriptor attrDescr2 = new DescriptorSupport(); 141 attrDescr2.setField("name", "Number"); 142 attrDescr2.setField("descriptorType", "attribute"); 143 attrDescr2.setField("getMethod", "getNumber"); 144 attrDescr2.setField("setMethod", "setNumber"); 145 ModelMBeanAttributeInfo attrInfo2 = 146 new ModelMBeanAttributeInfo("Number", "number attr", getNumber, 147 setNumber, attrDescr2); 148 Descriptor attrDescr3 = new DescriptorSupport(); 149 attrDescr3.setField("name", "Local"); 150 attrDescr3.setField("descriptorType", "attribute"); 151 attrDescr3.setField("currencyTimeLimit", "" + Integer.MAX_VALUE); 152 ModelMBeanAttributeInfo attrInfo3 = 153 new ModelMBeanAttributeInfo("Local", "java.lang.String", 154 "local attr", true, true, false, 155 attrDescr3); 156 Descriptor attrDescr4 = new DescriptorSupport(); 157 attrDescr4.setField("name", "Local2"); 158 attrDescr4.setField("descriptorType", "attribute"); 159 ModelMBeanAttributeInfo attrInfo4 = 160 new ModelMBeanAttributeInfo("Local2", "java.lang.String", 161 "local attr 2", true, true, false, 162 attrDescr4); 163 ModelMBeanAttributeInfo[] attrs = 164 new ModelMBeanAttributeInfo[] {attrInfo, attrInfo2, attrInfo3, 165 attrInfo4}; 166 ModelMBeanOperationInfo operInfo = 167 new ModelMBeanOperationInfo("getArray descr", getArray); 168 ModelMBeanOperationInfo operInfo2 = 169 new ModelMBeanOperationInfo("getNumber descr", getNumber); 170 ModelMBeanOperationInfo operInfo3 = 171 new ModelMBeanOperationInfo("addOne descr", addOne); 172 ModelMBeanOperationInfo operInfo4 = 173 new ModelMBeanOperationInfo("setNumber descr", setNumber); 174 ModelMBeanOperationInfo operInfo5 = 175 new ModelMBeanOperationInfo("tweakArray descr", tweakArray); 176 ModelMBeanOperationInfo operInfoSetManagedResource = 177 new ModelMBeanOperationInfo("setManagedResource descr", 178 setManagedResource); 179 ModelMBeanOperationInfo operInfoSendNotification = 180 new ModelMBeanOperationInfo("sendNotification descr", 181 sendNotification); 182 ModelMBeanOperationInfo operInfoAddAttributeChangeNL = 183 new ModelMBeanOperationInfo("AddAttributeChangeNL descr", 184 addAttributeChangeNL); 185 ModelMBeanOperationInfo[] opers = 186 new ModelMBeanOperationInfo[] {operInfo, operInfo2, operInfo3, 187 operInfo4, operInfo5, 188 operInfoSetManagedResource, 189 operInfoSendNotification, 190 operInfoAddAttributeChangeNL}; 191 ModelMBeanInfo info = 192 new ModelMBeanInfoSupport(Resource.class.getName(), 193 "Resourcish resource", 194 attrs, null, opers, null, 195 null); 196 mbs.createMBean(RequiredModelMBean.class.getName(), 197 on, 198 new Object[] {info}, 199 new String[] {ModelMBeanInfo.class.getName()}); 200 mbs.invoke(on, "setManagedResource", 201 new Object[] {resource, "objectReference"}, 202 new String[] {"java.lang.Object", "java.lang.String"}); 203 switch (testno) { 204 case 0: 205 /* Check that we can get an attribute of type Object[] */ 206 Object[] objs = (Object[]) mbs.getAttribute(on, "Array"); 207 for (int i = 0; i < objs.length; i++) 208 System.out.println(objs[i]); 209 break; 210 case 1: 211 /* Check that we can get an attribute of type int */ 212 Integer n = (Integer) mbs.getAttribute(on, "Number"); 213 System.out.println(n); 214 break; 215 case 2: 216 /* Check that we can call an operation that returns int */ 217 Integer n1 = 218 (Integer) mbs.invoke(on, "addOne", 219 new Integer[] {new Integer(1233)}, 220 new String[] {"int"}); 221 System.out.println(n1); 222 break; 223 case 3: 224 /* Check that we don't get an exception if you sendNotification 225 without any listeners. */ 226 Notification notif = new Notification("type", "source", 123L); 227 mbs.invoke(on, "sendNotification", new Object[] {notif}, 228 new String[] {"javax.management.Notification"}); 229 System.out.println("Successfully sent notification"); 230 break; 231 case 4: 232 /* Check that we can call addAttributeChangeNotificationListener 233 with null attribute. */ 234 NotificationListener listener = new NotificationListener() { 235 public void handleNotification(Notification notif, 236 Object handback) { 237 System.out.println("Got notif: " + notif + 238 " with handback: " + handback); 239 } 240 }; 241 mbs.invoke(on, "addAttributeChangeNotificationListener", 242 new Object[] {listener, null, "the-handback"}, 243 new String[] { 244 "javax.management.NotificationListener", 245 "java.lang.String", 246 "java.lang.Object", 247 }); 248 mbs.setAttribute(on, new Attribute("Number", new Integer(4321))); 249 System.out.println("Attribute value now: " + 250 mbs.getAttribute(on, "Number")); 251 break; 252 case 5: 253 /* Check that the default caching behaviour is not to cache. */ 254 Object[] firstGot = (Object[]) mbs.getAttribute(on, "Array"); 255 System.out.println("First got: " + Arrays.asList(firstGot)); 256 ModelMBeanInfo mmbi = (ModelMBeanInfo) mbs.getMBeanInfo(on); 257 System.out.println(mmbi.getDescriptor("Array", "attribute")); 258 mbs.invoke(on, "tweakArray", new Object[] {new Object[] {"x"}}, 259 new String[] {Object[].class.getName()}); 260 Object[] secondGot = (Object[]) mbs.getAttribute(on, "Array"); 261 System.out.println("Second got: " + Arrays.asList(secondGot)); 262 if (secondGot.length != 1) 263 throw new Exception("Got value: " + Arrays.asList(secondGot)); 264 break; 265 case 6: 266 /* Check that attributes without getters or setters work. 267 The value is stored in the descriptor. This test includes 268 an explicit currencyTimeLimit attribute. */ 269 mbs.setAttribute(on, new Attribute("Local", "string value")); 270 ModelMBeanInfo mmbi2 = (ModelMBeanInfo) mbs.getMBeanInfo(on); 271 System.out.println(mmbi2.getDescriptor("Local", "attribute")); 272 Object gotback = mbs.getAttribute(on, "Local"); 273 if (!"string value".equals(gotback)) 274 throw new Exception("Got value: " + gotback); 275 break; 276 case 7: 277 /* Check that attributes without getters or setters work. 278 The value is stored in the descriptor. This test does 279 not have an explicit currencyTimeLimit attribute. */ 280 mbs.setAttribute(on, new Attribute("Local2", "thing value")); 281 ModelMBeanInfo mmbi3 = (ModelMBeanInfo) mbs.getMBeanInfo(on); 282 System.out.println(mmbi3.getDescriptor("Local2", "attribute")); 283 Object gotback2 = mbs.getAttribute(on, "Local2"); 284 if (!"thing value".equals(gotback2)) 285 throw new Exception("Got value: " + gotback2); 286 break; 287 default: 288 System.err.println("UNKNOWN TEST NUMBER " + testno); 289 break; 290 } 291 } 292 293 private static final int NTESTS = 8; 294 295 }