1 /*
   2  * Copyright (c) 2003, 2013, 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.generics.reflectiveObjects;
  27 
  28 import java.lang.annotation.*;
  29 import java.lang.reflect.AnnotatedType;
  30 import java.lang.reflect.Array;
  31 import java.lang.reflect.Constructor;
  32 import java.lang.reflect.GenericDeclaration;
  33 import java.lang.reflect.Member;
  34 import java.lang.reflect.Method;
  35 import java.lang.reflect.Type;
  36 import java.lang.reflect.TypeVariable;
  37 import java.util.LinkedHashMap;
  38 import java.util.Map;
  39 import java.util.Objects;
  40 import sun.reflect.annotation.AnnotationSupport;
  41 import sun.reflect.annotation.TypeAnnotationParser;
  42 import sun.reflect.annotation.AnnotationType;
  43 import sun.reflect.generics.factory.GenericsFactory;
  44 import sun.reflect.generics.tree.FieldTypeSignature;
  45 import sun.reflect.generics.visitor.Reifier;
  46 import sun.reflect.misc.ReflectUtil;
  47 
  48 /**
  49  * Implementation of {@code java.lang.reflect.TypeVariable} interface
  50  * for core reflection.
  51  */
  52 public class TypeVariableImpl<D extends GenericDeclaration>
  53     extends LazyReflectiveObjectGenerator implements TypeVariable<D> {
  54     private final D genericDeclaration;
  55     private final String name;
  56 
  57     /**
  58      * The upper bounds.  Lazily converted from FieldTypeSignature[] to Type[].
  59      * We are required to evaluate the bounds lazily, so we store them as ASTs
  60      * until we are first asked for them.  This also neatly solves the problem
  61      * with F-bounds - you can't reify them before the formal is defined.
  62      */
  63     private volatile Object[] bounds;
  64 
  65     // constructor is private to enforce access through static factory
  66     private TypeVariableImpl(D decl, String n, FieldTypeSignature[] bs,
  67                              GenericsFactory f) {
  68         super(f);
  69         genericDeclaration = decl;
  70         name = n;
  71         bounds = bs;
  72     }
  73 
  74     /**
  75      * Factory method.
  76      * @param decl - the reflective object that declared the type variable
  77      * that this method should create
  78      * @param name - the name of the type variable to be returned
  79      * @param bs - an array of ASTs representing the bounds for the type
  80      * variable to be created
  81      * @param f - a factory that can be used to manufacture reflective
  82      * objects that represent the bounds of this type variable
  83      * @return A type variable with name, bounds, declaration and factory
  84      * specified
  85      */
  86     public static <T extends GenericDeclaration>
  87                              TypeVariableImpl<T> make(T decl, String name,
  88                                                       FieldTypeSignature[] bs,
  89                                                       GenericsFactory f) {
  90 
  91         if (!((decl instanceof Class) ||
  92                 (decl instanceof Method) ||
  93                 (decl instanceof Constructor))) {
  94             throw new AssertionError("Unexpected kind of GenericDeclaration" +
  95                     decl.getClass().toString());
  96         }
  97         return new TypeVariableImpl<T>(decl, name, bs, f);
  98     }
  99 
 100 
 101     /**
 102      * Returns an array of {@code Type} objects representing the
 103      * upper bound(s) of this type variable.  Note that if no upper bound is
 104      * explicitly declared, the upper bound is {@code Object}.
 105      *
 106      * <p>For each upper bound B:
 107      * <ul>
 108      *  <li>if B is a parameterized type or a type variable, it is created,
 109      *  (see {@link #ParameterizedType} for the details of the creation
 110      *  process for parameterized types).
 111      *  <li>Otherwise, B is resolved.
 112      * </ul>
 113      *
 114      * @throws {@code TypeNotPresentException} if any of the
 115      *     bounds refers to a non-existent type declaration
 116      * @throws {@code MalformedParameterizedTypeException} if any of the
 117      *     bounds refer to a parameterized type that cannot be instantiated
 118      *     for any reason
 119      * @return an array of Types representing the upper bound(s) of this
 120      *     type variable
 121     */
 122     public Type[] getBounds() {
 123         Object[] value = bounds;
 124         if (value instanceof FieldTypeSignature[]) {
 125             value = reifyBounds((FieldTypeSignature[])value);
 126             bounds = value;
 127         }
 128         return (Type[])value.clone();
 129     }
 130 
 131     /**
 132      * Returns the {@code GenericDeclaration} object representing the
 133      * generic declaration that declared this type variable.
 134      *
 135      * @return the generic declaration that declared this type variable.
 136      *
 137      * @since 1.5
 138      */
 139     public D getGenericDeclaration() {
 140         if (genericDeclaration instanceof Class)
 141             ReflectUtil.checkPackageAccess((Class)genericDeclaration);
 142         else if ((genericDeclaration instanceof Method) ||
 143                 (genericDeclaration instanceof Constructor))
 144             ReflectUtil.conservativeCheckMemberAccess((Member)genericDeclaration);
 145         else
 146             throw new AssertionError("Unexpected kind of GenericDeclaration");
 147         return genericDeclaration;
 148     }
 149 
 150 
 151     /**
 152      * Returns the name of this type variable, as it occurs in the source code.
 153      *
 154      * @return the name of this type variable, as it appears in the source code
 155      */
 156     public String getName()   { return name; }
 157 
 158     public String toString() {return getName();}
 159 
 160     @Override
 161     public boolean equals(Object o) {
 162         if (o instanceof TypeVariable &&
 163                 o.getClass() == TypeVariableImpl.class) {
 164             TypeVariable<?> that = (TypeVariable<?>) o;
 165 
 166             GenericDeclaration thatDecl = that.getGenericDeclaration();
 167             String thatName = that.getName();
 168 
 169             return Objects.equals(genericDeclaration, thatDecl) &&
 170                 Objects.equals(name, thatName);
 171 
 172         } else
 173             return false;
 174     }
 175 
 176     @Override
 177     public int hashCode() {
 178         return genericDeclaration.hashCode() ^ name.hashCode();
 179     }
 180 
 181     // Implementations of AnnotatedElement methods.
 182     @SuppressWarnings("unchecked")
 183     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
 184         Objects.requireNonNull(annotationClass);
 185         // T is an Annotation type, the return value of get will be an annotation
 186         return (T)mapAnnotations(getAnnotations()).get(annotationClass);
 187     }
 188 
 189     public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
 190         Objects.requireNonNull(annotationClass);
 191         return getAnnotation(annotationClass);
 192     }
 193 
 194     @Override
 195     public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
 196         Objects.requireNonNull(annotationClass);
 197         return AnnotationSupport.getDirectlyAndIndirectlyPresent(mapAnnotations(getAnnotations()), annotationClass);
 198     }
 199 
 200     @Override
 201     public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
 202         Objects.requireNonNull(annotationClass);
 203         return getAnnotationsByType(annotationClass);
 204     }
 205 
 206     public Annotation[] getAnnotations() {
 207         int myIndex = typeVarIndex();
 208         if (myIndex < 0)
 209             throw new AssertionError("Index must be non-negative.");
 210         return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex);
 211     }
 212 
 213     public Annotation[] getDeclaredAnnotations() {
 214         return getAnnotations();
 215     }
 216 
 217     public AnnotatedType[] getAnnotatedBounds() {
 218         return TypeAnnotationParser.parseAnnotatedBounds(getBounds(),
 219                                                          getGenericDeclaration(),
 220                                                          typeVarIndex());
 221     }
 222 
 223     private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
 224 
 225     // Helpers for annotation methods
 226     private int typeVarIndex() {
 227         TypeVariable<?>[] tVars = getGenericDeclaration().getTypeParameters();
 228         int i = -1;
 229         for (TypeVariable<?> v : tVars) {
 230             i++;
 231             if (equals(v))
 232                 return i;
 233         }
 234         return -1;
 235     }
 236 
 237     private static Map<Class<? extends Annotation>, Annotation> mapAnnotations(Annotation[] annos) {
 238         Map<Class<? extends Annotation>, Annotation> result =
 239             new LinkedHashMap<>();
 240         for (Annotation a : annos) {
 241             Class<? extends Annotation> klass = a.annotationType();
 242             AnnotationType type = AnnotationType.getInstance(klass);
 243             if (type.retention() == RetentionPolicy.RUNTIME)
 244                 if (result.put(klass, a) != null)
 245                     throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a);
 246         }
 247         return result;
 248     }
 249 }