2 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
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).
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.
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
26 package sun.reflect.annotation;
28 import java.lang.annotation.*;
29 import java.lang.reflect.*;
31 import java.security.AccessController;
32 import java.security.PrivilegedAction;
35 * Represents an annotation type at run time. Used to type-check annotations
36 * and apply member defaults.
41 public class AnnotationType {
43 * Annotation class -> AnnotationType mapping. This emulates
44 * sun.misc.SharedSecrets.getJavaLangAccess().getAnnotationType() and
45 * sun.misc.SharedSecrets.getJavaLangAccess().setAnnotationType() so
46 * this class can be used with gnu classpath.
48 * @author Mathias Panzenboeck
50 private static Map<Class, AnnotationType> annotationTypes =
51 new HashMap<Class, AnnotationType>();
54 * Member name -> type mapping. Note that primitive types
55 * are represented by the class objects for the corresponding wrapper
56 * types. This matches the return value that must be used for a
57 * dynamic proxy, allowing for a simple isInstance test.
59 private final Map<String, Class> memberTypes = new HashMap<String,Class>();
62 * Member name -> default value mapping.
64 private final Map<String, Object> memberDefaults =
65 new HashMap<String, Object>();
68 * Member name -> Method object mapping. This (and its assoicated
69 * accessor) are used only to generate AnnotationTypeMismatchExceptions.
71 private final Map<String, Method> members = new HashMap<String, Method>();
74 * The retention policy for this annotation type.
76 private RetentionPolicy retention = RetentionPolicy.RUNTIME;;
79 * Whether this annotation type is inherited.
81 private boolean inherited = false;
84 * Returns an AnnotationType instance for the specified annotation type.
86 * @throw IllegalArgumentException if the specified class object for
87 * does not represent a valid annotation type
89 public static synchronized AnnotationType getInstance(
90 Class annotationClass)
93 AnnotationType result = sun.misc.SharedSecrets.getJavaLangAccess().
94 getAnnotationType(annotationClass);
96 // emulating OpenJDKs SharedSecrets in GNU Classpath:
97 AnnotationType result = annotationTypes.get(annotationClass);
99 result = new AnnotationType((Class<?>) annotationClass);
107 * @param annotationClass the class object for the annotation type
108 * @throw IllegalArgumentException if the specified class object for
109 * does not represent a valid annotation type
111 private AnnotationType(final Class<?> annotationClass) {
112 if (!annotationClass.isAnnotation())
113 throw new IllegalArgumentException("Not an annotation type");
116 AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
117 public Method[] run() {
118 // Initialize memberTypes and defaultValues
119 return annotationClass.getDeclaredMethods();
124 for (Method method : methods) {
125 if (method.getParameterTypes().length != 0)
126 throw new IllegalArgumentException(method + " has params");
127 String name = method.getName();
128 Class type = method.getReturnType();
129 memberTypes.put(name, invocationHandlerReturnType(type));
130 members.put(name, method);
132 Object defaultValue = method.getDefaultValue();
133 if (defaultValue != null)
134 memberDefaults.put(name, defaultValue);
136 members.put(name, method);
140 sun.misc.SharedSecrets.getJavaLangAccess().
141 setAnnotationType(annotationClass, this);
143 // emulating OpenJDKs SharedSecrets in GNU Classpath:
144 annotationTypes.put(annotationClass, this);
146 // Initialize retention, & inherited fields. Special treatment
147 // of the corresponding annotation types breaks infinite recursion.
148 if (annotationClass != Retention.class &&
149 annotationClass != Inherited.class) {
150 Retention ret = annotationClass.getAnnotation(Retention.class);
151 retention = (ret == null ? RetentionPolicy.CLASS : ret.value());
152 inherited = annotationClass.isAnnotationPresent(Inherited.class);
157 * Returns the type that must be returned by the invocation handler
158 * of a dynamic proxy in order to have the dynamic proxy return
159 * the specified type (which is assumed to be a legal member type
160 * for an annotation).
162 public static Class invocationHandlerReturnType(Class type) {
163 // Translate primitives to wrappers
164 if (type == byte.class)
166 if (type == char.class)
167 return Character.class;
168 if (type == double.class)
170 if (type == float.class)
172 if (type == int.class)
173 return Integer.class;
174 if (type == long.class)
176 if (type == short.class)
178 if (type == boolean.class)
179 return Boolean.class;
181 // Otherwise, just return declared type
186 * Returns member types for this annotation type
187 * (member name -> type mapping).
189 public Map<String, Class> memberTypes() {
194 * Returns members of this annotation type
195 * (member name -> associated Method object mapping).
197 public Map<String, Method> members() {
202 * Returns the default values for this annotation type
203 * (Member name -> default value mapping).
205 public Map<String, Object> memberDefaults() {
206 return memberDefaults;
210 * Returns the retention policy for this annotation type.
212 public RetentionPolicy retention() {
217 * Returns true if this this annotation type is inherited.
219 public boolean isInherited() {
226 public String toString() {
227 StringBuffer s = new StringBuffer("Annotation Type:" + "\n");
228 s.append(" Member types: " + memberTypes + "\n");
229 s.append(" Member defaults: " + memberDefaults + "\n");
230 s.append(" Retention policy: " + retention + "\n");
231 s.append(" Inherited: " + inherited);