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  * @modules java.management
  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 }