1 /*
   2  * Copyright (c) 2013, 2015, 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.ArrayList;
  31 import java.util.Arrays;
  32 import java.util.List;
  33 import java.util.Map;
  34 
  35 import static sun.reflect.annotation.TypeAnnotation.*;
  36 
  37 public final class AnnotatedTypeFactory {
  38     /**
  39      * Create an AnnotatedType.
  40      *
  41      * @param type the type this AnnotatedType corresponds to
  42      * @param currentLoc the location this AnnotatedType corresponds to
  43      * @param actualTypeAnnos the type annotations this AnnotatedType has
  44      * @param allOnSameTarget all type annotation on the same TypeAnnotationTarget
  45      *                          as the AnnotatedType being built
  46      * @param decl the declaration having the type use this AnnotatedType
  47      *                          corresponds to
  48      */
  49     public static AnnotatedType buildAnnotatedType(Type type,
  50             LocationInfo currentLoc,
  51             TypeAnnotation[] actualTypeAnnos,
  52             TypeAnnotation[] allOnSameTarget,
  53             AnnotatedElement decl) {
  54         if (type == null) {
  55             return EMPTY_ANNOTATED_TYPE;
  56         }
  57         if (isArray(type))
  58             return new AnnotatedArrayTypeImpl(type,
  59                     currentLoc,
  60                     actualTypeAnnos,
  61                     allOnSameTarget,
  62                     decl);
  63         if (type instanceof Class) {
  64             return new AnnotatedTypeBaseImpl(type,
  65                     currentLoc,
  66                     actualTypeAnnos,
  67                     allOnSameTarget,
  68                     decl);
  69         } else if (type instanceof TypeVariable) {
  70             return new AnnotatedTypeVariableImpl((TypeVariable)type,
  71                     currentLoc,
  72                     actualTypeAnnos,
  73                     allOnSameTarget,
  74                     decl);
  75         } else if (type instanceof ParameterizedType) {
  76             return new AnnotatedParameterizedTypeImpl((ParameterizedType)type,
  77                     currentLoc,
  78                     actualTypeAnnos,
  79                     allOnSameTarget,
  80                     decl);
  81         } else if (type instanceof WildcardType) {
  82             return new AnnotatedWildcardTypeImpl((WildcardType) type,
  83                     currentLoc,
  84                     actualTypeAnnos,
  85                     allOnSameTarget,
  86                     decl);
  87         }
  88         throw new AssertionError("Unknown instance of Type: " + type + "\nThis should not happen.");
  89     }
  90 
  91     public static LocationInfo nestingForType(Type type, LocationInfo addTo) {
  92         if (isArray(type))
  93             return addTo;
  94         if (type instanceof Class) {
  95             Class<?> clz = (Class)type;
  96             if (clz.getEnclosingClass() == null)
  97                 return addTo;
  98             if (Modifier.isStatic(clz.getModifiers()))
  99                 return nestingForType(clz.getEnclosingClass(), addTo);
 100             return nestingForType(clz.getEnclosingClass(), addTo.pushInner());
 101         } else if (type instanceof ParameterizedType) {
 102             ParameterizedType t = (ParameterizedType)type;
 103             if (t.getOwnerType() == null)
 104                 return addTo;
 105             return nestingForType(t.getOwnerType(), addTo.pushInner());
 106         }
 107         return addTo;
 108     }
 109 
 110     private static boolean isArray(Type t) {
 111         if (t instanceof Class) {
 112             Class<?> c = (Class)t;
 113             if (c.isArray())
 114                 return true;
 115         } else if (t instanceof GenericArrayType) {
 116             return true;
 117         }
 118         return false;
 119     }
 120 
 121     static final TypeAnnotation[] EMPTY_TYPE_ANNOTATION_ARRAY = new TypeAnnotation[0];
 122     static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION,
 123             EMPTY_TYPE_ANNOTATION_ARRAY, EMPTY_TYPE_ANNOTATION_ARRAY, null);
 124     static final AnnotatedType[] EMPTY_ANNOTATED_TYPE_ARRAY = new AnnotatedType[0];
 125 
 126     private static class AnnotatedTypeBaseImpl implements AnnotatedType {
 127         private final Type type;
 128         private final AnnotatedElement decl;
 129         private final LocationInfo location;
 130         private final TypeAnnotation[] allOnSameTargetTypeAnnotations;
 131         private final Map<Class <? extends Annotation>, Annotation> annotations;
 132 
 133         AnnotatedTypeBaseImpl(Type type, LocationInfo location,
 134                 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
 135                 AnnotatedElement decl) {
 136             this.type = type;
 137             this.decl = decl;
 138             this.location = location;
 139             this.allOnSameTargetTypeAnnotations = allOnSameTargetTypeAnnotations;
 140             this.annotations = TypeAnnotationParser.mapTypeAnnotations(location.filter(actualTypeAnnotations));
 141         }
 142 
 143         // AnnotatedElement
 144         @Override
 145         public final Annotation[] getAnnotations() {
 146             return getDeclaredAnnotations();
 147         }
 148 
 149         @Override
 150         public final <T extends Annotation> T getAnnotation(Class<T> annotation) {
 151             return getDeclaredAnnotation(annotation);
 152         }
 153 
 154         @Override
 155         public final <T extends Annotation> T[] getAnnotationsByType(Class<T> annotation) {
 156             return getDeclaredAnnotationsByType(annotation);
 157         }
 158 
 159         @Override
 160         public final Annotation[] getDeclaredAnnotations() {
 161             return annotations.values().toArray(new Annotation[0]);
 162         }
 163 
 164         @Override
 165         @SuppressWarnings("unchecked")
 166         public final <T extends Annotation> T getDeclaredAnnotation(Class<T> annotation) {
 167             return (T)annotations.get(annotation);
 168         }
 169 
 170         @Override
 171         public final <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotation) {
 172             return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotations, annotation);
 173         }
 174 
 175         // AnnotatedType
 176         @Override
 177         public final Type getType() {
 178             return type;
 179         }
 180 
 181         @Override
 182         public AnnotatedType getAnnotatedOwnerType() {
 183             if (!(type instanceof Class<?>))
 184                 throw new IllegalStateException("Can't compute owner");
 185 
 186             Class<?> inner = (Class<?>)type;
 187             Class<?> owner = inner.getDeclaringClass();
 188             if (owner == null) // top-level, local or anonymous
 189                 return null;
 190             if (inner.isPrimitive() || inner == Void.TYPE)
 191                 return null;
 192 
 193             LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
 194             TypeAnnotation[]all = getTypeAnnotations();
 195             List<TypeAnnotation> l = new ArrayList<>(all.length);
 196 
 197             for (TypeAnnotation t : all)
 198                 if (t.getLocationInfo().isSameLocationInfo(outerLoc))
 199                     l.add(t);
 200 
 201             return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
 202 
 203         }
 204 
 205         // Implementation details
 206         final LocationInfo getLocation() {
 207             return location;
 208         }
 209         final TypeAnnotation[] getTypeAnnotations() {
 210             return allOnSameTargetTypeAnnotations;
 211         }
 212         final AnnotatedElement getDecl() {
 213             return decl;
 214         }
 215     }
 216 
 217     private static final class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType {
 218         AnnotatedArrayTypeImpl(Type type, LocationInfo location,
 219                 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
 220                 AnnotatedElement decl) {
 221             super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
 222         }
 223 
 224         @Override
 225         public AnnotatedType getAnnotatedGenericComponentType() {
 226             Type t = getComponentType();
 227             return AnnotatedTypeFactory.buildAnnotatedType(t,
 228                     nestingForType(t, getLocation().pushArray()),
 229                     getTypeAnnotations(),
 230                     getTypeAnnotations(),
 231                     getDecl());
 232         }
 233 
 234         @Override
 235         public AnnotatedType getAnnotatedOwnerType() {
 236             return null;
 237         }
 238 
 239         private Type getComponentType() {
 240             Type t = getType();
 241             if (t instanceof Class) {
 242                 Class<?> c = (Class)t;
 243                 return c.getComponentType();
 244             }
 245             return ((GenericArrayType)t).getGenericComponentType();
 246         }
 247     }
 248 
 249     private static final class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable {
 250         AnnotatedTypeVariableImpl(TypeVariable<?> type, LocationInfo location,
 251                 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
 252                 AnnotatedElement decl) {
 253             super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
 254         }
 255 
 256         @Override
 257         public AnnotatedType[] getAnnotatedBounds() {
 258             return getTypeVariable().getAnnotatedBounds();
 259         }
 260 
 261         @Override
 262         public AnnotatedType getAnnotatedOwnerType() {
 263             return null;
 264         }
 265 
 266         private TypeVariable<?> getTypeVariable() {
 267             return (TypeVariable)getType();
 268         }
 269     }
 270 
 271     private static final class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl
 272             implements AnnotatedParameterizedType {
 273         AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location,
 274                 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
 275                 AnnotatedElement decl) {
 276             super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
 277         }
 278 
 279         @Override
 280         public AnnotatedType[] getAnnotatedActualTypeArguments() {
 281             Type[] arguments = getParameterizedType().getActualTypeArguments();
 282             AnnotatedType[] res = new AnnotatedType[arguments.length];
 283             Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
 284             int initialCapacity = getTypeAnnotations().length;
 285             for (int i = 0; i < res.length; i++) {
 286                 List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
 287                 LocationInfo newLoc = nestingForType(arguments[i], getLocation().pushTypeArg((byte)i));
 288                 for (TypeAnnotation t : getTypeAnnotations())
 289                     if (t.getLocationInfo().isSameLocationInfo(newLoc))
 290                         l.add(t);
 291                 res[i] = buildAnnotatedType(arguments[i],
 292                         newLoc,
 293                         l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
 294                         getTypeAnnotations(),
 295                         getDecl());
 296             }
 297             return res;
 298         }
 299 
 300         @Override
 301         public AnnotatedType getAnnotatedOwnerType() {
 302             Type owner = getParameterizedType().getOwnerType();
 303             if (owner == null)
 304                 return null;
 305             LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
 306             TypeAnnotation[]all = getTypeAnnotations();
 307             List<TypeAnnotation> l = new ArrayList<>(all.length);
 308 
 309             for (TypeAnnotation t : all)
 310                 if (t.getLocationInfo().isSameLocationInfo(outerLoc))
 311                     l.add(t);
 312 
 313             return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
 314         }
 315 
 316         private ParameterizedType getParameterizedType() {
 317             return (ParameterizedType)getType();
 318         }
 319     }
 320 
 321     private static final class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType {
 322         private final boolean hasUpperBounds;
 323         AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location,
 324                 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
 325                 AnnotatedElement decl) {
 326             super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
 327             hasUpperBounds = (type.getLowerBounds().length == 0);
 328         }
 329 
 330         @Override
 331         public AnnotatedType[] getAnnotatedUpperBounds() {
 332             if (!hasUpperBounds()) {
 333                 return new AnnotatedType[] { buildAnnotatedType(Object.class,
 334                         LocationInfo.BASE_LOCATION,
 335                         EMPTY_TYPE_ANNOTATION_ARRAY,
 336                         EMPTY_TYPE_ANNOTATION_ARRAY,
 337                         null)
 338                 };
 339             }
 340             return getAnnotatedBounds(getWildcardType().getUpperBounds());
 341         }
 342 
 343         @Override
 344         public AnnotatedType[] getAnnotatedLowerBounds() {
 345             if (hasUpperBounds)
 346                 return new AnnotatedType[0];
 347             return getAnnotatedBounds(getWildcardType().getLowerBounds());
 348         }
 349 
 350         @Override
 351         public AnnotatedType getAnnotatedOwnerType() {
 352             return null;
 353         }
 354 
 355         private AnnotatedType[] getAnnotatedBounds(Type[] bounds) {
 356             AnnotatedType[] res = new AnnotatedType[bounds.length];
 357             Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
 358             int initialCapacity = getTypeAnnotations().length;
 359             for (int i = 0; i < res.length; i++) {
 360                 LocationInfo newLoc = nestingForType(bounds[i], getLocation().pushWildcard());
 361                 List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
 362                 for (TypeAnnotation t : getTypeAnnotations())
 363                     if (t.getLocationInfo().isSameLocationInfo(newLoc))
 364                         l.add(t);
 365                 res[i] = buildAnnotatedType(bounds[i],
 366                         newLoc,
 367                         l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
 368                         getTypeAnnotations(),
 369                         getDecl());
 370             }
 371             return res;
 372         }
 373 
 374         private WildcardType getWildcardType() {
 375             return (WildcardType)getType();
 376         }
 377 
 378         private boolean hasUpperBounds() {
 379             return hasUpperBounds;
 380         }
 381     }
 382 }