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