< prev index next >

src/java.base/share/classes/sun/reflect/annotation/AnnotationSupport.java

Print this page




  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.security.AccessController;
  31 import java.security.PrivilegedAction;
  32 import java.util.ArrayList;
  33 import java.util.Arrays;
  34 import java.util.List;
  35 import java.util.Map;
  36 import java.util.Objects;

  37 
  38 import jdk.internal.misc.SharedSecrets;
  39 import jdk.internal.misc.JavaLangAccess;
  40 import jdk.internal.reflect.ReflectionFactory;
  41 
  42 public final class AnnotationSupport {
  43     private static final JavaLangAccess LANG_ACCESS = SharedSecrets.getJavaLangAccess();
  44 
  45     /**
  46      * Finds and returns all annotations in {@code annotations} matching
  47      * the given {@code annoClass}.
  48      *
  49      * Apart from annotations directly present in {@code annotations} this
  50      * method searches for annotations inside containers i.e. indirectly
  51      * present annotations.
  52      *
  53      * The order of the elements in the array returned depends on the iteration
  54      * order of the provided map. Specifically, the directly present annotations
  55      * come before the indirectly present annotations if and only if the
  56      * directly present annotations come before the indirectly present


 160             Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
 161             Class<?> decl,
 162             Class<A> annoClass) {
 163         Objects.requireNonNull(decl);
 164 
 165         // Search declared
 166         A[] result = getDirectlyAndIndirectlyPresent(declaredAnnotations, annoClass);
 167 
 168         // Search inherited
 169         if(AnnotationType.getInstance(annoClass).isInherited()) {
 170             Class<?> superDecl = decl.getSuperclass();
 171             while (result.length == 0 && superDecl != null) {
 172                 result = getDirectlyAndIndirectlyPresent(LANG_ACCESS.getDeclaredAnnotationMap(superDecl), annoClass);
 173                 superDecl = superDecl.getSuperclass();
 174             }
 175         }
 176 
 177         return result;
 178     }
 179 



























































 180 
 181     /* Reflectively invoke the values-method of the given annotation
 182      * (container), cast it to an array of annotations and return the result.
 183      */
 184     private static <A extends Annotation> A[] getValueArray(Annotation container) {
 185         try {
 186             // According to JLS the container must have an array-valued value
 187             // method. Get the AnnotationType, get the "value" method and invoke
 188             // it to get the content.
 189 
 190             Class<? extends Annotation> containerClass = container.annotationType();
 191             AnnotationType annoType = AnnotationType.getInstance(containerClass);
 192             if (annoType == null)
 193                 throw invalidContainerException(container, null);
 194             Method m = annoType.members().get("value");
 195             if (m == null)
 196                 throw invalidContainerException(container, null);
 197 
 198             if (Proxy.isProxyClass(container.getClass())) {
 199                 // Invoke by invocation handler




  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.security.AccessController;
  31 import java.security.PrivilegedAction;
  32 import java.util.ArrayList;
  33 import java.util.Arrays;
  34 import java.util.List;
  35 import java.util.Map;
  36 import java.util.Objects;
  37 import java.util.function.IntFunction;
  38 
  39 import jdk.internal.misc.SharedSecrets;
  40 import jdk.internal.misc.JavaLangAccess;
  41 import jdk.internal.reflect.ReflectionFactory;
  42 
  43 public final class AnnotationSupport {
  44     private static final JavaLangAccess LANG_ACCESS = SharedSecrets.getJavaLangAccess();
  45 
  46     /**
  47      * Finds and returns all annotations in {@code annotations} matching
  48      * the given {@code annoClass}.
  49      *
  50      * Apart from annotations directly present in {@code annotations} this
  51      * method searches for annotations inside containers i.e. indirectly
  52      * present annotations.
  53      *
  54      * The order of the elements in the array returned depends on the iteration
  55      * order of the provided map. Specifically, the directly present annotations
  56      * come before the indirectly present annotations if and only if the
  57      * directly present annotations come before the indirectly present


 161             Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
 162             Class<?> decl,
 163             Class<A> annoClass) {
 164         Objects.requireNonNull(decl);
 165 
 166         // Search declared
 167         A[] result = getDirectlyAndIndirectlyPresent(declaredAnnotations, annoClass);
 168 
 169         // Search inherited
 170         if(AnnotationType.getInstance(annoClass).isInherited()) {
 171             Class<?> superDecl = decl.getSuperclass();
 172             while (result.length == 0 && superDecl != null) {
 173                 result = getDirectlyAndIndirectlyPresent(LANG_ACCESS.getDeclaredAnnotationMap(superDecl), annoClass);
 174                 superDecl = superDecl.getSuperclass();
 175             }
 176         }
 177 
 178         return result;
 179     }
 180 
 181 
 182     /**
 183      * There are cases where the number of parameters present for a constructor
 184      * in source code and the number of parameters present for that constructor
 185      * in the class file differ. Constructors of enum classes, anonymous classes,
 186      * local classes and member classes may have additional parameters generated
 187      * by compiler. This method fixes an array of "annotations collections"
 188      * by prefixing and/or suffixing it with "empty collection" elements
 189      * for parameters added by compiler.
 190      *
 191      * @param constructor the constructor
 192      * @param annColls an array of annotation collections for parameters in source code
 193      * @param emptyColl an empty collection replicated for compiler generated parameters
 194      * @param arrayFactory a factory for arrays of collections
 195      * @param <A> the type of annotation collection
 196      * @return new array of annotation collections for parameters in class file
 197      */
 198     public static <A> A[] fixConstructorParameterAnnotations(
 199         Constructor<?> constructor, A[] annColls, A emptyColl, IntFunction<A[]> arrayFactory)
 200     {
 201         int prefixLength = 0;
 202         boolean mayHaveSuffix = false;
 203         Class<?> declaringClass = constructor.getDeclaringClass();
 204         if (declaringClass.isEnum() ||
 205             (declaringClass.isAnonymousClass() && declaringClass.getSuperclass().isEnum())) {
 206             // enum class or enum constant anonymous subclass
 207             prefixLength = 2;
 208             mayHaveSuffix = true;
 209         } else if (declaringClass.isLocalClass() || declaringClass.isAnonymousClass()) {
 210             // local or anonymous class
 211             if (!Modifier.isStatic(declaringClass.getModifiers())) {
 212                 prefixLength = 1;
 213             }
 214             mayHaveSuffix = true;
 215         } else if (declaringClass.isMemberClass()) {
 216             // member class
 217             if (!Modifier.isStatic(declaringClass.getModifiers())) {
 218                 prefixLength = 1;
 219             }
 220         }
 221         // compute total length of array of arrays
 222         int len = annColls.length + prefixLength;
 223         if (len < constructor.getParameterCount() && mayHaveSuffix) {
 224             len = constructor.getParameterCount();
 225         }
 226         // prepend empty annotations prefix and/or append suffix if needed
 227         if (len > annColls.length) {
 228             A[] newAnnColls = arrayFactory.apply(len);
 229             Arrays.fill(newAnnColls, 0, prefixLength, emptyColl);
 230             System.arraycopy(annColls, 0,
 231                              newAnnColls, prefixLength,
 232                              annColls.length);
 233             Arrays.fill(newAnnColls,
 234                         prefixLength + annColls.length, newAnnColls.length,
 235                         emptyColl);
 236             annColls = newAnnColls;
 237         }
 238         return annColls;
 239     }
 240 
 241     /* Reflectively invoke the values-method of the given annotation
 242      * (container), cast it to an array of annotations and return the result.
 243      */
 244     private static <A extends Annotation> A[] getValueArray(Annotation container) {
 245         try {
 246             // According to JLS the container must have an array-valued value
 247             // method. Get the AnnotationType, get the "value" method and invoke
 248             // it to get the content.
 249 
 250             Class<? extends Annotation> containerClass = container.annotationType();
 251             AnnotationType annoType = AnnotationType.getInstance(containerClass);
 252             if (annoType == null)
 253                 throw invalidContainerException(container, null);
 254             Method m = annoType.members().get("value");
 255             if (m == null)
 256                 throw invalidContainerException(container, null);
 257 
 258             if (Proxy.isProxyClass(container.getClass())) {
 259                 // Invoke by invocation handler


< prev index next >