src/share/classes/sun/reflect/annotation/AnnotationType.java

Print this page




   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 }