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