1 /*
   2  * Copyright (c) 2005, 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 6337061
  27  * @summary Test that  ModelMBeanInfoSupport.getDescriptors(null) also
  28  *          returns the MBean's descriptor.
  29  * @author Eamonn McManus, Daniel Fuchs
  30  * @modules java.management
  31  * @run clean GetAllDescriptorsTest
  32  * @run build GetAllDescriptorsTest
  33  * @run main/othervm/java.security.policy=policy  GetAllDescriptorsTest
  34  */
  35 
  36 import java.lang.reflect.*;
  37 import java.util.*;
  38 import javax.management.*;
  39 import javax.management.modelmbean.*;
  40 
  41 public class GetAllDescriptorsTest {
  42 
  43     public static class Resource {
  44         public int getNumber() {
  45             return number;
  46         }
  47 
  48         public void setNumber(int n) {
  49             number = n;
  50         }
  51 
  52         public int addOne(int x) {
  53             return x + 1;
  54         }
  55 
  56         public Object[] getArray() {
  57             return (Object[]) array.clone();
  58         }
  59 
  60         // doesn't look like an attribute so not seen by caching logic
  61         public void tweakArray(Object[] array) {
  62             this.array = (Object[]) array.clone();
  63         }
  64 
  65         private int number = 1234;
  66         private Object[] array = {"hello", "world"};
  67     }
  68 
  69     public static void main(String[] args) {
  70         int errorCount = 0;
  71         for (int i = 0; i < NTESTS; i++) {
  72             try {
  73                 System.out.println("Test " + i + ":");
  74                 test(i);
  75             } catch (Throwable e) {
  76                 errorCount++;
  77                 boolean first = true;
  78                 do {
  79                     System.err.println(first ? "Exception:" : "Caused by:");
  80                     first = false;
  81                     e.printStackTrace();
  82                     Throwable nexte;
  83                     nexte = e.getCause();
  84                     if (nexte == null) { // old JMX
  85                         if (e instanceof MBeanException)
  86                             nexte = ((MBeanException) e).getTargetException();
  87                     }
  88                     e = nexte;
  89                 } while (e != null);
  90             }
  91         }
  92         if (errorCount == 0) {
  93             System.out.println("All ModelMBean tests successfuly passed");
  94             System.out.println("Bye! Bye!");
  95             // JTReg doesn't like System.exit(0);
  96             return;
  97         } else {
  98             System.err.println("ERROR: " + errorCount + " tests failed");
  99             System.exit(errorCount);
 100         }
 101 
 102     }
 103 
 104     private static void test(int testno) throws Exception {
 105         // com.sun.jmx.trace.TraceImplementation.init(2);
 106         Resource resource = new Resource();
 107         Class resourceClass = Resource.class;
 108         Class rmmbClass = RequiredModelMBean.class;
 109         Method setManagedResource =
 110             rmmbClass.getMethod("setManagedResource",
 111                                 new Class[] {Object.class,
 112                                              String.class});
 113         Method sendNotification =
 114             rmmbClass.getMethod("sendNotification",
 115                                 new Class[] {Notification.class});
 116         Method addAttributeChangeNL =
 117             rmmbClass.getMethod("addAttributeChangeNotificationListener",
 118                                 new Class[] {NotificationListener.class,
 119                                              String.class,
 120                                              Object.class});
 121         Method getArray = resourceClass.getMethod("getArray", new Class[0]);
 122         Method getNumber = resourceClass.getMethod("getNumber", new Class[0]);
 123         Method setNumber =
 124             resourceClass.getMethod("setNumber", new Class[] {Integer.TYPE});
 125         Method tweakArray =
 126             resourceClass.getMethod("tweakArray",
 127                                     new Class[] {Object[].class});
 128         Method addOne =
 129             resourceClass.getMethod("addOne", new Class[] {Integer.TYPE});
 130         MBeanServer mbs = MBeanServerFactory.newMBeanServer();
 131         ObjectName on = new ObjectName("a:b=c");
 132         Descriptor attrDescr = new DescriptorSupport();
 133         attrDescr.setField("name", "Array");
 134         attrDescr.setField("descriptorType", "attribute");
 135         attrDescr.setField("getMethod", "getArray");
 136         ModelMBeanAttributeInfo attrInfo =
 137             new ModelMBeanAttributeInfo("Array", "array attr", getArray,
 138                                         null, attrDescr);
 139         Descriptor attrDescr2 = new DescriptorSupport();
 140         attrDescr2.setField("name", "Number");
 141         attrDescr2.setField("descriptorType", "attribute");
 142         attrDescr2.setField("getMethod", "getNumber");
 143         attrDescr2.setField("setMethod", "setNumber");
 144         ModelMBeanAttributeInfo attrInfo2 =
 145             new ModelMBeanAttributeInfo("Number", "number attr", getNumber,
 146                                         setNumber, attrDescr2);
 147         Descriptor attrDescr3 = new DescriptorSupport();
 148         attrDescr3.setField("name", "Local");
 149         attrDescr3.setField("descriptorType", "attribute");
 150         attrDescr3.setField("currencyTimeLimit", "" + Integer.MAX_VALUE);
 151         ModelMBeanAttributeInfo attrInfo3 =
 152             new ModelMBeanAttributeInfo("Local", "java.lang.String",
 153                                         "local attr", true, true, false,
 154                                         attrDescr3);
 155         Descriptor attrDescr4 = new DescriptorSupport();
 156         attrDescr4.setField("name", "Local2");
 157         attrDescr4.setField("descriptorType", "attribute");
 158         ModelMBeanAttributeInfo attrInfo4 =
 159             new ModelMBeanAttributeInfo("Local2", "java.lang.String",
 160                                         "local attr 2", true, true, false,
 161                                         attrDescr4);
 162         ModelMBeanAttributeInfo[] attrs =
 163             new ModelMBeanAttributeInfo[] {attrInfo, attrInfo2, attrInfo3,
 164                                            attrInfo4};
 165         ModelMBeanOperationInfo operInfo =
 166             new ModelMBeanOperationInfo("getArray descr", getArray);
 167         ModelMBeanOperationInfo operInfo2 =
 168             new ModelMBeanOperationInfo("getNumber descr", getNumber);
 169         ModelMBeanOperationInfo operInfo3 =
 170             new ModelMBeanOperationInfo("addOne descr", addOne);
 171         ModelMBeanOperationInfo operInfo4 =
 172             new ModelMBeanOperationInfo("setNumber descr", setNumber);
 173         ModelMBeanOperationInfo operInfo5 =
 174             new ModelMBeanOperationInfo("tweakArray descr", tweakArray);
 175         ModelMBeanOperationInfo operInfoSetManagedResource =
 176             new ModelMBeanOperationInfo("setManagedResource descr",
 177                                         setManagedResource);
 178         ModelMBeanOperationInfo operInfoSendNotification =
 179             new ModelMBeanOperationInfo("sendNotification descr",
 180                                         sendNotification);
 181         ModelMBeanOperationInfo operInfoAddAttributeChangeNL =
 182             new ModelMBeanOperationInfo("AddAttributeChangeNL descr",
 183                                         addAttributeChangeNL);
 184         ModelMBeanOperationInfo[] opers =
 185             new ModelMBeanOperationInfo[] {operInfo, operInfo2, operInfo3,
 186                                            operInfo4, operInfo5,
 187                                            operInfoSetManagedResource,
 188                                            operInfoSendNotification,
 189                                            operInfoAddAttributeChangeNL};
 190         ModelMBeanInfo info =
 191             new ModelMBeanInfoSupport(Resource.class.getName(),
 192                                       "Resourcish resource",
 193                                       attrs, null, opers, null,
 194                                       null);
 195         mbs.createMBean(RequiredModelMBean.class.getName(),
 196                         on,
 197                         new Object[] {info},
 198                         new String[] {ModelMBeanInfo.class.getName()});
 199         mbs.invoke(on, "setManagedResource",
 200                    new Object[] {resource, "objectReference"},
 201                    new String[] {"java.lang.Object", "java.lang.String"});
 202         switch (testno) {
 203         case 0: {
 204             /* Check  getDescriptors("") on original MBeanInfo */
 205             final Descriptor[] desc = info.getDescriptors("");
 206             checkDescriptors(info,desc,"info.getDescriptors(\"\")");
 207             break;
 208         }
 209         case 1: {
 210             /* Check  getDescriptors(null) on original MBeanInfo */
 211             final Descriptor[] desc = info.getDescriptors(null);
 212             checkDescriptors(info,desc,"info.getDescriptors(null)");
 213             break;
 214         }
 215         case 2: {
 216             /* Check  getDescriptors("") on retrieved MBeanInfo */
 217             final MBeanInfo mbi = mbs.getMBeanInfo(on);
 218             final ModelMBeanInfo model = (ModelMBeanInfo)mbi;
 219             final Descriptor[] desc = model.getDescriptors("");
 220             checkDescriptors(info,desc,"model.getDescriptors(\"\")");
 221             break;
 222         }
 223         case 3: {
 224             /* Check  getDescriptors(null) on retrieved MBeanInfo */
 225             final MBeanInfo mbi = mbs.getMBeanInfo(on);
 226             final ModelMBeanInfo model = (ModelMBeanInfo)mbi;
 227             final Descriptor[] desc = model.getDescriptors(null);
 228             checkDescriptors(info,desc,"model.getDescriptors(null)");
 229             break;
 230         }
 231         default:
 232             System.err.println("UNKNOWN TEST NUMBER " + testno);
 233             break;
 234         }
 235     }
 236 
 237     /* Removes descriptor from the list and returns it. Returns {@code null}
 238        if descriptor is not found */
 239     private static Descriptor remove(ArrayList<Descriptor> list,
 240             Descriptor item) {
 241         if (list.remove(item)) return item;
 242         else return null;
 243     }
 244 
 245     /* Check that all descriptors have been returned */
 246     private static void checkDescriptors(ModelMBeanInfo modelMBeanInfo,
 247             Descriptor[] descriptors, String string) {
 248         int errCount = 0;
 249         final ArrayList<Descriptor> list =
 250                 new ArrayList<Descriptor>(descriptors.length);
 251         list.addAll(Arrays.asList(descriptors));
 252         System.out.println("Got " + list.size() + " descriptors for "+string);
 253 
 254         // checks that MBean's descriptor is returned.
 255         //
 256         final Descriptor mbd = ((MBeanInfo)modelMBeanInfo).getDescriptor();
 257         if (!mbd.equals(remove(list,mbd))) {
 258             System.err.println("modelMBeanInfo.getDescriptor(): not found");
 259             errCount++;
 260         }
 261 
 262         // checks that MBean's attributes descriptors are returned.
 263         //
 264         final MBeanAttributeInfo[] attrs = modelMBeanInfo.getAttributes();
 265         for (MBeanAttributeInfo att : attrs) {
 266             final Descriptor ad = att.getDescriptor();
 267             final String name = att.getName();
 268             if (!ad.equals(remove(list,ad))) {
 269                 System.err.println("attInfo.getDescriptor(): not found for "+
 270                         name);
 271                 errCount++;
 272             }
 273         }
 274 
 275         // checks that MBean's operations descriptors are returned.
 276         //
 277         final MBeanOperationInfo[] ops = modelMBeanInfo.getOperations();
 278         for (MBeanOperationInfo op : ops) {
 279             final Descriptor od = op.getDescriptor();
 280             final String name = op.getName();
 281             if (!od.equals(remove(list,od))) {
 282                 System.err.println("opInfo.getDescriptor(): not found for "+
 283                         name);
 284                 errCount++;
 285             }
 286         }
 287 
 288         // checks that MBean's notifications descriptors are returned.
 289         //
 290         final MBeanNotificationInfo[] ntfs = modelMBeanInfo.getNotifications();
 291         for (MBeanNotificationInfo ntf : ntfs) {
 292             final Descriptor nd = ntf.getDescriptor();
 293             final String name = ntf.getName();
 294             if (!nd.equals(remove(list,nd))) {
 295                 System.err.println("notifInfo.getDescriptor(): not found for "+
 296                         name);
 297                 errCount++;
 298             }
 299         }
 300         if (errCount > 0) {
 301             throw new RuntimeException(string+": failed with "+errCount+
 302                     " errors");
 303         } else if (list.size() != 0) {
 304             // Check that there are no additional descriptors
 305             //
 306             throw new RuntimeException(string+
 307                     ": Unexpected remaining descriptors: "+list);
 308         } else System.out.println(string+": PASSED");
 309     }
 310 
 311     private static final int NTESTS = 4;
 312 
 313 }