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