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 6221321 6295867 27 * @summary Test that annotations in Standard MBean interfaces 28 * correctly produce Descriptor entries 29 * @author Eamonn McManus 30 * 31 * @run clean AnnotationTest 32 * @run build AnnotationTest 33 * @run main AnnotationTest 34 */ 35 36 import java.lang.annotation.Retention; 37 import java.lang.annotation.RetentionPolicy; 38 import javax.management.Descriptor; 39 import javax.management.DescriptorRead; 40 import javax.management.DescriptorKey; 41 import javax.management.ImmutableDescriptor; 42 import javax.management.MBeanAttributeInfo; 43 import javax.management.MBeanConstructorInfo; 44 import javax.management.MBeanInfo; 45 import javax.management.MBeanOperationInfo; 46 import javax.management.MBeanServer; 47 import javax.management.ObjectName; 48 49 /* 50 This test checks that annotations produce Descriptor entries as 51 specified in javax.management.DescriptorKey. It does two things: 52 53 - An annotation consisting of an int and a String, each with an 54 appropriate @DescriptorKey annotation, is placed on every program 55 element where it can map to a Descriptor, namely: 56 57 . on an MBean interface 58 . on a getter for a read-only attribute 59 . on a setter for a write-only attribute 60 . on the getter but not the setter for a read/write attribute 61 . on the setter but not the getter for a read/write attribute 62 . on both the getter and the setter for a read/write attribute 63 . on an operation 64 . on each parameter of an operation 65 . on a public constructor with no parameters 66 . on a public constructor with a parameter 67 . on the parameter of that public constructor 68 . on all of the above for an MXBean instead of an MBean 69 70 The test checks that in each case the corresponding Descriptor 71 appears in the appropriate place inside the MBean's MBeanInfo. 72 73 - An annotation consisting of enough other types to ensure coverage 74 is placed on a getter. The test checks that the generated 75 MBeanAttributeInfo contains the corresponding Descriptor. The tested 76 types are the following: 77 78 . Class 79 . an enumeration type (java.lang.annotation.RetentionPolicy) 80 . boolean 81 . String[] 82 . Class[] 83 . int[] 84 . an array of enumeration type (RetentionPolicy[]) 85 . boolean[] 86 */ 87 public class AnnotationTest { 88 private static String failed = null; 89 90 @Retention(RetentionPolicy.RUNTIME) 91 public static @interface Pair { 92 @DescriptorKey("x") 93 int x(); 94 @DescriptorKey("y") 95 String y(); 96 } 97 98 @Retention(RetentionPolicy.RUNTIME) 99 public static @interface Full { 100 @DescriptorKey("class") 101 Class classValue(); 102 @DescriptorKey("enum") 103 RetentionPolicy enumValue(); 104 @DescriptorKey("boolean") 105 boolean booleanValue(); 106 @DescriptorKey("stringArray") 107 String[] stringArrayValue(); 108 @DescriptorKey("classArray") 109 Class[] classArrayValue(); 110 @DescriptorKey("intArray") 111 int[] intArrayValue(); 112 @DescriptorKey("enumArray") 113 RetentionPolicy[] enumArrayValue(); 114 @DescriptorKey("booleanArray") 115 boolean[] booleanArrayValue(); 116 } 117 118 /* We use the annotation @Pair(x = 3, y = "foo") everywhere, and this is 119 the Descriptor that it should produce: */ 120 private static Descriptor expectedDescriptor = 121 new ImmutableDescriptor(new String[] {"x", "y"}, 122 new Object[] {3, "foo"}); 123 124 private static Descriptor expectedFullDescriptor = 125 new ImmutableDescriptor(new String[] { 126 "class", "enum", "boolean", "stringArray", 127 "classArray", "intArray", "enumArray", 128 "booleanArray", 129 }, 130 new Object[] { 131 Full.class.getName(), 132 RetentionPolicy.RUNTIME.name(), 133 false, 134 new String[] {"foo", "bar"}, 135 new String[] {Full.class.getName()}, 136 new int[] {1, 2}, 137 new String[] {RetentionPolicy.RUNTIME.name()}, 138 new boolean[] {false, true}, 139 }); 140 141 @Pair(x = 3, y = "foo") 142 public static interface ThingMBean { 143 @Pair(x = 3, y = "foo") 144 @Full(classValue=Full.class, 145 enumValue=RetentionPolicy.RUNTIME, 146 booleanValue=false, 147 stringArrayValue={"foo", "bar"}, 148 classArrayValue={Full.class}, 149 intArrayValue={1, 2}, 150 enumArrayValue={RetentionPolicy.RUNTIME}, 151 booleanArrayValue={false, true}) 152 int getReadOnly(); 153 154 @Pair(x = 3, y = "foo") 155 void setWriteOnly(int x); 156 157 @Pair(x = 3, y = "foo") 158 int getReadWrite1(); 159 void setReadWrite1(int x); 160 161 @Pair(x = 3, y = "foo") 162 int getReadWrite2(); 163 @Pair(x = 3, y = "foo") 164 void setReadWrite2(int x); 165 166 int getReadWrite3(); 167 @Pair(x = 3, y = "foo") 168 void setReadWrite3(int x); 169 170 @Pair(x = 3, y = "foo") 171 int operation(@Pair(x = 3, y = "foo") int p1, 172 @Pair(x = 3, y = "foo") int p2); 173 } 174 175 public static class Thing implements ThingMBean { 176 @Pair(x = 3, y = "foo") 177 public Thing() {} 178 179 @Pair(x = 3, y = "foo") 180 public Thing(@Pair(x = 3, y = "foo") int p1) {} 181 182 public int getReadOnly() {return 0;} 183 184 public void setWriteOnly(int x) {} 185 186 public int getReadWrite1() {return 0;} 187 public void setReadWrite1(int x) {} 188 189 public int getReadWrite2() {return 0;} 190 public void setReadWrite2(int x) {} 191 192 public int getReadWrite3() {return 0;} 193 public void setReadWrite3(int x) {} 194 195 public int operation(int p1, int p2) {return 0;} 196 } 197 198 @Pair(x = 3, y = "foo") 199 public static interface ThingMXBean extends ThingMBean {} 200 201 public static class ThingImpl implements ThingMXBean { 202 @Pair(x = 3, y = "foo") 203 public ThingImpl() {} 204 205 @Pair(x = 3, y = "foo") 206 public ThingImpl(@Pair(x = 3, y = "foo") int p1) {} 207 208 public int getReadOnly() {return 0;} 209 210 public void setWriteOnly(int x) {} 211 212 public int getReadWrite1() {return 0;} 213 public void setReadWrite1(int x) {} 214 215 public int getReadWrite2() {return 0;} 216 public void setReadWrite2(int x) {} 217 218 public int getReadWrite3() {return 0;} 219 public void setReadWrite3(int x) {} 220 221 public int operation(int p1, int p2) {return 0;} 222 } 223 224 public static void main(String[] args) throws Exception { 225 System.out.println("Testing that annotations are correctly " + 226 "reflected in Descriptor entries"); 227 228 MBeanServer mbs = 229 java.lang.management.ManagementFactory.getPlatformMBeanServer(); 230 ObjectName on = new ObjectName("a:b=c"); 231 232 Thing thing = new Thing(); 233 mbs.registerMBean(thing, on); 234 check(mbs, on); 235 mbs.unregisterMBean(on); 236 237 ThingImpl thingImpl = new ThingImpl(); 238 mbs.registerMBean(thingImpl, on); 239 Descriptor d = mbs.getMBeanInfo(on).getDescriptor(); 240 if (!d.getFieldValue("mxbean").equals("true")) { 241 System.out.println("NOT OK: expected MXBean"); 242 failed = "Expected MXBean"; 243 } 244 check(mbs, on); 245 246 if (failed == null) 247 System.out.println("Test passed"); 248 else 249 throw new Exception("TEST FAILED: " + failed); 250 } 251 252 private static void check(MBeanServer mbs, ObjectName on) throws Exception { 253 MBeanInfo mbi = mbs.getMBeanInfo(on); 254 255 // check the MBean itself 256 check(mbi); 257 258 // check attributes 259 MBeanAttributeInfo[] attrs = mbi.getAttributes(); 260 for (MBeanAttributeInfo attr : attrs) { 261 check(attr); 262 if (attr.getName().equals("ReadOnly")) 263 check("@Full", attr.getDescriptor(), expectedFullDescriptor); 264 } 265 266 // check operations 267 MBeanOperationInfo[] ops = mbi.getOperations(); 268 for (MBeanOperationInfo op : ops) { 269 check(op); 270 check(op.getSignature()); 271 } 272 273 MBeanConstructorInfo[] constrs = mbi.getConstructors(); 274 for (MBeanConstructorInfo constr : constrs) { 275 check(constr); 276 check(constr.getSignature()); 277 } 278 } 279 280 private static void check(DescriptorRead x) { 281 check(x, x.getDescriptor(), expectedDescriptor); 282 } 283 284 private static void check(Object x, Descriptor d, Descriptor expect) { 285 String fail = null; 286 try { 287 Descriptor u = ImmutableDescriptor.union(d, expect); 288 if (!u.equals(d)) 289 fail = "should contain " + expect + "; is " + d; 290 } catch (IllegalArgumentException e) { 291 fail = e.getMessage(); 292 } 293 if (fail == null) { 294 System.out.println("OK: " + x); 295 } else { 296 failed = "NOT OK: Incorrect descriptor for: " + x; 297 System.out.println(failed); 298 System.out.println("..." + fail); 299 } 300 } 301 302 private static void check(DescriptorRead[] xx) { 303 for (DescriptorRead x : xx) 304 check(x); 305 } 306 }