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