1 /***************************************************************************************
2 * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
3 * http://aspectwerkz.codehaus.org *
4 * ---------------------------------------------------------------------------------- *
5 * The software in this package is published under the terms of the LGPL license *
6 * a copy of which has been included with this distribution in the license.txt file. *
7 **************************************************************************************/
8 package org.codehaus.aspectwerkz.reflect.impl.asm;
9
10 import gnu.trove.TIntObjectHashMap;
11 import org.codehaus.aspectwerkz.annotation.instrumentation.asm.AsmAnnotationHelper;
12 import org.codehaus.aspectwerkz.annotation.AnnotationInfo;
13 import org.codehaus.aspectwerkz.annotation.Annotations;
14 import org.codehaus.aspectwerkz.annotation.TypedAnnotationProxy;
15 import org.codehaus.aspectwerkz.annotation.UntypedAnnotationProxy;
16 import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
17 import org.codehaus.aspectwerkz.reflect.ClassInfo;
18 import org.codehaus.aspectwerkz.reflect.ConstructorInfo;
19 import org.codehaus.aspectwerkz.reflect.FieldInfo;
20 import org.codehaus.aspectwerkz.reflect.MethodInfo;
21 import org.codehaus.aspectwerkz.reflect.impl.java.JavaClassInfo;
22 import org.codehaus.aspectwerkz.transform.AsmHelper;
23 import org.codehaus.aspectwerkz.transform.AsmHelper;
24 import org.objectweb.asm.Attribute;
25 import org.objectweb.asm.ClassAdapter;
26 import org.objectweb.asm.ClassReader;
27 import org.objectweb.asm.ClassVisitor;
28 import org.objectweb.asm.CodeVisitor;
29 import org.objectweb.asm.attrs.Annotation;
30
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.lang.ref.WeakReference;
34 import java.lang.reflect.Array;
35 import java.lang.reflect.Modifier;
36 import java.util.ArrayList;
37 import java.util.List;
38 import java.util.Iterator;
39
40 /***
41 * Implementation of the ClassInfo interface utilizing the ASM bytecode library for the info retriaval.
42 *
43 * Annotations are lazily gathered, unless required to visit them at the same time as we visit methods and fields.
44 *
45 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
46 * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
47 */
48 public class AsmClassInfo implements ClassInfo {
49
50 protected final static List EMPTY_LIST = new ArrayList();
51
52 private final static Attribute[] NO_ATTRIBUTES = new Attribute[0];
53
54 /***
55 * The class loader wrapped in a weak ref.
56 */
57 private final WeakReference m_loaderRef;
58
59 /***
60 * The name of the class.
61 */
62 private String m_name;
63
64 /***
65 * The modifiers.
66 */
67 private int m_modifiers;
68
69 /***
70 * Is the class an interface.
71 */
72 private boolean m_isInterface = false;
73
74 /***
75 * Is the class a primitive type.
76 */
77 private boolean m_isPrimitive = false;
78
79 /***
80 * Is the class of type array.
81 */
82 private boolean m_isArray = false;
83
84 /***
85 * A list with the <code>ConstructorInfo</code> instances.
86 */
87 private final TIntObjectHashMap m_constructors = new TIntObjectHashMap();
88
89 /***
90 * A list with the <code>MethodInfo</code> instances.
91 */
92 private final TIntObjectHashMap m_methods = new TIntObjectHashMap();
93
94 /***
95 * A list with the <code>FieldInfo</code> instances.
96 */
97 private final TIntObjectHashMap m_fields = new TIntObjectHashMap();
98
99 /***
100 * A list with the interfaces class names.
101 */
102 private String[] m_interfaceClassNames = null;
103
104 /***
105 * A list with the interfaces.
106 */
107 private ClassInfo[] m_interfaces = null;
108
109 /***
110 * The super class name.
111 */
112 private String m_superClassName = null;
113
114 /***
115 * The super class.
116 */
117 private ClassInfo m_superClass = null;
118
119 /***
120 * The annotations.
121 * Lasily populated.
122 */
123 private List m_annotations = null;
124
125 /***
126 * The component type name if array type.
127 */
128 private String m_componentTypeName = null;
129
130 /***
131 * The component type if array type.
132 */
133 private ClassInfo m_componentType = null;
134
135 /***
136 * The class info repository.
137 */
138 private final AsmClassInfoRepository m_classInfoRepository;
139
140 /***
141 * Creates a new ClassInfo instance.
142 *
143 * @param bytecode
144 * @param loader
145 */
146 AsmClassInfo(final byte[] bytecode, final ClassLoader loader, boolean lazyAttributes) {
147 if (bytecode == null) {
148 throw new IllegalArgumentException("bytecode can not be null");
149 }
150 m_loaderRef = new WeakReference(loader);
151 m_classInfoRepository = AsmClassInfoRepository.getRepository(loader);
152 try {
153 ClassReader cr = new ClassReader(bytecode);
154 ClassInfoClassAdapter visitor = new ClassInfoClassAdapter(
155 AsmAnnotationHelper.NULL_CLASS_VISITOR,
156 lazyAttributes
157 );
158 cr.accept(visitor, lazyAttributes?NO_ATTRIBUTES:AsmAnnotationHelper.ANNOTATIONS_ATTRIBUTES, true);
159 } catch (Throwable t) {
160 t.printStackTrace();
161 }
162 m_classInfoRepository.addClassInfo(this);
163 }
164
165 /***
166 * Creates a new ClassInfo instance.
167 *
168 * @param resourceStream
169 * @param loader
170 */
171 AsmClassInfo(final InputStream resourceStream, final ClassLoader loader) {
172 if (resourceStream == null) {
173 throw new IllegalArgumentException("resource stream can not be null");
174 }
175 m_loaderRef = new WeakReference(loader);
176 m_classInfoRepository = AsmClassInfoRepository.getRepository(loader);
177 try {
178 ClassReader cr = new ClassReader(resourceStream);
179 ClassInfoClassAdapter visitor = new ClassInfoClassAdapter(
180 AsmAnnotationHelper.NULL_CLASS_VISITOR,
181 true);
182 cr.accept(visitor, NO_ATTRIBUTES, true);
183 } catch (Throwable t) {
184 t.printStackTrace();
185 }
186 m_classInfoRepository.addClassInfo(this);
187 }
188
189 /***
190 * Create a ClassInfo based on a component type and a given dimension Due to java.lang.reflect. behavior, the
191 * ClassInfo is almost empty. It is not an interface, only subclass of java.lang.Object, no methods, fields, or
192 * constructor, no annotation.
193 *
194 * @param className
195 * @param loader
196 * @param componentInfo
197 * @param dimension
198 * @TODO: not sure it has to be abstract final but it looks like all reflect based are.
199 * @TODO: dimension param is not used
200 */
201 AsmClassInfo(final String className, final ClassLoader loader, final ClassInfo componentInfo, final int dimension) {
202 m_loaderRef = new WeakReference(loader);
203 m_name = className.replace('/', '.');
204 m_classInfoRepository = AsmClassInfoRepository.getRepository(loader);
205 m_isArray = true;
206 m_componentType = componentInfo;
207 m_componentTypeName = componentInfo.getName();
208 m_modifiers = componentInfo.getModifiers() | Modifier.ABSTRACT | Modifier.FINAL;
209 m_isInterface = false;
210 m_superClass = JavaClassInfo.getClassInfo(Object.class);
211 m_superClassName = m_superClass.getName();
212 m_interfaceClassNames = new String[0];
213 m_interfaces = new ClassInfo[0];
214 m_classInfoRepository.addClassInfo(this);
215 }
216
217 /***
218 * Returns the class info for a specific class.
219 *
220 * @param className
221 * @param loader
222 * @return the class info
223 */
224 public static ClassInfo getClassInfo(final String className, final ClassLoader loader) {
225 return getClassInfo(className, loader, true);
226 }
227
228 /***
229 * Returns the class info for a specific class.
230 *
231 * @param className
232 * @param loader
233 * @return the class info
234 */
235 public static ClassInfo getClassInfo(final String className, final ClassLoader loader, final boolean lazyAttributes) {
236 AsmClassInfoRepository repository = AsmClassInfoRepository.getRepository(loader);
237 ClassInfo classInfo = repository.getClassInfo(className);
238 if (classInfo == null) {
239 classInfo = createClassInfoFromStream(className, loader, lazyAttributes);
240 }
241 return classInfo;
242 }
243
244 /***
245 * Returns the class info for a specific class.
246 *
247 * @param bytecode
248 * @param loader
249 * @return the class info
250 */
251 public static ClassInfo getClassInfo(final byte[] bytecode, final ClassLoader loader) {
252 String className = AsmClassInfo.retrieveClassNameFromBytecode(bytecode);
253 AsmClassInfoRepository repository = AsmClassInfoRepository.getRepository(loader);
254 ClassInfo classInfo = repository.getClassInfo(className);
255 if (classInfo == null) {
256 classInfo = new AsmClassInfo(bytecode, loader, true);
257 }
258 return classInfo;
259 }
260
261 /***
262 * Returns the class info for a specific class.
263 *
264 * @param stream
265 * @param loader
266 * @return the class info
267 */
268 public static ClassInfo getClassInfo(final InputStream stream, final ClassLoader loader) {
269 try {
270 ClassReader cr = new ClassReader(stream);
271
272 byte[] bytes = cr.b;
273 ClassNameRetrievalClassAdapter visitor = new ClassNameRetrievalClassAdapter(
274 AsmAnnotationHelper.NULL_CLASS_VISITOR
275 );
276 cr.accept(visitor, NO_ATTRIBUTES, true);
277 String className = visitor.getClassName();
278 AsmClassInfoRepository repository = AsmClassInfoRepository.getRepository(loader);
279 ClassInfo classInfo = repository.getClassInfo(className);
280 if (classInfo == null) {
281 classInfo = new AsmClassInfo(bytes, loader, true);
282 }
283 return classInfo;
284 } catch (IOException e) {
285 throw new WrappedRuntimeException(e);
286 }
287 }
288
289 /***
290 * Returns the class info for a specific class.
291 *
292 * @param stream
293 * @param loader
294 * @param lazyAttributes
295 * @return the class info
296 */
297 public static ClassInfo getClassInfo(final InputStream stream, final ClassLoader loader, boolean lazyAttributes) {
298 if (lazyAttributes) {
299 return getClassInfo(stream, loader);
300 }
301 try {
302 ClassReader cr = new ClassReader(stream);
303
304 byte[] bytes = cr.b;
305 ClassNameRetrievalClassAdapter visitor = new ClassNameRetrievalClassAdapter(
306 AsmAnnotationHelper.NULL_CLASS_VISITOR
307 );
308 cr.accept(visitor, NO_ATTRIBUTES, true);
309 String className = visitor.getClassName();
310 AsmClassInfoRepository repository = AsmClassInfoRepository.getRepository(loader);
311 ClassInfo classInfo = repository.getClassInfo(className);
312 if (classInfo == null) {
313 classInfo = new AsmClassInfo(bytes, loader, lazyAttributes);
314 }
315 return classInfo;
316 } catch (IOException e) {
317 throw new WrappedRuntimeException(e);
318 }
319 }
320
321 /***
322 * Marks the class as dirty (since it has been modified and needs to be rebuild).
323 *
324 * @param className
325 */
326 public static void markDirty(final String className, final ClassLoader loader) {
327 AsmClassInfoRepository.getRepository(loader).removeClassInfo(className);
328 }
329
330 /***
331 * Retrieves the class name from the bytecode of a class.
332 *
333 * @param bytecode
334 * @return the class name
335 */
336 public static String retrieveClassNameFromBytecode(final byte[] bytecode) {
337 ClassReader cr = new ClassReader(bytecode);
338 ClassNameRetrievalClassAdapter visitor = new ClassNameRetrievalClassAdapter(
339 AsmAnnotationHelper.NULL_CLASS_VISITOR
340 );
341 cr.accept(visitor, NO_ATTRIBUTES, true);
342 return visitor.getClassName();
343 }
344
345 /***
346 * Checks if the class is a of a primitive type, if so create and return the class for the type else return null.
347 *
348 * @param className
349 * @return the class for the primitive type or null
350 */
351 public static Class getPrimitiveClass(final String className) {
352 if (className.equals("void")) {
353 return void.class;
354 } else if (className.equals("long")) {
355 return long.class;
356 } else if (className.equals("int")) {
357 return int.class;
358 } else if (className.equals("short")) {
359 return short.class;
360 } else if (className.equals("double")) {
361 return double.class;
362 } else if (className.equals("float")) {
363 return float.class;
364 } else if (className.equals("byte")) {
365 return byte.class;
366 } else if (className.equals("boolean")) {
367 return boolean.class;
368 } else if (className.equals("char")) {
369 return char.class;
370 } else {
371 return null;
372 }
373 }
374
375 /***
376 * Returns the annotations infos.
377 *
378 * @return the annotations infos
379 */
380 public List getAnnotations() {
381 if (m_annotations == null) {
382 if (isPrimitive() || isArray()) {
383 m_annotations = EMPTY_LIST;
384 } else {
385 try {
386 ClassReader cr = new ClassReader(((ClassLoader)m_loaderRef.get()).getResourceAsStream(m_name.replace('.','/')+".class"));
387 List annotations = new ArrayList();
388 cr.accept(
389 new AsmAnnotationHelper.ClassAnnotationExtractor(annotations, (ClassLoader)m_loaderRef.get()),
390 AsmAnnotationHelper.ANNOTATIONS_ATTRIBUTES,
391 true
392 );
393 m_annotations = annotations;
394 } catch (IOException e) {
395
396 System.err.println("WARN - could not load " + m_name + " as a resource to retrieve annotations");
397 m_annotations = EMPTY_LIST;
398 }
399 }
400 }
401 return m_annotations;
402 }
403
404 /***
405 * Returns the name of the class.
406 *
407 * @return the name of the class
408 */
409 public String getName() {
410 return m_name;
411 }
412
413 /***
414 * Returns the class modifiers.
415 *
416 * @return the class modifiers
417 */
418 public int getModifiers() {
419 return m_modifiers;
420 }
421
422 /***
423 * Returns a constructor info by its hash.
424 *
425 * @param hash
426 * @return
427 */
428 public ConstructorInfo getConstructor(final int hash) {
429 return (ConstructorInfo)m_constructors.get(hash);
430 }
431
432 /***
433 * Returns a list with all the constructors info.
434 *
435 * @return the constructors info
436 */
437 public ConstructorInfo[] getConstructors() {
438 Object[] values = m_constructors.getValues();
439 ConstructorInfo[] methodInfos = new ConstructorInfo[values.length];
440 for (int i = 0; i < values.length; i++) {
441 methodInfos[i] = (ConstructorInfo)values[i];
442 }
443 return methodInfos;
444 }
445
446 /***
447 * Returns a method info by its hash.
448 *
449 * @param hash
450 * @return
451 */
452 public MethodInfo getMethod(final int hash) {
453 return (MethodInfo)m_methods.get(hash);
454 }
455
456 /***
457 * Returns a list with all the methods info.
458 *
459 * @return the methods info
460 */
461 public MethodInfo[] getMethods() {
462 Object[] values = m_methods.getValues();
463 MethodInfo[] methodInfos = new MethodInfo[values.length];
464 for (int i = 0; i < values.length; i++) {
465 methodInfos[i] = (MethodInfo)values[i];
466 }
467 return methodInfos;
468 }
469
470 /***
471 * Returns a field info by its hash.
472 *
473 * @param hash
474 * @return
475 */
476 public FieldInfo getField(final int hash) {
477 return (FieldInfo)m_fields.get(hash);
478 }
479
480 /***
481 * Returns a list with all the field info.
482 *
483 * @return the field info
484 */
485 public FieldInfo[] getFields() {
486 Object[] values = m_fields.getValues();
487 FieldInfo[] fieldInfos = new FieldInfo[values.length];
488 for (int i = 0; i < values.length; i++) {
489 fieldInfos[i] = (FieldInfo)values[i];
490 }
491 return fieldInfos;
492 }
493
494 /***
495 * Returns the interfaces.
496 *
497 * @return the interfaces
498 */
499 public ClassInfo[] getInterfaces() {
500 if (m_interfaces == null) {
501 m_interfaces = new ClassInfo[m_interfaceClassNames.length];
502 for (int i = 0; i < m_interfaceClassNames.length; i++) {
503 m_interfaces[i] = AsmClassInfo.getClassInfo(m_interfaceClassNames[i], (ClassLoader)m_loaderRef.get());
504 }
505 }
506 return m_interfaces;
507 }
508
509 /***
510 * Returns the super class.
511 *
512 * @return the super class
513 */
514 public ClassInfo getSuperClass() {
515 if (m_superClass == null && m_superClassName != null) {
516 m_superClass = AsmClassInfo.getClassInfo(m_superClassName, (ClassLoader)m_loaderRef.get());
517 }
518 return m_superClass;
519 }
520
521 /***
522 * Returns the component type if array type else null.
523 *
524 * @return the component type
525 */
526 public ClassInfo getComponentType() {
527 if (isArray() && (m_componentTypeName == null)) {
528 m_componentType = AsmClassInfo.getClassInfo(m_componentTypeName, (ClassLoader)m_loaderRef.get());
529 }
530 return m_componentType;
531 }
532
533 /***
534 * Is the class an interface.
535 *
536 * @return
537 */
538 public boolean isInterface() {
539 return m_isInterface;
540 }
541
542 /***
543 * Is the class a primitive type.
544 *
545 * @return
546 */
547 public boolean isPrimitive() {
548 return m_isPrimitive;
549 }
550
551 /***
552 * Is the class an array type.
553 *
554 * @return
555 */
556 public boolean isArray() {
557 return m_isArray;
558 }
559
560 /***
561 * @see java.lang.Object#equals(java.lang.Object)
562 */
563 public boolean equals(Object o) {
564 if (this == o) {
565 return true;
566 }
567 if (!(o instanceof ClassInfo)) {
568 return false;
569 }
570 ClassInfo classInfo = (ClassInfo)o;
571 return m_name.equals(classInfo.getName());
572 }
573
574 /***
575 * @see java.lang.Object#hashCode()
576 */
577 public int hashCode() {
578 return m_name.hashCode();
579 }
580
581 public String toString() {
582 return m_name;
583 }
584
585 /***
586 * Create a ClassInfo based on a component type and a given dimension
587 *
588 * @param className
589 * @param loader
590 * @param componentClassInfo
591 * @param dimension
592 * @return
593 */
594 public static ClassInfo getArrayClassInfo(
595 final String className,
596 final ClassLoader loader,
597 final ClassInfo componentClassInfo,
598 final int dimension) {
599 if (dimension <= 1) {
600 return componentClassInfo;
601 }
602 return new AsmClassInfo(className, loader, componentClassInfo, dimension);
603 }
604
605 /***
606 * Creates a ClassInfo based on the stream retrieved from the class loader through
607 * <code>getResourceAsStream</code>.
608 *
609 * @param className
610 * @param loader
611 * @param lazyAttributes
612 */
613 private static ClassInfo createClassInfoFromStream(String className, final ClassLoader loader, boolean lazyAttributes) {
614 className = className.replace('.', '/');
615
616
617 int componentTypeIndex = className.indexOf('[');
618 String componentName = className;
619 int dimension = 1;
620 if (componentTypeIndex > 0) {
621 componentName = className.substring(0, componentTypeIndex);
622 dimension = 1 + (className.length() - componentTypeIndex) / 2;
623 }
624
625
626 if (componentName.indexOf('/') < 0) {
627
628 Class primitiveClass = AsmClassInfo.getPrimitiveClass(componentName);
629 if (primitiveClass != null) {
630 if (dimension <= 1) {
631 return JavaClassInfo.getClassInfo(primitiveClass);
632 } else {
633 Class arrayClass = Array.newInstance(primitiveClass, dimension).getClass();
634 return JavaClassInfo.getClassInfo(arrayClass);
635 }
636 }
637 }
638
639
640 InputStream componentClassAsStream = null;
641 if (loader != null) {
642 componentClassAsStream = loader.getResourceAsStream(componentName + ".class");
643 } else {
644
645 componentClassAsStream = ClassLoader.getSystemClassLoader().getResourceAsStream(componentName + ".class");
646 }
647 if (componentClassAsStream == null) {
648 new RuntimeException(
649 "could not load class ["
650 + componentName
651 + "] as a resource in loader ["
652 + loader
653 + "]"
654 ).printStackTrace();
655 return new ClassInfo.NullClassInfo();
656 }
657 ClassInfo componentInfo = null;
658 try {
659 componentInfo = AsmClassInfo.getClassInfo(componentClassAsStream, loader, lazyAttributes);
660 } finally {
661 try {
662 componentClassAsStream.close();
663 } catch (Exception e) {
664 ;
665 }
666 }
667
668 if (dimension <= 1) {
669 return componentInfo;
670 } else {
671 return AsmClassInfo.getArrayClassInfo(className, loader, componentInfo, dimension);
672 }
673 }
674
675 /***
676 * Creates and returns a new annotation info build up from the Java5 annotation.
677 *
678 * @param annotation the ASM annotation abstractiono
679 * @param loader the class loader that has loaded the proxy class to use
680 * @return the annotation info
681 */
682 public static AnnotationInfo getAnnotationInfo(final Annotation annotation, final ClassLoader loader) {
683 String annotationName = annotation.type.substring(1, annotation.type.length() - 1).replace('/', '.');
684 String annotationValues = createAnnotationKeyValueString(annotation);
685
686 Class proxyClass = Annotations.getProxyClass(annotationName, loader);
687 org.codehaus.aspectwerkz.annotation.Annotation proxy;
688 if (proxyClass == null) {
689 proxy = new UntypedAnnotationProxy();
690 } else {
691 try {
692 proxy = (TypedAnnotationProxy)proxyClass.newInstance();
693 } catch (Exception e) {
694 throw new WrappedRuntimeException(e);
695 }
696 }
697 proxy.initialize(annotationName, annotationValues);
698 return new AnnotationInfo(annotationName, proxy);
699 }
700
701 /***
702 * Creates a string with the annotation key value pairs.
703 *
704 * @param annotation
705 * @return the string
706 */
707 private static String createAnnotationKeyValueString(final Annotation annotation) {
708 List elementValues = annotation.elementValues;
709 StringBuffer annotationValues = new StringBuffer();
710 if (elementValues.size() != 0) {
711 int i = 0;
712 for (Iterator iterator = elementValues.iterator(); iterator.hasNext();) {
713 Object[] keyValuePair = (Object[])iterator.next();
714 annotationValues.append((String)keyValuePair[0]);
715 annotationValues.append('=');
716 annotationValues.append(keyValuePair[1].toString());
717 if (i < elementValues.size() - 1) {
718 annotationValues.append(',');
719 }
720 }
721 }
722 return annotationValues.toString();
723 }
724
725 /***
726 * ASM bytecode visitor that retrieves the class name from the bytecode.
727 *
728 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
729 */
730 public static class ClassNameRetrievalClassAdapter extends ClassAdapter {
731
732 private String m_className;
733
734 public ClassNameRetrievalClassAdapter(final ClassVisitor visitor) {
735 super(visitor);
736 }
737
738 public void visit(
739 final int version,
740 final int access,
741 final String name,
742 final String superName,
743 final String[] interfaces,
744 final String sourceFile) {
745 m_className = name.replace('/', '.');
746 super.visit(version, access, name, superName, interfaces, sourceFile);
747 }
748
749 public String getClassName() {
750 return m_className;
751 }
752 }
753
754 /***
755 * ASM bytecode visitor that gathers info about the class.
756 *
757 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
758 */
759 private class ClassInfoClassAdapter extends ClassAdapter {
760 private static final String CLINIT_METHOD_NAME = "<clinit>";
761 private static final String INIT_METHOD_NAME = "<init>";
762
763 public boolean m_lazyAttributes = true;
764
765 public ClassInfoClassAdapter(final ClassVisitor visitor, boolean lazyAttributes) {
766 super(visitor);
767 m_lazyAttributes = lazyAttributes;
768 }
769
770 public void visit(
771 final int version,
772 final int access,
773 final String name,
774 final String superName,
775 final String[] interfaces,
776 final String sourceFile) {
777 m_name = name.replace('/', '.');
778 m_modifiers = access;
779
780 m_superClassName = superName == null ? null : superName.replace('/', '.');
781 m_interfaceClassNames = new String[interfaces.length];
782 for (int i = 0; i < interfaces.length; i++) {
783 m_interfaceClassNames[i] = interfaces[i].replace('/', '.');
784 }
785
786
787
788 if (m_name.endsWith("[]")) {
789 m_isArray = true;
790 int index = m_name.indexOf('[');
791 m_componentTypeName = m_name.substring(0, index);
792 } else if (m_name.equals("long")
793 || m_name.equals("int")
794 || m_name.equals("short")
795 || m_name.equals("double")
796 || m_name.equals("float")
797 || m_name.equals("byte")
798 || m_name.equals("boolean")
799 || m_name.equals("char")) {
800 m_isPrimitive = true;
801 }
802 super.visit(version, access, name, superName, interfaces, sourceFile);
803 }
804
805 public void visitAttribute(final Attribute attribute) {
806
807 if (!m_lazyAttributes) {
808 List annotations = new ArrayList();
809 annotations = AsmAnnotationHelper.extractAnnotations(annotations, attribute, (ClassLoader)m_loaderRef.get());
810 m_annotations = annotations;
811 }
812 super.visitAttribute(attribute);
813 }
814
815 public void visitField(
816 final int access,
817 final String name,
818 final String desc,
819 final Object value,
820 final Attribute attrs) {
821 final FieldStruct struct = new FieldStruct();
822 struct.modifiers = access;
823 struct.name = name;
824 struct.desc = desc;
825 struct.value = value;
826 AsmFieldInfo fieldInfo = new AsmFieldInfo(struct, m_name, (ClassLoader)m_loaderRef.get());
827
828 if (!m_lazyAttributes) {
829 List annotations = new ArrayList();
830 annotations = AsmAnnotationHelper.extractAnnotations(annotations, attrs, (ClassLoader)m_loaderRef.get());
831 fieldInfo.m_annotations = annotations;
832 }
833 m_fields.put(AsmHelper.calculateFieldHash(name, desc), fieldInfo);
834 super.visitField(access, name, desc, value, attrs);
835 }
836
837 public CodeVisitor visitMethod(
838 final int access,
839 final String name,
840 final String desc,
841 final String[] exceptions,
842 final Attribute attrs) {
843 final MethodStruct struct = new MethodStruct();
844 struct.modifiers = access;
845 struct.name = name;
846 struct.desc = desc;
847 struct.exceptions = exceptions;
848 int hash = AsmHelper.calculateMethodHash(name, desc);
849 if (name.equals(CLINIT_METHOD_NAME)) {
850
851 } else {
852 AsmMemberInfo memberInfo = null;
853 if (name.equals(INIT_METHOD_NAME)) {
854 memberInfo = new AsmConstructorInfo(struct, m_name, (ClassLoader)m_loaderRef.get());
855 m_constructors.put(hash, memberInfo);
856 } else {
857 memberInfo = new AsmMethodInfo(struct, m_name, (ClassLoader)m_loaderRef.get());
858 m_methods.put(hash, memberInfo);
859 }
860
861 if (!m_lazyAttributes) {
862 List annotations = new ArrayList();
863 annotations = AsmAnnotationHelper.extractAnnotations(annotations, attrs, (ClassLoader)m_loaderRef.get());
864 memberInfo.m_annotations = annotations;
865 }
866 }
867
868 return super.visitMethod(access, name, desc, exceptions, attrs);
869 }
870
871 }
872
873 }