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 6204469
  27  * @summary Check that descriptors have not broken serial interop.
  28  * @author Eamonn McManus
  29  * @modules java.management
  30  * @run clean MBeanInfoInteropTest SerializedInfo
  31  * @run build MBeanInfoInteropTest SerializedInfo
  32  * @run main MBeanInfoInteropTest SerializedInfo
  33  */
  34 
  35 /*
  36  * When run with just a classname argument ("SerializedInfo" above),
  37  * this reads the serialized objects from that class.
  38  * When run with the argument "generate" and a classname, say "SerializedInfo",
  39  * this creates the class SerializedInfo.java.  The idea is to do that on JDK 5.0
  40  * then run this test on the latest JDK, or vice versa.  The
  41  * copy included in this source directory was generated on JDK 5.0
  42  * so that we continue to check forward interop (serialize on JDK 5,
  43  * deserialize on JDK 6).  There is no easy way to automate backward
  44  * interop checking.
  45  */
  46 
  47 import java.io.ByteArrayInputStream;
  48 import java.io.ByteArrayOutputStream;
  49 import java.io.ObjectInputStream;
  50 import java.io.ObjectOutputStream;
  51 import java.io.PrintWriter;
  52 import java.io.Serializable;
  53 import java.lang.reflect.Field;
  54 import java.lang.reflect.Modifier;
  55 import javax.management.Descriptor;
  56 import javax.management.MBeanAttributeInfo;
  57 import javax.management.MBeanConstructorInfo;
  58 import javax.management.MBeanInfo;
  59 import javax.management.MBeanNotificationInfo;
  60 import static javax.management.MBeanOperationInfo.*;
  61 import static javax.management.openmbean.SimpleType.INTEGER;
  62 import javax.management.MBeanOperationInfo;
  63 import javax.management.MBeanParameterInfo;
  64 import javax.management.modelmbean.DescriptorSupport;
  65 import javax.management.modelmbean.ModelMBeanAttributeInfo;
  66 import javax.management.modelmbean.ModelMBeanConstructorInfo;
  67 import javax.management.modelmbean.ModelMBeanInfoSupport;
  68 import javax.management.modelmbean.ModelMBeanNotificationInfo;
  69 import javax.management.modelmbean.ModelMBeanOperationInfo;
  70 import javax.management.openmbean.OpenMBeanAttributeInfo;
  71 import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
  72 import javax.management.openmbean.OpenMBeanConstructorInfo;
  73 import javax.management.openmbean.OpenMBeanConstructorInfoSupport;
  74 import javax.management.openmbean.OpenMBeanInfoSupport;
  75 import javax.management.openmbean.OpenMBeanOperationInfo;
  76 import javax.management.openmbean.OpenMBeanOperationInfoSupport;
  77 import javax.management.openmbean.OpenMBeanParameterInfo;
  78 import javax.management.openmbean.OpenMBeanParameterInfoSupport;
  79 
  80 public class MBeanInfoInteropTest {
  81     public static void main(String[] args) throws Exception {
  82         if (args.length == 2 && args[0].equals("generate"))
  83             generate(args[1]);
  84         else if (args.length == 1)
  85             test(args[0]);
  86         else {
  87             final String usage =
  88                 "Usage: MBeanInfoInteropTest [generate] ClassName";
  89             throw new Exception(usage);
  90         }
  91     }
  92 
  93     private static void test(String className) throws Exception {
  94         Class<?> c = Class.forName(className);
  95         Field f = c.getField("BYTES");
  96         byte[] bytes = (byte[]) f.get(null);
  97         ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
  98         ObjectInputStream ois = new ObjectInputStream(bis);
  99         boolean matched = true;
 100         for (Serializable s : objects) {
 101             Object o = ois.readObject();
 102             if (!o.equals(s)) {
 103                 showMismatch(o, s);
 104                 matched = false;
 105             }
 106         }
 107         if (!matched)
 108             throw new Exception("Read objects did not match");
 109         System.out.println("Test passed");
 110     }
 111 
 112     private static void showMismatch(Object read, Serializable expected)
 113     throws Exception {
 114         String name = "<unknown>";
 115         Field[] fs = MBeanInfoInteropTest.class.getDeclaredFields();
 116         for (Field f : fs) {
 117             if (!Modifier.isStatic(f.getModifiers()))
 118                 continue;
 119             Object x = f.get(null);
 120             if (x == expected) {
 121                 name = f.getName();
 122                 break;
 123             }
 124         }
 125         System.out.println("Read object mismatch for field " + name);
 126         System.out.println("...read:     " + read);
 127         System.out.println("...expected: " + expected);
 128     }
 129 
 130     private static void generate(String className) throws Exception {
 131         System.out.println("Generating " + className + ".java");
 132         ByteArrayOutputStream bos = new ByteArrayOutputStream();
 133         ObjectOutputStream oos = new ObjectOutputStream(bos);
 134         for (Serializable s : objects)
 135             oos.writeObject(s);
 136         oos.close();
 137         byte[] bytes = bos.toByteArray();
 138         PrintWriter pw = new PrintWriter(className + ".java");
 139         pw.printf(
 140             "// Generated by: MBeanInfoInteropTest generate %s\n" +
 141             "import java.io.*;\n" +
 142             "public class %s {\n" +
 143             "public static final byte[] BYTES = {\n", className, className);
 144         for (int i = 0; i < bytes.length; i++) {
 145             byte b = bytes[i];
 146             pw.printf("%d,", b);
 147             if (i % 16 == 15)
 148                 pw.printf("\n");
 149         }
 150         pw.printf("\n");
 151         pw.printf(
 152             "};\n" +
 153             "}\n");
 154         pw.close();
 155         System.out.println("...done");
 156     }
 157 
 158     private static MBeanAttributeInfo mbai;
 159     private static MBeanParameterInfo mbpi;
 160     private static MBeanConstructorInfo mbci1, mbci2;
 161     private static MBeanNotificationInfo mbni1, mbni2;
 162     private static MBeanOperationInfo mboi1, mboi2;
 163     private static MBeanInfo mbi1, mbi2;
 164     private static OpenMBeanAttributeInfoSupport ombai1, ombai2, ombai3, ombai4;
 165     private static OpenMBeanParameterInfoSupport ombpi1, ombpi2, ombpi3, ombpi4;
 166     private static OpenMBeanConstructorInfoSupport ombci1, ombci2;
 167     private static OpenMBeanOperationInfoSupport omboi1, omboi2;
 168     private static OpenMBeanInfoSupport ombi1, ombi2;
 169     private static ModelMBeanAttributeInfo mmbai1, mmbai2;
 170     private static ModelMBeanConstructorInfo mmbci1, mmbci2, mmbci3, mmbci4;
 171     private static ModelMBeanOperationInfo mmboi1, mmboi2, mmboi3, mmboi4;
 172     private static ModelMBeanNotificationInfo mmbni1, mmbni2, mmbni3, mmbni4;
 173     private static ModelMBeanInfoSupport mmbi1, mmbi2, mmbi3, mmbi4;
 174     private static Serializable[] objects;
 175     static {
 176         try {
 177             init();
 178         } catch (Exception e) {
 179             throw new IllegalArgumentException("unexpected", e);
 180         }
 181     }
 182     private static void init() throws Exception {
 183         mbai =
 184             new MBeanAttributeInfo("name", "type", "descr", true, false, false);
 185         mbpi =
 186             new MBeanParameterInfo("name", "type", "descr");
 187         MBeanParameterInfo[] params = new MBeanParameterInfo[] {mbpi};
 188         mbci1 =
 189             new MBeanConstructorInfo("name", "descr", null);
 190         mbci2 =
 191             new MBeanConstructorInfo("name", "descr", params);
 192         mbni1 =
 193             new MBeanNotificationInfo(null, "name", "descr");
 194         mbni2 =
 195             new MBeanNotificationInfo(new String[] {"type"}, "name", "descr");
 196         mboi1 =
 197             new MBeanOperationInfo("name", "descr", null, "type", ACTION);
 198         mboi2 =
 199             new MBeanOperationInfo("name", "descr", params, "type", INFO);
 200         mbi1 =
 201             new MBeanInfo("class", "descr", null, null, null, null);
 202         mbi2 =
 203             new MBeanInfo(
 204                 "class", "descr",
 205                 new MBeanAttributeInfo[] {mbai},
 206                 new MBeanConstructorInfo[] {mbci1, mbci2},
 207                 new MBeanOperationInfo[] {mboi1, mboi2},
 208                 new MBeanNotificationInfo[] {mbni1, mbni2});
 209 
 210         ombai1 =
 211             new OpenMBeanAttributeInfoSupport("name", "descr", INTEGER,
 212                                               true, false, false);
 213         ombai2 =
 214             new OpenMBeanAttributeInfoSupport("name", "descr", INTEGER,
 215                                               true, false, false, 5);
 216         ombai3 =
 217             new OpenMBeanAttributeInfoSupport("name", "descr", INTEGER,
 218                                               true, false, false, 5, 1, 6);
 219         ombai4 =
 220             new OpenMBeanAttributeInfoSupport("name", "descr", INTEGER,
 221                                               true, false, false, 5,
 222                                               new Integer[] {2, 3, 5, 7});
 223         ombpi1 =
 224             new OpenMBeanParameterInfoSupport("name1", "descr", INTEGER);
 225         ombpi2 =
 226             new OpenMBeanParameterInfoSupport("name2", "descr", INTEGER, 5);
 227         ombpi3 =
 228             new OpenMBeanParameterInfoSupport("name3", "descr", INTEGER, 5, 1, 6);
 229         ombpi4 =
 230             new OpenMBeanParameterInfoSupport("name4", "descr", INTEGER, 5,
 231                                               new Integer[] {2, 3, 5, 7});
 232         OpenMBeanParameterInfo[] oparams = {ombpi1, ombpi2, ombpi3, ombpi4};
 233         ombci1 =
 234             new OpenMBeanConstructorInfoSupport("name", "descr", null);
 235         ombci2 =
 236             new OpenMBeanConstructorInfoSupport("name", "descr", oparams);
 237         omboi1 =
 238             new OpenMBeanOperationInfoSupport("name", "descr", null,
 239                                               INTEGER, ACTION);
 240         omboi2 =
 241             new OpenMBeanOperationInfoSupport("name", "descr", oparams,
 242                                               INTEGER, ACTION);
 243         ombi1 =
 244             new OpenMBeanInfoSupport("class", "descr", null, null, null, null);
 245         ombi2 =
 246             new OpenMBeanInfoSupport(
 247                 "class", "descr",
 248                 new OpenMBeanAttributeInfo[] {ombai1, ombai2, ombai3, ombai4},
 249                 new OpenMBeanConstructorInfo[] {ombci1, ombci2},
 250                 new OpenMBeanOperationInfo[] {omboi1, omboi2},
 251                 new MBeanNotificationInfo[] {mbni1, mbni2});
 252 
 253         Descriptor attrd = new DescriptorSupport(new String[] {
 254             "name=name", "descriptorType=attribute",
 255         });
 256         mmbai1 =
 257             new ModelMBeanAttributeInfo("name", "type", "descr",
 258                                         true, false, false);
 259         mmbai2 =
 260             new ModelMBeanAttributeInfo("name", "type", "descr",
 261                                         true, false, false, attrd);
 262         Descriptor constrd = new DescriptorSupport(new String[] {
 263             "name=name", "descriptorType=operation", "role=constructor",
 264         });
 265         mmbci1 =
 266             new ModelMBeanConstructorInfo("name", "descr", null);
 267         mmbci2 =
 268             new ModelMBeanConstructorInfo("name", "descr", null, constrd);
 269         mmbci3 =
 270             new ModelMBeanConstructorInfo("name", "descr", params);
 271         mmbci4 =
 272             new ModelMBeanConstructorInfo("name", "descr", params, constrd);
 273         Descriptor operd = new DescriptorSupport(new String[] {
 274             "name=name", "descriptorType=operation",
 275         });
 276         mmboi1 =
 277             new ModelMBeanOperationInfo("name", "descr", null, "type", ACTION);
 278         mmboi2 =
 279             new ModelMBeanOperationInfo("name", "descr", null, "type", ACTION,
 280                                         operd);
 281         mmboi3 =
 282             new ModelMBeanOperationInfo("name", "descr", params, "type", ACTION);
 283         mmboi4 =
 284             new ModelMBeanOperationInfo("name", "descr", params, "type", ACTION,
 285                                         operd);
 286         Descriptor notifd = new DescriptorSupport(new String[] {
 287             "name=name", "descriptorType=notification",
 288         });
 289         mmbni1 =
 290             new ModelMBeanNotificationInfo(null, "name", "descr");
 291         mmbni2 =
 292             new ModelMBeanNotificationInfo(null, "name", "descr", notifd);
 293         mmbni3 =
 294             new ModelMBeanNotificationInfo(new String[] {"type"}, "name", "descr");
 295         mmbni4 =
 296             new ModelMBeanNotificationInfo(new String[] {"type"}, "name",
 297                                            "descr", notifd);
 298         Descriptor mbeand = new DescriptorSupport(new String[] {
 299             "name=name", "descriptorType=mbean",
 300         });
 301         mmbi1 =
 302             new ModelMBeanInfoSupport("class", "descr", null, null, null, null);
 303         mmbi2 =
 304             new ModelMBeanInfoSupport("class", "descr", null, null, null, null,
 305                                       mbeand);
 306         mmbi3 =
 307             new ModelMBeanInfoSupport(
 308                 "class", "descr",
 309                 new ModelMBeanAttributeInfo[] {mmbai1, mmbai2},
 310                 new ModelMBeanConstructorInfo[] {mmbci1, mmbci2, mmbci3, mmbci4},
 311                 new ModelMBeanOperationInfo[] {mmboi1, mmboi2, mmboi3, mmboi4},
 312                 new ModelMBeanNotificationInfo[] {mmbni1, mmbni2, mmbni3, mmbni4});
 313         mmbi4 =
 314             new ModelMBeanInfoSupport(
 315                 "class", "descr",
 316                 new ModelMBeanAttributeInfo[] {mmbai1, mmbai2},
 317                 new ModelMBeanConstructorInfo[] {mmbci1, mmbci2, mmbci3, mmbci4},
 318                 new ModelMBeanOperationInfo[] {mmboi1, mmboi2, mmboi3, mmboi4},
 319                 new ModelMBeanNotificationInfo[] {mmbni1, mmbni2, mmbni3, mmbni4},
 320                 mbeand);
 321 
 322         objects = new Serializable[] {
 323             mbai, mbpi, mbci1, mbci2, mbni1, mbni2, mboi1, mboi2, mbi1, mbi2,
 324 
 325             ombai1, ombai2, ombai3, ombai4,
 326             ombpi1, ombpi2, ombpi3, ombpi4,
 327             ombci1, ombci2,
 328             omboi1, omboi2,
 329             ombi1, ombi2,
 330 
 331             mmbai1, mmbai2,
 332             mmbci1, mmbci2, mmbci3, mmbci4,
 333             mmboi1, mmboi2, mmboi3, mmboi4,
 334             mmbni1, mmbni2, mmbni3, mmbni4,
 335         };
 336     }
 337 }