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. 211 return annotationsToString(getAnnotations(), false) + type.toString(); 212 } 213 214 protected String annotationsToString(Annotation[] annotations, boolean leadingSpace) { 215 if (annotations != null && annotations.length > 0) { 216 StringJoiner sj = new StringJoiner(" "); 217 if (leadingSpace) { 218 sj.add(""); // Add a space 219 } 220 221 for (Annotation annotation : annotations) { 222 sj.add(annotation.toString()); 223 } 224 225 if (!leadingSpace) { 226 sj.add(""); 227 } 228 return sj.toString(); 229 } else { 230 return ""; 231 } 232 } 233 234 protected boolean equalsTypeAndAnnotations(AnnotatedType that) { 235 return getType().equals(that.getType()) && 236 // Treat ordering of annotations as significant 237 Arrays.equals(getAnnotations(), that.getAnnotations()) && 238 Objects.equals(getAnnotatedOwnerType(), that.getAnnotatedOwnerType()); 239 } 240 241 int baseHashCode() { 242 return type.hashCode() ^ 243 // Acceptable to use Objects.hash rather than 244 // Arrays.deepHashCode since the elements of the array 245 // are not themselves arrays. 246 Objects.hash((Object[])getAnnotations()) ^ 247 Objects.hash(getAnnotatedOwnerType()); 248 } 249 250 @Override 251 public boolean equals(Object o) { 252 if (o instanceof AnnotatedType && 253 !(o instanceof AnnotatedArrayType) && 254 !(o instanceof AnnotatedTypeVariable) && 255 !(o instanceof AnnotatedParameterizedType) && 256 !(o instanceof AnnotatedWildcardType)) { 257 AnnotatedType that = (AnnotatedType) o; 258 return equalsTypeAndAnnotations(that); 259 } else { 260 return false; 261 } 262 } 263 264 @Override 265 public int hashCode() { 266 return baseHashCode(); 267 } 268 269 // Implementation details 270 final LocationInfo getLocation() { 271 return location; 272 } 273 final TypeAnnotation[] getTypeAnnotations() { 274 return allOnSameTargetTypeAnnotations; 275 } 276 final AnnotatedElement getDecl() { 277 return decl; 278 } 279 } 280 281 private static final class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType { 282 AnnotatedArrayTypeImpl(Type type, LocationInfo location, 283 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 284 AnnotatedElement decl) { 285 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); 286 } 287 288 @Override 289 public AnnotatedType getAnnotatedGenericComponentType() { 290 Type t = getComponentType(); 291 return AnnotatedTypeFactory.buildAnnotatedType(t, 292 nestingForType(t, getLocation().pushArray()), 293 getTypeAnnotations(), 294 getTypeAnnotations(), 295 getDecl()); 296 } 297 298 @Override 299 public AnnotatedType getAnnotatedOwnerType() { 300 return null; 301 } 302 303 private Type getComponentType() { 304 Type t = getType(); 305 if (t instanceof Class) { 306 Class<?> c = (Class)t; 307 return c.getComponentType(); 308 } 309 return ((GenericArrayType)t).getGenericComponentType(); 310 } 311 312 @Override 313 public String toString() { 314 // To annotate the full type of an array, the annotations 315 // are placed between the type and the brackets. For 316 // example, to annotate an array of Strings, the syntax used is 317 // 318 // String @TypeAnnotation [] 319 // 320 // and *not* 321 // 322 // @TypeAnnotation String[]. 323 // 324 // The toString output should strive to be reusable in 325 // source code. Therefore, the general logic of putting 326 // the annotations before a textual representation of the 327 // type need to be overridden for arrays. 328 StringBuilder sb = new StringBuilder(); 329 330 AnnotatedType componentType = this; 331 while (componentType instanceof AnnotatedArrayType) { 332 AnnotatedArrayType annotatedArrayType = (AnnotatedArrayType) componentType; 333 sb.append(annotationsToString(annotatedArrayType.getAnnotations(), true) + "[]"); 334 componentType = annotatedArrayType.getAnnotatedGenericComponentType(); 335 } 336 337 sb.insert(0, componentType.toString()); 338 return sb.toString(); 339 } 340 341 @Override 342 public boolean equals(Object o) { 343 if (o instanceof AnnotatedArrayType) { 344 AnnotatedArrayType that = (AnnotatedArrayType) o; 345 return equalsTypeAndAnnotations(that) && 346 Objects.equals(getAnnotatedGenericComponentType(), 347 that.getAnnotatedGenericComponentType()); 348 } else { 349 return false; 350 } 351 } 352 353 @Override 354 public int hashCode() { 355 return baseHashCode() ^ getAnnotatedGenericComponentType().hashCode(); 356 } 357 } 358 359 private static final class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable { 360 AnnotatedTypeVariableImpl(TypeVariable<?> type, LocationInfo location, 361 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 362 AnnotatedElement decl) { 363 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); 364 } 365 366 @Override 367 public AnnotatedType[] getAnnotatedBounds() { 368 return getTypeVariable().getAnnotatedBounds(); 369 } 370 371 @Override 372 public AnnotatedType getAnnotatedOwnerType() { 373 return null; 374 } 375 376 private TypeVariable<?> getTypeVariable() { 377 return (TypeVariable)getType(); 378 } 379 380 @Override 381 public boolean equals(Object o) { 382 if (o instanceof AnnotatedTypeVariable) { 383 AnnotatedTypeVariable that = (AnnotatedTypeVariable) o; 384 return equalsTypeAndAnnotations(that) && 385 Arrays.equals(getAnnotatedBounds(), that.getAnnotatedBounds()); 386 } else { 387 return false; 388 } 389 } 390 391 @Override 392 public int hashCode() { 393 return baseHashCode() ^ 394 Objects.hash((Object[])getAnnotatedBounds()); 395 } 396 } 397 398 private static final class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl 399 implements AnnotatedParameterizedType { 400 AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location, 401 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 402 AnnotatedElement decl) { 403 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); 404 } 405 406 @Override 407 public AnnotatedType[] getAnnotatedActualTypeArguments() { 408 Type[] arguments = getParameterizedType().getActualTypeArguments(); 409 AnnotatedType[] res = new AnnotatedType[arguments.length]; 410 Arrays.fill(res, EMPTY_ANNOTATED_TYPE); 411 int initialCapacity = getTypeAnnotations().length; 412 for (int i = 0; i < res.length; i++) { 413 List<TypeAnnotation> l = new ArrayList<>(initialCapacity); 414 LocationInfo newLoc = nestingForType(arguments[i], getLocation().pushTypeArg((byte)i)); 415 for (TypeAnnotation t : getTypeAnnotations()) 416 if (t.getLocationInfo().isSameLocationInfo(newLoc)) 417 l.add(t); 418 res[i] = buildAnnotatedType(arguments[i], 419 newLoc, 420 l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), 421 getTypeAnnotations(), 422 getDecl()); 423 } 424 return res; 425 } 426 427 @Override 428 public AnnotatedType getAnnotatedOwnerType() { 429 Type owner = getParameterizedType().getOwnerType(); 430 if (owner == null) 431 return null; 432 LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1)); 433 TypeAnnotation[]all = getTypeAnnotations(); 434 List<TypeAnnotation> l = new ArrayList<>(all.length); 435 436 for (TypeAnnotation t : all) 437 if (t.getLocationInfo().isSameLocationInfo(outerLoc)) 438 l.add(t); 439 440 return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl()); 441 } 442 443 private ParameterizedType getParameterizedType() { 444 return (ParameterizedType)getType(); 445 } 446 447 @Override 448 public boolean equals(Object o) { 449 if (o instanceof AnnotatedParameterizedType) { 450 AnnotatedParameterizedType that = (AnnotatedParameterizedType) o; 451 return equalsTypeAndAnnotations(that) && 452 Arrays.equals(getAnnotatedActualTypeArguments(), that.getAnnotatedActualTypeArguments()); 453 } else { 454 return false; 455 } 456 } 457 458 @Override 459 public int hashCode() { 460 return baseHashCode() ^ 461 Objects.hash((Object[])getAnnotatedActualTypeArguments()); 462 } 463 } 464 465 private static final class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType { 466 private final boolean hasUpperBounds; 467 AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location, 468 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 469 AnnotatedElement decl) { 470 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); 471 hasUpperBounds = (type.getLowerBounds().length == 0); 472 } 473 474 @Override 475 public AnnotatedType[] getAnnotatedUpperBounds() { 476 if (!hasUpperBounds()) { 477 return new AnnotatedType[] { buildAnnotatedType(Object.class, 478 LocationInfo.BASE_LOCATION, 479 EMPTY_TYPE_ANNOTATION_ARRAY, 480 EMPTY_TYPE_ANNOTATION_ARRAY, 481 null) 482 }; 483 } 484 return getAnnotatedBounds(getWildcardType().getUpperBounds()); 485 } 486 487 @Override 488 public AnnotatedType[] getAnnotatedLowerBounds() { 489 if (hasUpperBounds) 490 return new AnnotatedType[0]; 491 return getAnnotatedBounds(getWildcardType().getLowerBounds()); 492 } 493 494 @Override 495 public AnnotatedType getAnnotatedOwnerType() { 496 return null; 497 } 498 499 private AnnotatedType[] getAnnotatedBounds(Type[] bounds) { 500 AnnotatedType[] res = new AnnotatedType[bounds.length]; 501 Arrays.fill(res, EMPTY_ANNOTATED_TYPE); 502 int initialCapacity = getTypeAnnotations().length; 503 for (int i = 0; i < res.length; i++) { 504 LocationInfo newLoc = nestingForType(bounds[i], getLocation().pushWildcard()); 505 List<TypeAnnotation> l = new ArrayList<>(initialCapacity); 506 for (TypeAnnotation t : getTypeAnnotations()) 507 if (t.getLocationInfo().isSameLocationInfo(newLoc)) 508 l.add(t); 509 res[i] = buildAnnotatedType(bounds[i], 510 newLoc, 511 l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), 512 getTypeAnnotations(), 513 getDecl()); 514 } 515 return res; 516 } 517 518 private WildcardType getWildcardType() { 519 return (WildcardType)getType(); 520 } 521 522 private boolean hasUpperBounds() { 523 return hasUpperBounds; 524 } 525 526 @Override 527 public boolean equals(Object o) { 528 if (o instanceof AnnotatedWildcardType) { 529 AnnotatedWildcardType that = (AnnotatedWildcardType) o; 530 return equalsTypeAndAnnotations(that) && 531 // Treats ordering as significant 532 Arrays.equals(getAnnotatedLowerBounds(), that.getAnnotatedLowerBounds()) && 533 // Treats ordering as significant 534 Arrays.equals(getAnnotatedUpperBounds(), that.getAnnotatedUpperBounds()); 535 } else { 536 return false; 537 } 538 } 539 540 @Override 541 public int hashCode() { 542 return baseHashCode() ^ 543 Objects.hash((Object[])getAnnotatedLowerBounds()) ^ 544 Objects.hash((Object[])getAnnotatedUpperBounds()); 545 } 546 } 547 }