1 /* 2 * Copyright (c) 2003, 2016, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.reflect.annotation; 27 28 import java.lang.annotation.*; 29 import java.lang.reflect.*; 30 import java.util.*; 31 import java.security.AccessController; 32 import java.security.PrivilegedAction; 33 import jdk.internal.misc.SharedSecrets; 34 import jdk.internal.misc.JavaLangAccess; 35 import jdk.internal.reflect.ReflectionFactory; 36 37 /** 38 * Represents an annotation type at run time. Used to type-check annotations 39 * and apply member defaults. 40 * 41 * @author Josh Bloch 42 * @since 1.5 43 */ 44 public class AnnotationType { 45 /** 46 * Member name -> type mapping. Note that primitive types 47 * are represented by the class objects for the corresponding wrapper 48 * types. This matches the return value that must be used for a 49 * dynamic proxy, allowing for a simple isInstance test. 50 */ 51 private final Map<String, Class<?>> memberTypes; 52 53 /** 54 * Member name -> default value mapping. 55 */ 56 private final Map<String, Object> memberDefaults; 57 58 /** 59 * Member name -> Method object mapping. This (and its associated 60 * accessor) are used only to generate AnnotationTypeMismatchExceptions. 61 */ 62 private final Map<String, Method> members; 63 64 /** 65 * The retention policy for this annotation type. 66 */ 67 private final RetentionPolicy retention; 68 69 /** 70 * Whether this annotation type is inherited. 71 */ 72 private final boolean inherited; 73 74 /** 75 * Returns an AnnotationType instance for the specified annotation type. 76 * 77 * @throws AnnotationFormatError if the specified class object 78 * does not represent a valid annotation type 79 */ 80 public static AnnotationType getInstance( 81 Class<? extends Annotation> annotationClass) 82 { 83 JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); 84 AnnotationType result = jla.getAnnotationType(annotationClass); // volatile read 85 if (result == null) { 86 result = new AnnotationType(annotationClass); 87 // try to CAS the AnnotationType: null -> result 88 if (!jla.casAnnotationType(annotationClass, null, result)) { 89 // somebody was quicker -> read it's result 90 result = jla.getAnnotationType(annotationClass); 91 assert result != null; 92 } 93 } 94 95 return result; 96 } 97 98 /** 99 * Sole constructor. 100 * 101 * @param annotationClass the class object for the annotation type 102 * @throws AnnotationFormatError if the specified class object 103 * does not represent a valid annotation type 104 */ 105 private AnnotationType(final Class<? extends Annotation> annotationClass) { 106 Class<?>[] superInterfaces = annotationClass.getInterfaces(); 107 if (!annotationClass.isAnnotation() || 108 superInterfaces.length != 1 || 109 superInterfaces[0] != Annotation.class) { 110 throw new AnnotationFormatError("Not an annotation type."); 111 } 112 113 Method[] methods = 114 AccessController.doPrivileged(new PrivilegedAction<>() { 115 public Method[] run() { 116 return annotationClass.getDeclaredMethods(); 117 } 118 }); 119 120 memberTypes = new HashMap<>(methods.length+1, 1.0f); 121 memberDefaults = new HashMap<>(0); 122 members = new HashMap<>(methods.length+1, 1.0f); 123 124 for (Method method : methods) { 125 // skip synthetic methods as would be created for lambdas for example 126 if (!method.isSynthetic()) { 127 validateAnnotationMethod(method); 128 String name = method.getName(); 129 Class<?> type = method.getReturnType(); 130 memberTypes.put(name, invocationHandlerReturnType(type)); 131 members.put(name, method); 132 Object defaultValue = method.getDefaultValue(); 133 if (defaultValue != null) { 134 memberDefaults.put(name, defaultValue); 135 } 136 } 137 } 138 139 // Initialize retention, & inherited fields. Special treatment 140 // of the corresponding annotation types breaks infinite recursion. 141 if (annotationClass != Retention.class && 142 annotationClass != Inherited.class) { 143 JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); 144 Map<Class<? extends Annotation>, Annotation> metaAnnotations = 145 AnnotationParser.parseSelectAnnotations( 146 jla.getRawClassAnnotations(annotationClass), 147 jla.getConstantPool(annotationClass), 148 annotationClass, 149 Retention.class, Inherited.class 150 ); 151 Retention ret = (Retention) metaAnnotations.get(Retention.class); 152 retention = (ret == null ? RetentionPolicy.CLASS : ret.value()); 153 inherited = metaAnnotations.containsKey(Inherited.class); 154 } 155 else { 156 retention = RetentionPolicy.RUNTIME; 157 inherited = false; 158 } 159 } 160 161 /** 162 * Returns the type that must be returned by the invocation handler 163 * of a dynamic proxy in order to have the dynamic proxy return 164 * the specified type (which is assumed to be a legal member type 165 * for an annotation). 166 */ 167 public static Class<?> invocationHandlerReturnType(Class<?> type) { 168 // Translate primitives to wrappers 169 if (type == byte.class) 170 return Byte.class; 171 if (type == char.class) 172 return Character.class; 173 if (type == double.class) 174 return Double.class; 175 if (type == float.class) 176 return Float.class; 177 if (type == int.class) 178 return Integer.class; 179 if (type == long.class) 180 return Long.class; 181 if (type == short.class) 182 return Short.class; 183 if (type == boolean.class) 184 return Boolean.class; 185 186 // Otherwise, just return declared type 187 return type; 188 } 189 190 /** 191 * Returns member types for this annotation type 192 * (member name {@literal ->} type mapping). 193 */ 194 public Map<String, Class<?>> memberTypes() { 195 return memberTypes; 196 } 197 198 /** 199 * Returns members of this annotation type 200 * (member name {@literal ->} associated Method object mapping). 201 */ 202 public Map<String, Method> members() { 203 return members; 204 } 205 206 private volatile Map<String, Method> accessibleMembers; 207 208 /** 209 * Returns members of this annotation type 210 * (member name {@literal ->} associated Method object mapping) 211 * which are made {@link Method#setAccessible(boolean) accessible}. 212 */ 213 Map<String, Method> accessibleMembers() { 214 Map<String, Method> accMembers = accessibleMembers; 215 if (accMembers == null) { 216 accMembers = AccessController.doPrivileged(new PrivilegedAction<>() { 217 @Override 218 public Map<String, Method> run() { 219 Map<String, Method> ams = new HashMap<>(members.size()+1, 1.0f); 220 ReflectionFactory rf = ReflectionFactory.getReflectionFactory(); 221 for (Method m : members.values()) { 222 Method am = rf.leafCopyMethod(m); 223 am.setAccessible(true); 224 ams.put(am.getName(), am); 225 } 226 return ams; 227 } 228 }); 229 accessibleMembers = accMembers; 230 } 231 return accMembers; 232 } 233 234 /** 235 * Returns the default values for this annotation type 236 * (Member name {@literal ->} default value mapping). 237 */ 238 public Map<String, Object> memberDefaults() { 239 return memberDefaults; 240 } 241 242 /** 243 * Returns the retention policy for this annotation type. 244 */ 245 public RetentionPolicy retention() { 246 return retention; 247 } 248 249 /** 250 * Returns true if this annotation type is inherited. 251 */ 252 public boolean isInherited() { 253 return inherited; 254 } 255 256 /** 257 * For debugging. 258 */ 259 public String toString() { 260 return "Annotation Type:\n" + 261 " Member types: " + memberTypes + "\n" + 262 " Member defaults: " + memberDefaults + "\n" + 263 " Retention policy: " + retention + "\n" + 264 " Inherited: " + inherited; 265 } 266 267 /** 268 * Validates that specified method is structurally appropriate for an 269 * annotation type. As of Java SE 8, annotation types cannot 270 * contain static methods and the declared methods of an 271 * annotation type must take zero arguments and there are 272 * restrictions on the return type. 273 * @throws AnnotationFormatError if specified method is 274 * inappropriate method for an annotation type. 275 */ 276 private static void validateAnnotationMethod(Method method) { 277 /* 278 * Specification citations below are from JLS 279 * 9.6.1. Annotation Type Elements 280 */ 281 boolean valid = true; 282 block: { 283 /* 284 * "By virtue of the AnnotationTypeElementDeclaration 285 * production, a method declaration in an annotation type 286 * declaration cannot have formal parameters, type 287 * parameters, or a throws clause. 288 * 289 * "By virtue of the AnnotationTypeElementModifier 290 * production, a method declaration in an annotation type 291 * declaration cannot be default or static." 292 */ 293 if (method.getModifiers() != (Modifier.PUBLIC | Modifier.ABSTRACT) || 294 method.isDefault() || 295 method.getParameterCount() != 0 || 296 method.getExceptionTypes().length != 0) { 297 valid = false; 298 break block; 299 } 300 301 /* 302 * "It is a compile-time error if the return type of a 303 * method declared in an annotation type is not one of the 304 * following: a primitive type, String, Class, any 305 * parameterized invocation of Class, an enum type 306 * (section 8.9), an annotation type, or an array type 307 * (chapter 10) whose element type is one of the preceding 308 * types." 309 */ 310 Class<?> returnType = method.getReturnType(); 311 if (returnType.isArray()) { 312 returnType = returnType.getComponentType(); 313 if (returnType.isArray()) { // Only single dimensional arrays 314 valid = false; 315 break block; 316 } 317 } 318 319 if (!((returnType.isPrimitive() && returnType != void.class) || 320 returnType == java.lang.String.class || 321 returnType == java.lang.Class.class || 322 returnType.isEnum() || 323 returnType.isAnnotation())) { 324 valid = false; 325 break block; 326 } 327 328 /* 329 * "It is a compile-time error if any method declared in an 330 * annotation type has a signature that is 331 * override-equivalent to that of any public or protected 332 * method declared in class Object or in the interface 333 * java.lang.annotation.Annotation." 334 * 335 * The methods in Object or Annotation meeting the other 336 * criteria (no arguments, contrained return type, etc.) 337 * above are: 338 * 339 * String toString() 340 * int hashCode() 341 * Class<? extends Annotation> annotationType() 342 */ 343 String methodName = method.getName(); 344 if ((methodName.equals("toString") && returnType == java.lang.String.class) || 345 (methodName.equals("hashCode") && returnType == int.class) || 346 (methodName.equals("annotationType") && returnType == java.lang.Class.class)) { 347 valid = false; 348 break block; 349 } 350 } 351 352 if (!valid) { 353 throw new AnnotationFormatError( 354 "Malformed method on an annotation type: " + method); 355 } 356 } 357 }