1 /*
   2  * Copyright (c) 2013, 2018, 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 import java.util.Objects;
  35 import java.util.StringJoiner;
  36 
  37 import static sun.reflect.annotation.TypeAnnotation.*;
  38 
  39 public final class AnnotatedTypeFactory {
  40     /**
  41      * Create an AnnotatedType.
  42      *
  43      * @param type the type this AnnotatedType corresponds to
  44      * @param currentLoc the location this AnnotatedType corresponds to
  45      * @param actualTypeAnnos the type annotations this AnnotatedType has
  46      * @param allOnSameTarget all type annotation on the same TypeAnnotationTarget
  47      *                          as the AnnotatedType being built
  48      * @param decl the declaration having the type use this AnnotatedType
  49      *                          corresponds to
  50      */
  51     public static AnnotatedType buildAnnotatedType(Type type,
  52             LocationInfo currentLoc,
  53             TypeAnnotation[] actualTypeAnnos,
  54             TypeAnnotation[] allOnSameTarget,
  55             AnnotatedElement decl) {
  56         if (type == null) {
  57             return EMPTY_ANNOTATED_TYPE;
  58         }
  59         if (isArray(type))
  60             return new AnnotatedArrayTypeImpl(type,
  61                     currentLoc,
  62                     actualTypeAnnos,
  63                     allOnSameTarget,
  64                     decl);
  65         if (type instanceof Class) {
  66             return new AnnotatedTypeBaseImpl(type,
  67                     currentLoc,
  68                     actualTypeAnnos,
  69                     allOnSameTarget,
  70                     decl);
  71         } else if (type instanceof TypeVariable) {
  72             return new AnnotatedTypeVariableImpl((TypeVariable)type,
  73                     currentLoc,
  74                     actualTypeAnnos,
  75                     allOnSameTarget,
  76                     decl);
  77         } else if (type instanceof ParameterizedType) {
  78             return new AnnotatedParameterizedTypeImpl((ParameterizedType)type,
  79                     currentLoc,
  80                     actualTypeAnnos,
  81                     allOnSameTarget,
  82                     decl);
  83         } else if (type instanceof WildcardType) {
  84             return new AnnotatedWildcardTypeImpl((WildcardType) type,
  85                     currentLoc,
  86                     actualTypeAnnos,
  87                     allOnSameTarget,
  88                     decl);
  89         }
  90         throw new AssertionError("Unknown instance of Type: " + type + "\nThis should not happen.");
  91     }
  92 
  93     public static LocationInfo nestingForType(Type type, LocationInfo addTo) {
  94         if (isArray(type))
  95             return addTo;
  96         if (type instanceof Class) {
  97             Class<?> clz = (Class)type;
  98             if (clz.getEnclosingClass() == null)
  99                 return addTo;
 100             if (Modifier.isStatic(clz.getModifiers()))
 101                 return nestingForType(clz.getEnclosingClass(), addTo);
 102             return nestingForType(clz.getEnclosingClass(), addTo.pushInner());
 103         } else if (type instanceof ParameterizedType) {
 104             ParameterizedType t = (ParameterizedType)type;
 105             if (t.getOwnerType() == null)
 106                 return addTo;
 107             return nestingForType(t.getOwnerType(), addTo.pushInner());
 108         }
 109         return addTo;
 110     }
 111 
 112     private static boolean isArray(Type t) {
 113         if (t instanceof Class) {
 114             Class<?> c = (Class)t;
 115             if (c.isArray())
 116                 return true;
 117         } else if (t instanceof GenericArrayType) {
 118             return true;
 119         }
 120         return false;
 121     }
 122 
 123     static final TypeAnnotation[] EMPTY_TYPE_ANNOTATION_ARRAY = new TypeAnnotation[0];
 124     static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION,
 125             EMPTY_TYPE_ANNOTATION_ARRAY, EMPTY_TYPE_ANNOTATION_ARRAY, null);
 126     static final AnnotatedType[] EMPTY_ANNOTATED_TYPE_ARRAY = new AnnotatedType[0];
 127 
 128     private static class AnnotatedTypeBaseImpl implements AnnotatedType {
 129         private final Type type;
 130         private final AnnotatedElement decl;
 131         private final LocationInfo location;
 132         private final TypeAnnotation[] allOnSameTargetTypeAnnotations;
 133         private final Map<Class <? extends Annotation>, Annotation> annotations;
 134 
 135         AnnotatedTypeBaseImpl(Type type, LocationInfo location,
 136                 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
 137                 AnnotatedElement decl) {
 138             this.type = type;
 139             this.decl = decl;
 140             this.location = location;
 141             this.allOnSameTargetTypeAnnotations = allOnSameTargetTypeAnnotations;
 142             this.annotations = TypeAnnotationParser.mapTypeAnnotations(location.filter(actualTypeAnnotations));
 143         }
 144 
 145         // AnnotatedElement
 146         @Override
 147         public final Annotation[] getAnnotations() {
 148             return getDeclaredAnnotations();
 149         }
 150 
 151         @Override
 152         public final <T extends Annotation> T getAnnotation(Class<T> annotation) {
 153             return getDeclaredAnnotation(annotation);
 154         }
 155 
 156         @Override
 157         public final <T extends Annotation> T[] getAnnotationsByType(Class<T> annotation) {
 158             return getDeclaredAnnotationsByType(annotation);
 159         }
 160 
 161         @Override
 162         public final Annotation[] getDeclaredAnnotations() {
 163             return annotations.values().toArray(new Annotation[0]);
 164         }
 165 
 166         @Override
 167         @SuppressWarnings("unchecked")
 168         public final <T extends Annotation> T getDeclaredAnnotation(Class<T> annotation) {
 169             return (T)annotations.get(annotation);
 170         }
 171 
 172         @Override
 173         public final <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotation) {
 174             return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotations, annotation);
 175         }
 176 
 177         // AnnotatedType
 178         @Override
 179         public final Type getType() {
 180             return type;
 181         }
 182 
 183         @Override
 184         public AnnotatedType getAnnotatedOwnerType() {
 185             if (!(type instanceof Class<?>))
 186                 throw new IllegalStateException("Can't compute owner");
 187 
 188             Class<?> inner = (Class<?>)type;
 189             Class<?> owner = inner.getDeclaringClass();
 190             if (owner == null) // top-level, local or anonymous
 191                 return null;
 192             if (inner.isPrimitive() || inner == Void.TYPE)
 193                 return null;
 194 
 195             LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
 196             TypeAnnotation[]all = getTypeAnnotations();
 197             List<TypeAnnotation> l = new ArrayList<>(all.length);
 198 
 199             for (TypeAnnotation t : all)
 200                 if (t.getLocationInfo().isSameLocationInfo(outerLoc))
 201                     l.add(t);
 202 
 203             return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
 204 
 205         }
 206 
 207         @Override // java.lang.Object
 208         public String toString() {
 209             // Reusable toString implementation, but needs to be
 210             // specialized for quirks of arrays and interior types of
 211             // wildcards, etc.
 212             return annotationsToString(getAnnotations(), false) + 
 213                 ((type instanceof Class) ? type.getTypeName(): type.toString());
 214         }
 215 
 216         protected String annotationsToString(Annotation[] annotations, boolean leadingSpace) {
 217             if (annotations != null && annotations.length > 0) {
 218                 StringJoiner sj = new StringJoiner(" ");
 219                 if (leadingSpace) {
 220                     sj.add(""); // Add a space
 221                 }
 222 
 223                 for (Annotation annotation : annotations) {
 224                     sj.add(annotation.toString());
 225                 }
 226 
 227                 if (!leadingSpace) {
 228                     sj.add("");
 229                 }
 230                 return sj.toString();
 231             } else {
 232                 return "";
 233             }
 234         }
 235 
 236         protected boolean equalsTypeAndAnnotations(AnnotatedType that) {
 237             return getType().equals(that.getType()) &&
 238                 // Treat ordering of annotations as significant
 239                 Arrays.equals(getAnnotations(), that.getAnnotations()) &&
 240                 Objects.equals(getAnnotatedOwnerType(), that.getAnnotatedOwnerType());
 241         }
 242 
 243         int baseHashCode() {
 244             return type.hashCode() ^
 245                 // Acceptable to use Objects.hash rather than
 246                 // Arrays.deepHashCode since the elements of the array
 247                 // are not themselves arrays.
 248                 Objects.hash((Object[])getAnnotations()) ^
 249                 Objects.hash(getAnnotatedOwnerType());
 250         }
 251 
 252         @Override
 253         public boolean equals(Object o) {
 254             if (o instanceof AnnotatedType &&
 255                 !(o instanceof AnnotatedArrayType) &&
 256                 !(o instanceof AnnotatedTypeVariable) &&
 257                 !(o instanceof AnnotatedParameterizedType) &&
 258                 !(o instanceof AnnotatedWildcardType)) {
 259                 AnnotatedType that = (AnnotatedType) o;
 260                 return equalsTypeAndAnnotations(that);
 261             } else {
 262                 return false;
 263             }
 264         }
 265 
 266         @Override
 267         public int hashCode() {
 268             return baseHashCode();
 269         }
 270 
 271         // Implementation details
 272         final LocationInfo getLocation() {
 273             return location;
 274         }
 275         final TypeAnnotation[] getTypeAnnotations() {
 276             return allOnSameTargetTypeAnnotations;
 277         }
 278         final AnnotatedElement getDecl() {
 279             return decl;
 280         }
 281     }
 282 
 283     private static final class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType {
 284         AnnotatedArrayTypeImpl(Type type, LocationInfo location,
 285                 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
 286                 AnnotatedElement decl) {
 287             super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
 288         }
 289 
 290         @Override
 291         public AnnotatedType getAnnotatedGenericComponentType() {
 292             Type t = getComponentType();
 293             return AnnotatedTypeFactory.buildAnnotatedType(t,
 294                     nestingForType(t, getLocation().pushArray()),
 295                     getTypeAnnotations(),
 296                     getTypeAnnotations(),
 297                     getDecl());
 298         }
 299 
 300         @Override
 301         public AnnotatedType getAnnotatedOwnerType() {
 302             return null;
 303         }
 304 
 305         private Type getComponentType() {
 306             Type t = getType();
 307             if (t instanceof Class) {
 308                 Class<?> c = (Class)t;
 309                 return c.getComponentType();
 310             }
 311             return ((GenericArrayType)t).getGenericComponentType();
 312         }
 313 
 314         @Override
 315         public String toString() {
 316             // To annotate the full type of an array, the annotations
 317             // are placed between the type and the brackets. For
 318             // example, to annotate an array of Strings, the syntax used is
 319             //
 320             // String @TypeAnnotation []
 321             //
 322             // and *not*
 323             //
 324             // @TypeAnnotation String[].
 325             //
 326             // The toString output should strive to be reusable in
 327             // source code. Therefore, the general logic of putting
 328             // the annotations before a textual representation of the
 329             // type need to be overridden for arrays.
 330             StringBuilder sb = new StringBuilder();
 331 
 332             AnnotatedType componentType = this;
 333             while (componentType instanceof AnnotatedArrayType) {
 334                 AnnotatedArrayType annotatedArrayType = (AnnotatedArrayType) componentType;
 335                 sb.append(annotationsToString(annotatedArrayType.getAnnotations(), true) + "[]");
 336                 componentType = annotatedArrayType.getAnnotatedGenericComponentType();
 337             }
 338 
 339             sb.insert(0, componentType.toString());
 340             return sb.toString();
 341         }
 342 
 343         @Override
 344         public boolean equals(Object o) {
 345             if (o instanceof AnnotatedArrayType) {
 346                 AnnotatedArrayType that = (AnnotatedArrayType) o;
 347                 return equalsTypeAndAnnotations(that) &&
 348                     Objects.equals(getAnnotatedGenericComponentType(),
 349                                    that.getAnnotatedGenericComponentType());
 350             } else {
 351                 return false;
 352             }
 353         }
 354 
 355         @Override
 356         public int hashCode() {
 357             return baseHashCode() ^ getAnnotatedGenericComponentType().hashCode();
 358         }
 359     }
 360 
 361     private static final class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable {
 362         AnnotatedTypeVariableImpl(TypeVariable<?> type, LocationInfo location,
 363                 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
 364                 AnnotatedElement decl) {
 365             super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
 366         }
 367 
 368         @Override
 369         public AnnotatedType[] getAnnotatedBounds() {
 370             return getTypeVariable().getAnnotatedBounds();
 371         }
 372 
 373         @Override
 374         public AnnotatedType getAnnotatedOwnerType() {
 375             return null;
 376         }
 377 
 378         private TypeVariable<?> getTypeVariable() {
 379             return (TypeVariable)getType();
 380         }
 381 
 382         // For toString, the declaration of a type variable should
 383         // including information about its bounds, etc. However, the
 384         // use of a type variable should not. For that reason, it is
 385         // acceptable for the toString implementation of
 386         // AnnotatedTypeVariableImpl to use the inherited
 387         // implementation from AnnotatedTypeBaseImpl.
 388 
 389         @Override
 390         public boolean equals(Object o) {
 391             if (o instanceof AnnotatedTypeVariable) {
 392                 AnnotatedTypeVariable that = (AnnotatedTypeVariable) o;
 393                 return equalsTypeAndAnnotations(that) &&
 394                     Arrays.equals(getAnnotatedBounds(), that.getAnnotatedBounds());
 395             } else {
 396                 return false;
 397             }
 398         }
 399 
 400         @Override
 401         public int hashCode() {
 402             return baseHashCode() ^
 403                 Objects.hash((Object[])getAnnotatedBounds());
 404         }
 405     }
 406 
 407     private static final class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl
 408             implements AnnotatedParameterizedType {
 409         AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location,
 410                 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
 411                 AnnotatedElement decl) {
 412             super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
 413         }
 414 
 415         @Override
 416         public AnnotatedType[] getAnnotatedActualTypeArguments() {
 417             Type[] arguments = getParameterizedType().getActualTypeArguments();
 418             AnnotatedType[] res = new AnnotatedType[arguments.length];
 419             Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
 420             int initialCapacity = getTypeAnnotations().length;
 421             for (int i = 0; i < res.length; i++) {
 422                 List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
 423                 LocationInfo newLoc = nestingForType(arguments[i], getLocation().pushTypeArg((byte)i));
 424                 for (TypeAnnotation t : getTypeAnnotations())
 425                     if (t.getLocationInfo().isSameLocationInfo(newLoc))
 426                         l.add(t);
 427                 res[i] = buildAnnotatedType(arguments[i],
 428                         newLoc,
 429                         l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
 430                         getTypeAnnotations(),
 431                         getDecl());
 432             }
 433             return res;
 434         }
 435 
 436         @Override
 437         public AnnotatedType getAnnotatedOwnerType() {
 438             Type owner = getParameterizedType().getOwnerType();
 439             if (owner == null)
 440                 return null;
 441             LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
 442             TypeAnnotation[]all = getTypeAnnotations();
 443             List<TypeAnnotation> l = new ArrayList<>(all.length);
 444 
 445             for (TypeAnnotation t : all)
 446                 if (t.getLocationInfo().isSameLocationInfo(outerLoc))
 447                     l.add(t);
 448 
 449             return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
 450         }
 451 
 452         private ParameterizedType getParameterizedType() {
 453             return (ParameterizedType)getType();
 454         }
 455 
 456         @Override
 457         public String toString() {
 458             StringBuilder sb = new StringBuilder();
 459             sb.append(annotationsToString(getAnnotations(), false));
 460 
 461             Type t = getParameterizedType().getRawType();
 462             sb.append(t.getTypeName());
 463 
 464             StringJoiner sj = new StringJoiner(", ", "<", ">");
 465             sj.setEmptyValue("");
 466             for(AnnotatedType typeArg: getAnnotatedActualTypeArguments()) {
 467                 sj.add(typeArg.toString());
 468             }
 469             sb.append(sj.toString());
 470 
 471             return sb.toString();
 472         }
 473 
 474         @Override
 475         public boolean equals(Object o) {
 476             if (o instanceof AnnotatedParameterizedType) {
 477                 AnnotatedParameterizedType that = (AnnotatedParameterizedType) o;
 478                 return equalsTypeAndAnnotations(that) &&
 479                     Arrays.equals(getAnnotatedActualTypeArguments(), that.getAnnotatedActualTypeArguments());
 480             } else {
 481                 return false;
 482             }
 483         }
 484 
 485         @Override
 486         public int hashCode() {
 487             return baseHashCode() ^
 488                 Objects.hash((Object[])getAnnotatedActualTypeArguments());
 489         }
 490     }
 491 
 492     private static final class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType {
 493         private final boolean hasUpperBounds;
 494         AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location,
 495                 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
 496                 AnnotatedElement decl) {
 497             super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
 498             hasUpperBounds = (type.getLowerBounds().length == 0);
 499         }
 500 
 501         @Override
 502         public AnnotatedType[] getAnnotatedUpperBounds() {
 503             if (!hasUpperBounds()) {
 504                 return new AnnotatedType[] { buildAnnotatedType(Object.class,
 505                         LocationInfo.BASE_LOCATION,
 506                         EMPTY_TYPE_ANNOTATION_ARRAY,
 507                         EMPTY_TYPE_ANNOTATION_ARRAY,
 508                         null)
 509                 };
 510             }
 511             return getAnnotatedBounds(getWildcardType().getUpperBounds());
 512         }
 513 
 514         @Override
 515         public AnnotatedType[] getAnnotatedLowerBounds() {
 516             if (hasUpperBounds)
 517                 return new AnnotatedType[0];
 518             return getAnnotatedBounds(getWildcardType().getLowerBounds());
 519         }
 520 
 521         @Override
 522         public AnnotatedType getAnnotatedOwnerType() {
 523             return null;
 524         }
 525 
 526         private AnnotatedType[] getAnnotatedBounds(Type[] bounds) {
 527             AnnotatedType[] res = new AnnotatedType[bounds.length];
 528             Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
 529             int initialCapacity = getTypeAnnotations().length;
 530             for (int i = 0; i < res.length; i++) {
 531                 LocationInfo newLoc = nestingForType(bounds[i], getLocation().pushWildcard());
 532                 List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
 533                 for (TypeAnnotation t : getTypeAnnotations())
 534                     if (t.getLocationInfo().isSameLocationInfo(newLoc))
 535                         l.add(t);
 536                 res[i] = buildAnnotatedType(bounds[i],
 537                         newLoc,
 538                         l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
 539                         getTypeAnnotations(),
 540                         getDecl());
 541             }
 542             return res;
 543         }
 544 
 545         private WildcardType getWildcardType() {
 546             return (WildcardType)getType();
 547         }
 548 
 549         private boolean hasUpperBounds() {
 550             return hasUpperBounds;
 551         }
 552 
 553         @Override
 554         public String toString() {
 555             StringBuilder sb = new StringBuilder();
 556             sb.append(annotationsToString(getAnnotations(), false));
 557             sb.append("?");
 558 
 559             AnnotatedType[] bounds = getAnnotatedLowerBounds();
 560             if (bounds.length > 0) {
 561                 sb.append(" super ");
 562             } else {
 563                 bounds = getAnnotatedUpperBounds();
 564                 if (bounds.length > 0) {
 565                     sb.append(" extends ");
 566                 }
 567                 // With extra work, could check for and elide " extends
 568                 // Object" if Object was not annotated.
 569             }
 570             
 571             StringJoiner sj = new StringJoiner(" & ");
 572             for(AnnotatedType bound : bounds) {
 573                 sj.add(bound.toString());
 574             }
 575             sb.append(sj.toString());
 576             return sb.toString();
 577         }
 578 
 579 
 580         @Override
 581         public boolean equals(Object o) {
 582             if (o instanceof AnnotatedWildcardType) {
 583                 AnnotatedWildcardType that = (AnnotatedWildcardType) o;
 584                 return equalsTypeAndAnnotations(that) &&
 585                     // Treats ordering as significant
 586                     Arrays.equals(getAnnotatedLowerBounds(), that.getAnnotatedLowerBounds()) &&
 587                     // Treats ordering as significant
 588                     Arrays.equals(getAnnotatedUpperBounds(), that.getAnnotatedUpperBounds());
 589             } else {
 590                 return false;
 591             }
 592         }
 593 
 594         @Override
 595         public int hashCode() {
 596             return baseHashCode() ^
 597                 Objects.hash((Object[])getAnnotatedLowerBounds()) ^
 598                 Objects.hash((Object[])getAnnotatedUpperBounds());
 599         }
 600     }
 601 }