001 package net.sourceforge.retroweaver.runtime.java.lang.reflect; 002 003 import java.io.IOException; 004 import java.io.InputStream; 005 import java.lang.reflect.Constructor; 006 import java.lang.reflect.Field; 007 import java.lang.reflect.Method; 008 import java.util.HashMap; 009 import java.util.HashSet; 010 import java.util.LinkedList; 011 import java.util.Map; 012 import java.util.Set; 013 import java.util.Stack; 014 015 import net.sourceforge.retroweaver.runtime.java.lang.TypeNotPresentException; 016 import net.sourceforge.retroweaver.runtime.java.lang.annotation.AIB; 017 018 import org.objectweb.asm.AnnotationVisitor; 019 import org.objectweb.asm.Attribute; 020 import org.objectweb.asm.ClassReader; 021 import org.objectweb.asm.ClassVisitor; 022 import org.objectweb.asm.FieldVisitor; 023 import org.objectweb.asm.MethodVisitor; 024 import org.objectweb.asm.Opcodes; 025 import org.objectweb.asm.signature.SignatureReader; 026 import org.objectweb.asm.signature.SignatureVisitor; 027 028 public class ReflectionDescriptor implements ClassVisitor { 029 030 private static final boolean DEBUG = false; 031 032 private static final Map<Class, ReflectionDescriptor> descriptors = new HashMap<Class, ReflectionDescriptor>(); 033 034 public static ReflectionDescriptor getReflectionDescriptor(Class class_) { 035 synchronized (descriptors) { 036 ReflectionDescriptor d = descriptors.get(class_); 037 if (d == null) { 038 d = new ReflectionDescriptor(class_); 039 descriptors.put(class_, d); 040 if (DEBUG) d.debugMessage("Adding descriptor"); 041 } 042 return d; 043 } 044 } 045 046 private final Class class_; 047 048 private ReflectionDescriptor(Class class_) { 049 this.class_ = class_; 050 String name = class_.getName(); 051 052 String resource = "/" + name.replace('.', '/') + ".class"; 053 if (DEBUG) System.out.println("Reading class file: " + resource); 054 InputStream classStream = class_.getResourceAsStream(resource); 055 parseStream(name, classStream); 056 } 057 058 protected ReflectionDescriptor(String name, InputStream classStream) { 059 class_ = null; 060 parseStream(name, classStream); 061 } 062 063 private void parseStream(String name, InputStream classStream) { 064 try { 065 ClassReader r = new ClassReader(classStream); 066 r.accept(this, ClassReader.SKIP_CODE + ClassReader.SKIP_DEBUG 067 + ClassReader.SKIP_FRAMES); 068 069 } catch (IOException e) { 070 // Shouldn't generally happen 071 throw new TypeNotPresentException( 072 "[Retroweaver] Unable to read reflection data for: " + name, e); 073 } finally { 074 try { 075 if (classStream != null) { 076 classStream.close(); 077 } 078 } catch (IOException e) { // NOPMD by xlv 079 } 080 } 081 } 082 083 private String internalName; 084 085 private String enclosingClassName; 086 087 private String enclosingMethodName; 088 089 private String enclosingMethodDesc; 090 091 private HashMap<String, Integer> fieldAccessTable = new HashMap<String, Integer>(); 092 093 private HashMap<String, Integer> methodAccessTable = new HashMap<String, Integer>(); 094 095 public String getEnclosingClassName() { 096 return enclosingClassName; 097 } 098 099 public void debugMessage(String msg) { 100 System.out.println(msg + 101 "\n\tclass: " + class_.getName() + 102 "\n\tenclosingClassName: " + enclosingClassName + 103 "\n\tenclosingMethodName: " + enclosingMethodName + ' ' + enclosingMethodDesc); 104 } 105 106 public Class getEnclosingClass() { 107 //debugMessage("getEnclosingClass"); 108 if (enclosingClassName == null) { 109 return null; 110 } 111 112 try { 113 //debugMessage("getEnclosingClass"); 114 String name = enclosingClassName.replace('/', '.'); 115 Class c = class_.getClassLoader().loadClass(name); 116 117 return c; 118 } catch (ClassNotFoundException e) { 119 return null; 120 } 121 } 122 123 public Method getEnclosingMethod() { 124 //debugMessage("getEnclosingMethod"); 125 if (enclosingMethodName == null) { 126 return null; 127 } 128 129 return getMethod(getEnclosingClass(), enclosingMethodName, enclosingMethodDesc); 130 } 131 132 public Constructor getEnclosingConstructor() { 133 //debugMessage("getEnclosingMethod"); 134 if (enclosingMethodName == null) { 135 return null; 136 } 137 138 return getConstructor(getEnclosingClass(), enclosingMethodDesc); 139 } 140 141 public boolean testFieldAccess(Field f, int mask) { 142 String name = f.getName(); 143 return (fieldAccessTable.get(name).intValue() & mask) != 0; 144 } 145 146 public boolean testMethodAccess(Method m, int mask) { 147 String name = m.getName(); 148 String desc = org.objectweb.asm.Type.getMethodDescriptor(m); 149 return (methodAccessTable.get(name+desc).intValue() & mask) != 0; 150 } 151 152 public boolean testConstructorAccess(Constructor c, int mask) { 153 String name = "<init>"; 154 String desc = org.objectweb.asm.Type.getConstructorDescriptor(c); 155 return (methodAccessTable.get(name+desc).intValue() & mask) != 0; 156 } 157 158 private Method getMethod(Class class_, String name, String desc) { 159 org.objectweb.asm.Type[] types = org.objectweb.asm.Type.getArgumentTypes(desc); 160 161 outer_loop: 162 for (Method m : class_.getDeclaredMethods()) { 163 final org.objectweb.asm.Type[] methodTypes = org.objectweb.asm.Type.getArgumentTypes(m); 164 if (!m.getName().equals(name) 165 || methodTypes.length != types.length) { 166 continue; 167 } 168 for (int i = 0; i < types.length; ++i) { 169 if (!types[i].equals(methodTypes[i])) { 170 continue outer_loop; 171 } 172 } 173 return m; 174 } 175 return null; 176 } 177 178 private Constructor getConstructor(Class class_, String desc) { 179 org.objectweb.asm.Type[] types = org.objectweb.asm.Type.getArgumentTypes(desc); 180 181 outer_loop: 182 for (Constructor c : class_.getDeclaredConstructors()) { 183 final Class[] constructorTypes = c.getParameterTypes(); 184 if (constructorTypes.length != types.length) { 185 continue; 186 } 187 for (int i = 0; i < types.length; ++i) { 188 if (!types[i].equals(org.objectweb.asm.Type.getType(constructorTypes[i]))) { 189 continue outer_loop; 190 } 191 } 192 return c; 193 } 194 return null; 195 } 196 197 private void parseSignature(String signature, boolean isInterface, String superName, String[] interfaces) { 198 if (signature == null) { 199 typeParameters = new TypeVariable[0]; 200 genericSuperclass = superName==null?null:new ClassTypeImpl(superName.replaceAll("/", ".")); 201 if (interfaces == null) { 202 genericInterfaces = new Type[0]; 203 } else { 204 genericInterfaces = new Type[interfaces.length]; 205 for(int i = 0; i < interfaces.length; i++) { 206 genericInterfaces[i] = new ClassTypeImpl(interfaces[i].replaceAll("/", "."), true); 207 } 208 } 209 } else { 210 if (DEBUG) System.out.println("Parsing " + signature); 211 SignatureReader r = new SignatureReader(signature); 212 ClassTypeImpl currentType = new ClassTypeImpl(internalName.replaceAll("/", "."), isInterface); 213 SigVisitor v = new SigVisitor(currentType, false); 214 r.accept(v); 215 v.endParsing(); 216 217 typeParameters = v.typeParameters; 218 genericSuperclass = v.genericSuperclass; 219 genericInterfaces = v.genericInterfaces; 220 } 221 if (isInterface) { 222 genericSuperclass = null; 223 } 224 225 } 226 227 private TypeVariable[] typeParameters; 228 229 private Type genericSuperclass; 230 231 private Type[] genericInterfaces; 232 233 public TypeVariable[] getTypeParameters() throws GenericSignatureFormatError { 234 return typeParameters; 235 } 236 237 public Type getGenericSuperclass() throws GenericSignatureFormatError, TypeNotPresentException, MalformedParameterizedTypeException { 238 return genericSuperclass; 239 } 240 241 public Type[] getGenericInterfaces() throws GenericSignatureFormatError, TypeNotPresentException, MalformedParameterizedTypeException { 242 return genericInterfaces; 243 } 244 245 /** 246 * Visits the header of the class. 247 * 248 * @param version the class version. 249 * @param access the class's access flags (see {@link Opcodes}). This 250 * parameter also indicates if the class is deprecated. 251 * @param name the internal name of the class (see 252 * {@link Type#getInternalName() getInternalName}). 253 * @param signature the signature of this class. May be <tt>null</tt> if 254 * the class is not a generic one, and does not extend or implement 255 * generic classes or interfaces. 256 * @param superName the internal of name of the super class (see 257 * {@link Type#getInternalName() getInternalName}). For interfaces, 258 * the super class is {@link Object}. May be <tt>null</tt>, but 259 * only for the {@link Object} class. 260 * @param interfaces the internal names of the class's interfaces (see 261 * {@link Type#getInternalName() getInternalName}). May be 262 * <tt>null</tt>. 263 */ 264 public void visit( 265 int version, 266 int access, 267 String name, 268 String signature, 269 String superName, 270 String[] interfaces) { 271 internalName = name; 272 boolean isInterface = ( access & Opcodes.ACC_INTERFACE ) == Opcodes.ACC_INTERFACE; 273 parseSignature(signature, isInterface, superName, interfaces); 274 } 275 276 public void visitSource(String source, String debug) {} 277 278 /** 279 * Visits the enclosing class of the class. This method must be called only 280 * if the class has an enclosing class. 281 * 282 * @param owner internal name of the enclosing class of the class. 283 * @param name the name of the method that contains the class, or 284 * <tt>null</tt> if the class is not enclosed in a method of its 285 * enclosing class. 286 * @param desc the descriptor of the method that contains the class, or 287 * <tt>null</tt> if the class is not enclosed in a method of its 288 * enclosing class. 289 */ 290 public void visitOuterClass(String owner, String name, String desc) { 291 enclosingClassName = owner; 292 enclosingMethodName = name; 293 enclosingMethodDesc = desc; 294 //debugMessage("visitOuterClass"); 295 } 296 297 /** 298 * Visits information about an inner class. This inner class is not 299 * necessarily a member of the class being visited. 300 * 301 * @param name the internal name of an inner class (see 302 * {@link Type#getInternalName() getInternalName}). 303 * @param outerName the internal name of the class to which the inner class 304 * belongs (see {@link Type#getInternalName() getInternalName}). May 305 * be <tt>null</tt>. 306 * @param innerName the (simple) name of the inner class inside its 307 * enclosing class. May be <tt>null</tt> for anonymous inner 308 * classes. 309 * @param access the access flags of the inner class as originally declared 310 * in the enclosing class. 311 */ 312 public void visitInnerClass( 313 String name, 314 String outerName, 315 String innerName, 316 int access) { 317 if (name.equals(internalName)) { 318 if (outerName != null) { 319 enclosingClassName = outerName; 320 } 321 } 322 //debugMessage("visitInnerClass"); 323 } 324 325 public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 326 return AIB.EMPTY_VISITOR; 327 } 328 329 public void visitAttribute(Attribute attr) {} 330 331 public FieldVisitor visitField( 332 int access, 333 String name, 334 String desc, 335 String signature, 336 Object value) { 337 fieldAccessTable.put(name, access); 338 return null; 339 } 340 341 public MethodVisitor visitMethod( 342 int access, 343 String name, 344 String desc, 345 String signature, 346 String[] exceptions) { 347 methodAccessTable.put(name+desc, access); 348 return null; 349 } 350 351 public void visitEnd() {} 352 353 public static void main(String args[]) { 354 String signature = "<E:Ljava/lang/String;>Ljava/util/LinkedList<TE;>;Ljava/io/Serializable;Ljava/lang/Comparable<TE;>;"; 355 String internalName = "blah.TopLevel"; 356 357 System.out.println("Parsing " + signature); 358 SignatureReader r = new SignatureReader(signature); 359 ClassTypeImpl currentType = new ClassTypeImpl(internalName.replaceAll("/", "."), false); 360 SigVisitor v = new SigVisitor(currentType, false); 361 r.accept(v); 362 v.endParsing(); 363 364 System.out.println(v.genericInterfaces.length); 365 for(Type t: v.genericInterfaces) { 366 System.out.println(t); 367 } 368 } 369 370 private static class SigVisitor implements SignatureVisitor { 371 protected TypeVariable[] typeParameters; 372 protected Type genericSuperclass; 373 protected Type[] genericInterfaces; 374 375 private Stack<Type> stack = new Stack<Type>(); 376 377 private Set<TypeVariableImpl> typeVariables = new HashSet<TypeVariableImpl>(); 378 379 private LinkedList<TypeVariableImpl> formalTypeParameters = new LinkedList<TypeVariableImpl>(); 380 381 private StringBuffer declaration; 382 383 private boolean isInterface; 384 385 private ClassTypeImpl currentType; 386 387 private boolean seenFormalParameter; 388 389 private boolean seenInterfaceBound; 390 391 private boolean seenParameter; 392 393 private boolean seenInterface; 394 395 private StringBuffer returnType; 396 397 private StringBuffer exceptions; 398 399 /** 400 * Stack used to keep track of class types that have arguments. Each element 401 * of this stack is a boolean encoded in one bit. The top of the stack is 402 * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping = 403 * /2. 404 */ 405 private int argumentStack; 406 407 private Stack<Integer> argumentStackPosition = new Stack<Integer>(); 408 409 /** 410 * Stack used to keep track of array class types. Each element of this stack 411 * is a boolean encoded in one bit. The top of the stack is the lowest order 412 * bit. Pushing false = *2, pushing true = *2+1, popping = /2. 413 */ 414 private int arrayStack; 415 416 private String separator = ""; 417 418 public SigVisitor(final ClassTypeImpl currentType, final boolean isInterface) { 419 this.isInterface = isInterface; 420 this.declaration = new StringBuffer(); 421 this.currentType = currentType; 422 } 423 424 private SigVisitor(final StringBuffer buf) { 425 this.declaration = buf; 426 } 427 428 /** 429 * Visits a formal type parameter. 430 * 431 * @param name the name of the formal parameter. 432 */ 433 public void visitFormalTypeParameter(final String name) { 434 if (seenFormalParameter) { 435 endFormal(); 436 } 437 TypeVariableImpl t = new TypeVariableImpl(name); 438 typeVariables.add(t); 439 formalTypeParameters.add(t); 440 if (DEBUG) System.out.println("pushing visitFormalTypeParameter " + t); 441 442 declaration.append(seenFormalParameter ? ", " : "<").append(name); 443 seenFormalParameter = true; 444 seenInterfaceBound = false; 445 } 446 447 /** 448 * Visits the class bound of the last visited formal type parameter. 449 * 450 * @return a non null visitor to visit the signature of the class bound. 451 */ 452 public SignatureVisitor visitClassBound() { 453 separator = " extends "; 454 startType(); 455 return this; 456 } 457 458 /** 459 * Visits an interface bound of the last visited formal type parameter. 460 * 461 * @return a non null visitor to visit the signature of the interface bound. 462 */ 463 public SignatureVisitor visitInterfaceBound() { 464 separator = seenInterfaceBound ? ", " : " extends "; 465 seenInterfaceBound = true; 466 startType(); 467 return this; 468 } 469 470 /** 471 * Visits the type of the super class. 472 * 473 * @return a non null visitor to visit the signature of the super class 474 * type. 475 */ 476 public SignatureVisitor visitSuperclass() { 477 endFormals(); 478 separator = " extends "; 479 startType(); 480 return this; 481 } 482 483 /** 484 * Visits the type of an interface implemented by the class. 485 * 486 * @return a non null visitor to visit the signature of the interface type. 487 */ 488 public SignatureVisitor visitInterface() { 489 if (!seenInterface) { 490 endGenericSuperclass(); 491 } 492 separator = seenInterface ? ", " : isInterface 493 ? " extends " 494 : " implements "; 495 seenInterface = true; 496 startType(); 497 return this; 498 } 499 500 /** 501 * Visits the type of a method parameter. 502 * 503 * @return a non null visitor to visit the signature of the parameter type. 504 */ 505 public SignatureVisitor visitParameterType() { 506 endFormals(); 507 if (!seenParameter) { 508 seenParameter = true; 509 declaration.append('('); 510 } else { 511 declaration.append(", "); 512 } 513 startType(); 514 return this; 515 } 516 517 /** 518 * Visits the return type of the method. 519 * 520 * @return a non null visitor to visit the signature of the return type. 521 */ 522 public SignatureVisitor visitReturnType() { 523 endFormals(); 524 if (!seenParameter) { 525 declaration.append('('); 526 } else { 527 seenParameter = false; 528 } 529 declaration.append(')'); 530 returnType = new StringBuffer(); 531 return new SigVisitor(returnType); 532 } 533 534 /** 535 * Visits the type of a method exception. 536 * 537 * @return a non null visitor to visit the signature of the exception type. 538 */ 539 public SignatureVisitor visitExceptionType() { 540 if (exceptions == null) { 541 exceptions = new StringBuffer(); 542 } else { 543 exceptions.append(", "); 544 } 545 // startType(); 546 return new SigVisitor(exceptions); 547 } 548 549 /** 550 * Visits a signature corresponding to a primitive type. 551 * 552 * @param descriptor the descriptor of the primitive type, or 'V' for 553 * <tt>void</tt>. 554 */ 555 public void visitBaseType(final char descriptor) { 556 if (DEBUG) System.out.println("visitBaseType " + descriptor); 557 switch (descriptor) { 558 case 'V': 559 declaration.append("void"); 560 break; 561 case 'B': 562 declaration.append("byte"); 563 break; 564 case 'J': 565 declaration.append("long"); 566 break; 567 case 'Z': 568 declaration.append("boolean"); 569 break; 570 case 'I': 571 declaration.append("int"); 572 break; 573 case 'S': 574 declaration.append("short"); 575 break; 576 case 'C': 577 declaration.append("char"); 578 break; 579 case 'F': 580 declaration.append("float"); 581 break; 582 // case 'D': 583 default: 584 declaration.append("double"); 585 break; 586 } 587 endType(); 588 } 589 590 /** 591 * Visits a signature corresponding to a type variable. 592 * 593 * @param name the name of the type variable. 594 */ 595 public void visitTypeVariable(final String name) { 596 if (DEBUG) System.out.println("visitTypeVariable " + name); 597 TypeVariableImpl t = new TypeVariableImpl(name); 598 typeVariables.add(t); 599 stack.push(t); 600 declaration.append(name); 601 endType(); 602 } 603 604 /** 605 * Visits a signature corresponding to an array type. 606 * 607 * @return a non null visitor to visit the signature of the array element 608 * type. 609 */ 610 public SignatureVisitor visitArrayType() { 611 startType(); 612 arrayStack |= 1; 613 return this; 614 } 615 616 /** 617 * Starts the visit of a signature corresponding to a class or interface 618 * type. 619 * 620 * @param name the internal name of the class or interface. 621 */ 622 public void visitClassType(final String name) { 623 ClassTypeImpl t = new ClassTypeImpl(name.replace('/', '.')); 624 stack.push(t); 625 if (DEBUG) System.out.println("visitClassType " + name.replace('/', '.')); 626 627 if (!"java/lang/Object".equals(name)) { 628 declaration.append(separator).append(name.replace('/', '.')); 629 } else { 630 // Map<java.lang.Object,java.util.List> 631 // or 632 // abstract public V get(Object key); (seen in Dictionary.class) 633 // should have Object 634 // but java.lang.String extends java.lang.Object is unnecessary 635 boolean needObjectClass = argumentStack % 2 != 0 || seenParameter; 636 if (needObjectClass) { 637 declaration.append(separator).append(name.replace('/', '.')); 638 } 639 } 640 separator = ""; 641 argumentStack *= 2; 642 argumentStackPosition.push(stack.size()); 643 } 644 645 /** 646 * Visits an inner class. 647 * 648 * @param name the local name of the inner class in its enclosing class. 649 */ 650 public void visitInnerClassType(final String name) { 651 if (DEBUG) System.out.println("visitInnerClassType " + name); 652 if (argumentStack % 2 != 0) { 653 declaration.append('>'); 654 } 655 argumentStack /= 2; 656 argumentStackPosition.pop(); 657 declaration.append('.'); 658 declaration.append(separator).append(name.replace('/', '.')); 659 separator = ""; 660 argumentStack *= 2; 661 argumentStackPosition.push(stack.size()); 662 } 663 664 /** 665 * Visits an unbounded type argument of the last visited class or inner 666 * class type. 667 */ 668 public void visitTypeArgument() { 669 if (DEBUG) System.out.println("visitTypeArgument"); 670 if (argumentStack % 2 == 0) { 671 ++argumentStack; 672 declaration.append('<'); 673 } else { 674 declaration.append(", "); 675 } 676 declaration.append('?'); 677 } 678 679 /** 680 * Visits a type argument of the last visited class or inner class type. 681 * 682 * @param wildcard '+', '-' or '='. 683 * @return a non null visitor to visit the signature of the type argument. 684 */ 685 public SignatureVisitor visitTypeArgument(final char tag) { 686 if (argumentStack % 2 == 0) { 687 ++argumentStack; 688 declaration.append('<'); 689 } else { 690 declaration.append(", "); 691 } 692 693 if (tag == SignatureVisitor.EXTENDS) { 694 declaration.append("? extends "); 695 } else if (tag == SignatureVisitor.SUPER) { 696 declaration.append("? super "); 697 } 698 699 startType(); 700 return this; 701 } 702 703 /** 704 * Ends the visit of a signature corresponding to a class or interface type. 705 */ 706 public void visitEnd() { 707 if (DEBUG) System.out.println("visitEnd"); 708 if (DEBUG) System.out.println("\t" + declaration); 709 if (argumentStack % 2 != 0) { 710 int stackPos = argumentStackPosition.peek().intValue() - 1; 711 712 Type raw = stack.elementAt(stackPos); 713 Type owner = null; // FIXME 714 715 int l = stack.size() - stackPos - 1; 716 Type args[] = new Type[l]; 717 for(int i = l-1; i >= 0; i--) { 718 args[i] = stack.pop(); 719 } 720 stack.pop(); 721 ParameterizedTypeImpl t = new ParameterizedTypeImpl(owner, args, raw); 722 stack.push(t); 723 declaration.append('>'); 724 } 725 argumentStack /= 2; 726 argumentStackPosition.pop(); 727 endType(); 728 } 729 730 public String getDeclaration() { 731 return declaration.toString(); 732 } 733 734 public String getReturnType() { 735 return returnType == null ? null : returnType.toString(); 736 } 737 738 public String getExceptions() { 739 return exceptions == null ? null : exceptions.toString(); 740 } 741 742 // ----------------------------------------------- 743 744 private void endFormal() { 745 Type bounds[] = stack.toArray(new Type[stack.size()]); 746 stack.removeAllElements(); 747 formalTypeParameters.getLast().setBounds(bounds); 748 } 749 750 private void endGenericSuperclass() { 751 genericSuperclass = stack.pop(); 752 } 753 754 public void endParsing() { 755 if (!seenInterface) { 756 endGenericSuperclass(); 757 genericInterfaces = new Type[0]; 758 } else { 759 genericInterfaces = stack.toArray(new Type[stack.size()]); 760 stack.removeAllElements(); 761 for(Type t: genericInterfaces) { 762 if (t instanceof ParameterizedTypeImpl) { 763 ParameterizedTypeImpl p = (ParameterizedTypeImpl) t; 764 t = p.raw; 765 } 766 if (t instanceof ClassTypeImpl) { 767 ClassTypeImpl c = (ClassTypeImpl) t; 768 c.isInterface = true; 769 } 770 } 771 } 772 currentType.setTypeParameters(typeParameters); 773 for(TypeVariableImpl t: typeVariables) { 774 t.setGenericDeclaration(currentType); 775 } 776 } 777 778 private void endFormals() { 779 if (seenFormalParameter) { 780 endFormal(); 781 declaration.append('>'); 782 seenFormalParameter = false; 783 } 784 typeParameters = formalTypeParameters.toArray(new TypeVariable[formalTypeParameters.size()]); 785 } 786 787 private void startType() { 788 arrayStack *= 2; 789 } 790 791 private void endType() { 792 if (arrayStack % 2 != 0) { 793 while (arrayStack % 2 != 0) { 794 Type t = stack.pop(); 795 stack.push(new GenericArrayTypeImpl(t)); 796 arrayStack /= 2; 797 declaration.append("[]"); 798 } 799 } else { 800 arrayStack /= 2; 801 } 802 } 803 } 804 805 public static class ClassTypeImpl implements Type, GenericDeclaration { 806 private final String name; 807 private boolean isInterface; 808 private TypeVariable<?>[] typeParameters; 809 public ClassTypeImpl(String name) { 810 this.name = name; 811 isInterface = false; 812 } 813 public ClassTypeImpl(String name, boolean isInterface) { 814 this.name = name; 815 this.isInterface = isInterface; 816 } 817 public String toString() { return (isInterface?"interface ":"class ") + name; } 818 public TypeVariable<?>[] getTypeParameters() { 819 return typeParameters; 820 } 821 public void setTypeParameters(TypeVariable<?>[] typeParameters) { 822 this.typeParameters = typeParameters; 823 } 824 } 825 826 public static class GenericArrayTypeImpl implements GenericArrayType { 827 public GenericArrayTypeImpl(Type genericComponentType) { 828 this.genericComponentType = genericComponentType; 829 } 830 private Type genericComponentType; 831 public Type getGenericComponentType() throws TypeNotPresentException, MalformedParameterizedTypeException { 832 return genericComponentType; 833 } 834 } 835 836 public static class ParameterizedTypeImpl implements ParameterizedType { 837 public ParameterizedTypeImpl(Type owner, Type args[], Type raw) { 838 this.owner = owner; 839 this.args = args; 840 this.raw = raw; 841 } 842 private Type owner, args[], raw; 843 844 public Type[] getActualTypeArguments() throws TypeNotPresentException, MalformedParameterizedTypeException { 845 return args; 846 } 847 public Type getOwnerType() { 848 return owner; 849 } 850 public Type getRawType() { 851 return raw; 852 } 853 public String toString() { 854 StringBuffer sb = new StringBuffer(); 855 String s = raw.toString(); 856 if (s.startsWith("class ")) { 857 s = s.substring(6); 858 } else if (s.startsWith("interface ")) { 859 s = s.substring(10); 860 } 861 sb.append(s); 862 if (args.length != 0) { 863 sb.append('<'); 864 boolean first = true; 865 for(Type t: args) { 866 if (!first) { 867 sb.append(", "); 868 } 869 first = false; 870 s = t.toString(); 871 if (s.startsWith("class ")) { 872 s = s.substring(6); 873 } 874 sb.append(s); 875 } 876 sb.append('>'); 877 } 878 return sb.toString(); 879 } 880 } 881 882 public static class TypeVariableImpl<D extends GenericDeclaration> implements TypeVariable { 883 private final String name; 884 885 public TypeVariableImpl(String name) { 886 this.name = name; 887 } 888 889 private Type[] bounds; 890 private D genericDeclaration; 891 892 protected void setBounds(Type[] bounds) { 893 this.bounds = bounds; 894 } 895 public Type[] getBounds() throws TypeNotPresentException, MalformedParameterizedTypeException { 896 return bounds; 897 } 898 899 protected void setGenericDeclaration(D d) { 900 genericDeclaration = d; 901 } 902 public D getGenericDeclaration() { 903 return genericDeclaration; 904 } 905 906 public String getName() { 907 return name; 908 } 909 910 public String toString() { return name; } 911 } 912 913 public static class WildcardTypeImpl implements WildcardType { 914 public Type[] getLowerBounds() throws TypeNotPresentException, MalformedParameterizedTypeException { 915 throw new UnsupportedOperationException("NotImplemented"); 916 } 917 918 public Type[] getUpperBounds() throws TypeNotPresentException, MalformedParameterizedTypeException { 919 throw new UnsupportedOperationException("NotImplemented"); 920 } 921 } 922 923 }