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