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 }