1 /* 2 * Copyright (c) 2007, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @summary Tests com.sun.beans.TypeResolver 27 * @author Eamonn McManus 28 * @modules java.base/sun.reflect.generics.reflectiveObjects 29 * java.desktop/com.sun.beans 30 */ 31 32 import com.sun.beans.TypeResolver; 33 34 import java.lang.annotation.Annotation; 35 import java.lang.reflect.AnnotatedType; 36 import java.lang.reflect.Field; 37 import java.lang.reflect.GenericDeclaration; 38 import java.lang.reflect.Method; 39 import java.lang.reflect.Type; 40 import java.lang.reflect.TypeVariable; 41 import java.lang.reflect.WildcardType; 42 import java.util.ArrayList; 43 import java.util.Arrays; 44 import java.util.Comparator; 45 import java.util.List; 46 import java.util.Map; 47 48 import sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl; 49 import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl; 50 51 public class TestTypeResolver { 52 static final List<Class<?>> failedCases = new ArrayList<Class<?>>(); 53 54 public static void main(String[] args) throws Exception { 55 test(TestTypeResolver.class); 56 if (failedCases.isEmpty()) 57 System.out.println("TEST PASSED"); 58 else { 59 System.out.println("TEST FAILED: failed cases: " + failedCases); 60 throw new Error("TEST FAILED"); 61 } 62 } 63 64 private static void test(Class<?> c) throws Exception { 65 /* Every public nested class represents a test. In each case, either 66 * the class contains further nested classes, in which case we 67 * call this method recursively; or it declares or inherits a 68 * method called getThing() and it declares a static field 69 * called "expect" which 70 * is the Type of that method's return value. The test consists 71 * of checking that the value returned by 72 * TypeResolver.resolveInClass is indeed this Type. 73 */ 74 System.out.println("Test " + c); 75 Class<?>[] nested = c.getClasses(); 76 Arrays.sort(nested, classNameComparator); 77 for (Class<?> n : nested) 78 test(n); 79 final Method m; 80 try { 81 m = c.getMethod("getThing"); 82 } catch (NoSuchMethodException e) { 83 if (nested.length == 0) { 84 System.out.println( 85 "TEST ERROR: class " + c.getName() + " has neither " + 86 "nested classes nor getThing() method"); 87 failedCases.add(c); 88 } 89 return; 90 } 91 Object expect = null; 92 try { 93 Field f = c.getDeclaredField("expect"); 94 expect = f.get(null); 95 } catch (NoSuchFieldException e) { 96 Class<?> outer = c.getDeclaringClass(); 97 if (outer != null) { 98 try { 99 Field f = outer.getDeclaredField("expect" + c.getSimpleName()); 100 expect = f.get(null); 101 } catch (NoSuchFieldException e1) { 102 } 103 } 104 } 105 if (expect == null) { 106 System.out.println( 107 "TEST ERROR: class " + c.getName() + " has getThing() method " + 108 "but not expect field"); 109 failedCases.add(c); 110 return; 111 } 112 Type t = m.getGenericReturnType(); 113 // t = FixType.fixType(t, c); 114 t = TypeResolver.resolveInClass(c, t); 115 System.out.print("..." + t); 116 // check expected value, and incidentally equals method defined 117 // by private implementations of the various Type interfaces 118 if (expect.equals(t) && t.equals(expect)) 119 System.out.println(", as expected"); 120 else if ((expect.equals(t) || t.equals(expect)) && expect.toString().equals(t.toString())) 121 System.out.println(", as workaround of the 8023301 bug"); 122 else { 123 System.out.println(" BUT SHOULD BE " + expect); 124 failedCases.add(c); 125 } 126 } 127 128 private static class ClassNameComparator implements Comparator<Class<?>> { 129 public int compare(Class<?> a, Class<?> b) { 130 return a.getName().compareTo(b.getName()); 131 } 132 } 133 134 private static final Comparator<Class<?>> classNameComparator = 135 new ClassNameComparator(); 136 137 private static abstract class TypeVariableImpl<D extends GenericDeclaration> 138 implements TypeVariable<D> { 139 private final String name; 140 private final D gd; 141 private final Type[] bounds; 142 143 TypeVariableImpl(String name, D gd, Type... bounds) { 144 this.name = name; 145 this.gd = gd; 146 if (bounds.length == 0) 147 bounds = new Type[] {Object.class}; 148 this.bounds = bounds.clone(); 149 } 150 151 public Type[] getBounds() { 152 return bounds.clone(); 153 } 154 155 public D getGenericDeclaration() { 156 return gd; 157 } 158 159 public String getName() { 160 return name; 161 } 162 163 public String toString() { 164 return name; 165 } 166 167 public boolean equals(Object o) { 168 if (!(o instanceof TypeVariable)) 169 return false; 170 TypeVariable tv = (TypeVariable) o; 171 return equal(name, tv.getName()) && 172 equal(gd, tv.getGenericDeclaration()) && 173 Arrays.equals(bounds, tv.getBounds()); 174 } 175 176 public int hashCode() { 177 return hash(name) ^ hash(gd) ^ Arrays.hashCode(bounds); 178 } 179 180 public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { 181 return false; // not used 182 } 183 184 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { 185 return null; // not used 186 } 187 188 public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) { 189 return null; // not used 190 } 191 192 public Annotation[] getAnnotations() { 193 return null; // not used 194 } 195 196 public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) { 197 return null; // not used 198 } 199 200 public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) { 201 return null; // not used 202 } 203 204 public Annotation[] getDeclaredAnnotations() { 205 return null; // not used 206 } 207 208 public AnnotatedType[] getAnnotatedBounds() { 209 return null; // not used 210 } 211 212 public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) { 213 return null; // not used 214 } 215 216 public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) { 217 return null; // not used 218 } 219 220 } 221 222 private static class ClassTypeVariable extends TypeVariableImpl<Class<?>> { 223 ClassTypeVariable(String name, Class<?> gd, Type... bounds) { 224 super(name, gd, bounds); 225 } 226 } 227 228 private static class MethodTypeVariable extends TypeVariableImpl<Method> { 229 MethodTypeVariable(String name, Method gd, Type... bounds) { 230 super(name, gd, bounds); 231 } 232 } 233 234 private static class WildcardTypeImpl implements WildcardType { 235 private final Type[] upperBounds; 236 private final Type[] lowerBounds; 237 238 WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) { 239 if (upperBounds == null || upperBounds.length == 0) 240 upperBounds = new Type[] {Object.class}; 241 if (lowerBounds == null) 242 lowerBounds = new Type[0]; 243 this.upperBounds = upperBounds.clone(); 244 this.lowerBounds = lowerBounds.clone(); 245 } 246 247 public Type[] getUpperBounds() { 248 return upperBounds.clone(); 249 } 250 251 public Type[] getLowerBounds() { 252 return lowerBounds.clone(); 253 } 254 255 public boolean equals(Object o) { 256 if (o instanceof WildcardType) { 257 WildcardType wt = (WildcardType) o; 258 return Arrays.equals(upperBounds, wt.getUpperBounds()) && 259 Arrays.equals(lowerBounds, wt.getLowerBounds()); 260 } else 261 return false; 262 } 263 264 public int hashCode() { 265 return Arrays.hashCode(upperBounds) ^ Arrays.hashCode(lowerBounds); 266 } 267 268 public String toString() { 269 StringBuilder sb = new StringBuilder("?"); 270 if (upperBounds.length > 1 || upperBounds[0] != Object.class) { 271 sb.append(" extends"); 272 appendBounds(sb, upperBounds); 273 } 274 if (lowerBounds.length > 0) { 275 sb.append(" super"); 276 appendBounds(sb, lowerBounds); 277 } 278 return sb.toString(); 279 } 280 281 private static void appendBounds(StringBuilder sb, Type[] bounds) { 282 boolean and = false; 283 for (Type bound : bounds) { 284 if (and) 285 sb.append(" &"); 286 sb.append(" "); 287 if (bound instanceof Class) 288 sb.append(((Class<?>) bound).getName()); 289 else 290 sb.append(bound); 291 and = true; 292 } 293 } 294 } 295 296 static boolean equal(Object x, Object y) { 297 if (x == y) 298 return true; 299 if (x == null || y == null) 300 return false; 301 return x.equals(y); 302 } 303 304 static int hash(Object x) { 305 return (x == null) ? null : x.hashCode(); 306 } 307 308 309 public static class Outer<T> { 310 public class Inner { 311 public T getThing() { 312 return null; 313 } 314 } 315 316 static final Type expectInner = new ClassTypeVariable("T", Outer.class); 317 } 318 319 public static class Super<T> { 320 static final Type expect = new ClassTypeVariable("T", Super.class); 321 322 public T getThing() { 323 return null; 324 } 325 } 326 327 public static class Int extends Super<Integer> { 328 static final Type expect = Integer.class; 329 } 330 331 public static class IntOverride extends Int { 332 static final Type expect = Integer.class; 333 334 public Integer getThing() { 335 return null; 336 } 337 } 338 339 public static class Mid<X> extends Super<X> { 340 static final Type expect = new ClassTypeVariable("X", Mid.class); 341 } 342 343 public static class Str extends Mid<String> { 344 static final Type expect = String.class; 345 } 346 347 public static class ListInt extends Super<List<Integer>> { 348 static final Type expect = ParameterizedTypeImpl.make( 349 List.class, new Type[] {Integer.class}, null); 350 } 351 352 public static class ListIntSub extends ListInt { 353 static final Type expect = ParameterizedTypeImpl.make( 354 List.class, new Type[] {Integer.class}, null); 355 356 public List<Integer> getThing() { 357 return null; 358 } 359 } 360 361 public static class ListU<U> extends Super<List<U>> { 362 static final Type expect = ParameterizedTypeImpl.make( 363 List.class, new Type[] {new ClassTypeVariable("U", ListU.class)}, null); 364 } 365 366 public static class ListUInt extends ListU<Integer> { 367 static final Type expect = ParameterizedTypeImpl.make( 368 List.class, new Type[] {Integer.class}, null); 369 } 370 371 public static class ListUSub<V> extends ListU<V> { 372 static final Type expect = ParameterizedTypeImpl.make( 373 List.class, new Type[] {new ClassTypeVariable("V", ListUSub.class)}, null); 374 375 public List<V> getThing() { 376 return null; 377 } 378 } 379 380 public static class ListUSubInt extends ListUSub<Integer> { 381 static final Type expect = ParameterizedTypeImpl.make( 382 List.class, new Type[] {Integer.class}, null); 383 } 384 385 public static class TwoParams<S, T> extends Super<S> { 386 static final Type expect = new ClassTypeVariable("S", TwoParams.class); 387 } 388 389 public static class TwoParamsSub<T> extends TwoParams<T, Integer> { 390 static final Type expect = new ClassTypeVariable("T", TwoParamsSub.class); 391 } 392 393 public static class TwoParamsSubSub extends TwoParamsSub<String> { 394 static final Type expect = String.class; 395 } 396 397 public static interface Intf<T> { 398 static final Type expect = new ClassTypeVariable("T", Intf.class); 399 400 public T getThing(); 401 } 402 403 public static abstract class Impl implements Intf<String> { 404 static final Type expect = String.class; 405 } 406 407 public static class Impl2 extends Super<String> implements Intf<String> { 408 static final Type expect = String.class; 409 } 410 411 public static class Bound<T extends Number> extends Super<T> { 412 static final Type expect = new ClassTypeVariable("T", Bound.class, Number.class); 413 } 414 415 public static class BoundInt extends Bound<Integer> { 416 static final Type expect = Integer.class; 417 } 418 419 public static class RawBound extends Bound { 420 static final Type expect = Number.class; 421 } 422 423 public static class RawBoundInt extends BoundInt { 424 static final Type expect = Integer.class; 425 } 426 427 public static class MethodParam<T> { 428 private static final Method m; 429 430 static { 431 try { 432 m = MethodParam.class.getMethod("getThing"); 433 } catch (Exception e) { 434 throw new AssertionError(e); 435 } 436 } 437 438 static final Type expect = new MethodTypeVariable("T", m); 439 440 public <T> T getThing() { 441 return null; 442 } 443 } 444 445 public static class Raw extends Super { 446 static final Type expect = Object.class; 447 } 448 449 public static class RawSub extends Raw { 450 static final Type expect = Object.class; 451 } 452 453 public static class SimpleArray extends Super<String[]> { 454 static final Type expect = String[].class; 455 } 456 457 public static class GenericArray extends Super<List<String>[]> { 458 static final Type expect = GenericArrayTypeImpl.make( 459 ParameterizedTypeImpl.make(List.class, new Type[] {String.class}, null)); 460 } 461 462 public static class GenericArrayT<T> extends Super<T[]> { 463 static final Type expect = GenericArrayTypeImpl.make( 464 new ClassTypeVariable("T", GenericArrayT.class)); 465 } 466 467 public static class GenericArrayTSub extends GenericArrayT<String[]> { 468 static final Type expect = String[][].class; 469 } 470 471 public static class Wildcard extends Super<List<?>> { 472 static final Type expect = ParameterizedTypeImpl.make( 473 List.class, new Type[] {new WildcardTypeImpl(null, null)}, null); 474 } 475 476 public static class WildcardT<T> extends Super<List<? extends T>> { 477 static final Type expect = ParameterizedTypeImpl.make( 478 List.class, 479 new Type[] { 480 new WildcardTypeImpl( 481 new Type[] {new ClassTypeVariable("T", WildcardT.class)}, 482 null)}, 483 null); 484 } 485 486 public static class WildcardTSub extends WildcardT<Integer> { 487 static final Type expect = ParameterizedTypeImpl.make( 488 List.class, 489 new Type[] { 490 new WildcardTypeImpl( 491 new Type[] {Integer.class}, 492 null)}, 493 null); 494 } 495 496 public static class WildcardTSubSub<X> extends WildcardTSub { 497 // X is just so we can have a raw subclass 498 static final Type expect = WildcardTSub.expect; 499 } 500 501 public static class RawWildcardTSubSub extends WildcardTSubSub { 502 static final Type expect = List.class; 503 } 504 505 public static class WildcardTSuper<T> extends Super<List<? super T>> { 506 static final Type expect = ParameterizedTypeImpl.make( 507 List.class, 508 new Type[] { 509 new WildcardTypeImpl( 510 null, 511 new Type[] {new ClassTypeVariable("T", WildcardTSuper.class)})}, 512 null); 513 } 514 515 public static class WildcardTSuperSub extends WildcardTSuper<Integer> { 516 static final Type expect = ParameterizedTypeImpl.make( 517 List.class, 518 new Type[] { 519 new WildcardTypeImpl( 520 null, 521 new Type[] {Integer.class})}, 522 null); 523 } 524 525 public static class SuperMap<K, V> { 526 static final Type expect = ParameterizedTypeImpl.make( 527 Map.class, 528 new Type[] { 529 new ClassTypeVariable("K", SuperMap.class), 530 new ClassTypeVariable("V", SuperMap.class)}, 531 null); 532 533 public Map<K, V> getThing() { 534 return null; 535 } 536 } 537 538 public static class SubMap extends SuperMap<String, Integer> { 539 static final Type expect = ParameterizedTypeImpl.make( 540 Map.class, 541 new Type[] {String.class, Integer.class}, 542 null); 543 } 544 545 public static class ListListT<T> extends Super<List<List<T>>> { 546 static final Type expect = ParameterizedTypeImpl.make( 547 List.class, 548 new Type[] { 549 ParameterizedTypeImpl.make( 550 List.class, 551 new Type[] {new ClassTypeVariable("T", ListListT.class)}, 552 null)}, 553 null); 554 } 555 556 public static class ListListString extends ListListT<String> { 557 static final Type expect = ParameterizedTypeImpl.make( 558 List.class, 559 new Type[] { 560 ParameterizedTypeImpl.make( 561 List.class, 562 new Type[] {String.class}, 563 null)}, 564 null); 565 } 566 567 public static class UExtendsT<T, U extends T> extends Super<U> { 568 static final Type expect = new ClassTypeVariable( 569 "U", UExtendsT.class, new ClassTypeVariable("T", UExtendsT.class)); 570 } 571 572 public static class UExtendsTSub extends UExtendsT<Number, Integer> { 573 static final Type expect = Integer.class; 574 } 575 576 public static class SelfRef<T extends SelfRef<T>> extends Super<T> { 577 static final Type expect = 578 SelfRef.class.getTypeParameters()[0]; 579 } 580 581 public static class SelfRefSub extends SelfRef<SelfRefSub> { 582 static final Type expect = SelfRefSub.class; 583 } 584 }