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 }