1 /* 2 * Copyright (c) 2003, 2021, 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.access.SharedSecrets; 34 import jdk.internal.access.JavaLangAccess; 35 36 /** 37 * Represents an annotation type at run time. Used to type-check annotations 38 * and apply member defaults. 39 * 40 * @author Josh Bloch 41 * @since 1.5 42 */ 43 public class AnnotationType { 44 /** 45 * Member name -> type mapping. Note that primitive types 46 * are represented by the class objects for the corresponding wrapper 47 * types. This matches the return value that must be used for a 48 * dynamic proxy, allowing for a simple isInstance test. 49 */ 50 private final Map<String, Class<?>> memberTypes; 51 52 /** 53 * Member name -> default value mapping. 54 */ 55 private final Map<String, Object> memberDefaults; 56 57 /** 58 * Member name -> Method object mapping. This (and its associated 59 * accessor) are used only to generate AnnotationTypeMismatchExceptions. 60 */ 61 private final Map<String, Method> members; 62 63 /** 64 * The retention policy for this annotation type. 65 */ 66 private final RetentionPolicy retention; 67 68 /** 69 * Whether this annotation type is inherited. 70 */ 71 private final boolean inherited; 72 73 /** 74 * Returns an AnnotationType instance for the specified annotation type. 75 * 76 * @throws IllegalArgumentException if the specified class object 77 * does not represent a valid annotation type 78 */ getInstance( Class<? extends Annotation> annotationClass)79 public static AnnotationType getInstance( 80 Class<? extends Annotation> annotationClass) 81 { 82 JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); 83 AnnotationType result = jla.getAnnotationType(annotationClass); // volatile read 84 if (result == null) { 85 result = new AnnotationType(annotationClass); 86 // try to CAS the AnnotationType: null -> result 87 if (!jla.casAnnotationType(annotationClass, null, result)) { 88 // somebody was quicker -> read it's result 89 result = jla.getAnnotationType(annotationClass); 90 assert result != null; 91 } 92 } 93 94 return result; 95 } 96 97 /** 98 * Sole constructor. 99 * 100 * @param annotationClass the class object for the annotation type 101 * @throws IllegalArgumentException if the specified class object for 102 * does not represent a valid annotation type 103 */ AnnotationType(final Class<? extends Annotation> annotationClass)104 private AnnotationType(final Class<? extends Annotation> annotationClass) { 105 if (!annotationClass.isAnnotation()) 106 throw new IllegalArgumentException("Not an annotation type"); 107 108 @SuppressWarnings("removal") 109 Method[] methods = 110 AccessController.doPrivileged(new PrivilegedAction<>() { 111 public Method[] run() { 112 // Initialize memberTypes and defaultValues 113 return annotationClass.getDeclaredMethods(); 114 } 115 }); 116 117 memberTypes = new HashMap<>(methods.length+1, 1.0f); 118 memberDefaults = new HashMap<>(0); 119 members = new HashMap<>(methods.length+1, 1.0f); 120 121 for (Method method : methods) { 122 if (Modifier.isPublic(method.getModifiers()) && 123 Modifier.isAbstract(method.getModifiers()) && 124 !method.isSynthetic()) { 125 if (method.getParameterCount() != 0) { 126 throw new IllegalArgumentException(method + " has params"); 127 } 128 String name = method.getName(); 129 Class<?> type = method.getReturnType(); 130 memberTypes.put(name, invocationHandlerReturnType(type)); 131 members.put(name, method); 132 133 Object defaultValue = method.getDefaultValue(); 134 if (defaultValue != null) { 135 memberDefaults.put(name, defaultValue); 136 } 137 } 138 } 139 140 // Initialize retention, & inherited fields. Special treatment 141 // of the corresponding annotation types breaks infinite recursion. 142 if (annotationClass != Retention.class && 143 annotationClass != Inherited.class) { 144 JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); 145 Map<Class<? extends Annotation>, Annotation> metaAnnotations = 146 AnnotationParser.parseSelectAnnotations( 147 jla.getRawClassAnnotations(annotationClass), 148 jla.getConstantPool(annotationClass), 149 annotationClass, 150 Retention.class, Inherited.class 151 ); 152 Retention ret = (Retention) metaAnnotations.get(Retention.class); 153 retention = (ret == null ? RetentionPolicy.CLASS : ret.value()); 154 inherited = metaAnnotations.containsKey(Inherited.class); 155 } 156 else { 157 retention = RetentionPolicy.RUNTIME; 158 inherited = false; 159 } 160 } 161 162 /** 163 * Returns the type that must be returned by the invocation handler 164 * of a dynamic proxy in order to have the dynamic proxy return 165 * the specified type (which is assumed to be a legal member type 166 * for an annotation). 167 */ invocationHandlerReturnType(Class<?> type)168 public static Class<?> invocationHandlerReturnType(Class<?> type) { 169 // Translate primitives to wrappers 170 if (type == byte.class) 171 return Byte.class; 172 if (type == char.class) 173 return Character.class; 174 if (type == double.class) 175 return Double.class; 176 if (type == float.class) 177 return Float.class; 178 if (type == int.class) 179 return Integer.class; 180 if (type == long.class) 181 return Long.class; 182 if (type == short.class) 183 return Short.class; 184 if (type == boolean.class) 185 return Boolean.class; 186 187 // Otherwise, just return declared type 188 return type; 189 } 190 191 /** 192 * Returns member types for this annotation type 193 * (member name {@literal ->} type mapping). 194 */ memberTypes()195 public Map<String, Class<?>> memberTypes() { 196 return memberTypes; 197 } 198 199 /** 200 * Returns members of this annotation type 201 * (member name {@literal ->} associated Method object mapping). 202 */ members()203 public Map<String, Method> members() { 204 return members; 205 } 206 207 /** 208 * Returns the default values for this annotation type 209 * (Member name {@literal ->} default value mapping). 210 */ memberDefaults()211 public Map<String, Object> memberDefaults() { 212 return memberDefaults; 213 } 214 215 /** 216 * Returns the retention policy for this annotation type. 217 */ retention()218 public RetentionPolicy retention() { 219 return retention; 220 } 221 222 /** 223 * Returns true if this annotation type is inherited. 224 */ isInherited()225 public boolean isInherited() { 226 return inherited; 227 } 228 229 /** 230 * For debugging. 231 */ toString()232 public String toString() { 233 return "Annotation Type:\n" + 234 " Member types: " + memberTypes + "\n" + 235 " Member defaults: " + memberDefaults + "\n" + 236 " Retention policy: " + retention + "\n" + 237 " Inherited: " + inherited; 238 } 239 } 240