Source Code Cross Referenced for AsmClassInfo.java in  » Aspect-oriented » aspectwerkz-2.0 » org » codehaus » aspectwerkz » reflect » impl » asm » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Aspect oriented » aspectwerkz 2.0 » org.codehaus.aspectwerkz.reflect.impl.asm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**************************************************************************************
0002:         * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved.                 *
0003:         * http://aspectwerkz.codehaus.org                                                    *
0004:         * ---------------------------------------------------------------------------------- *
0005:         * The software in this package is published under the terms of the LGPL license      *
0006:         * a copy of which has been included with this distribution in the license.txt file.  *
0007:         **************************************************************************************/package org.codehaus.aspectwerkz.reflect.impl.asm;
0008:
0009:        import gnu.trove.TIntObjectHashMap;
0010:        import gnu.trove.TIntArrayList;
0011:        import org.codehaus.aspectwerkz.annotation.instrumentation.asm.AsmAnnotationHelper;
0012:        import org.codehaus.aspectwerkz.annotation.AnnotationInfo;
0013:        import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
0014:        import org.codehaus.aspectwerkz.reflect.ClassInfo;
0015:        import org.codehaus.aspectwerkz.reflect.ConstructorInfo;
0016:        import org.codehaus.aspectwerkz.reflect.FieldInfo;
0017:        import org.codehaus.aspectwerkz.reflect.MethodInfo;
0018:        import org.codehaus.aspectwerkz.reflect.StaticInitializationInfo;
0019:        import org.codehaus.aspectwerkz.reflect.StaticInitializationInfoImpl;
0020:        import org.codehaus.aspectwerkz.reflect.impl.java.JavaClassInfo;
0021:        import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
0022:        import org.codehaus.aspectwerkz.transform.TransformationConstants;
0023:        import org.codehaus.aspectwerkz.proxy.ProxyCompiler;
0024:        import org.objectweb.asm.Attribute;
0025:        import org.objectweb.asm.ClassReader;
0026:        import org.objectweb.asm.CodeVisitor;
0027:        import org.objectweb.asm.Label;
0028:        import org.objectweb.asm.Type;
0029:        import org.objectweb.asm.attrs.Annotation;
0030:        import org.objectweb.asm.attrs.Attributes;
0031:
0032:        import java.io.IOException;
0033:        import java.io.InputStream;
0034:        import java.lang.ref.WeakReference;
0035:        import java.lang.reflect.Array;
0036:        import java.lang.reflect.Modifier;
0037:        import java.util.ArrayList;
0038:        import java.util.List;
0039:        import java.util.Iterator;
0040:
0041:        /**
0042:         * Implementation of the ClassInfo interface utilizing the ASM bytecode library for the info retriaval.
0043:         * <p/>
0044:         * Annotations are lazily gathered, unless required to visit them at the same time as we visit methods and fields.
0045:         * <p/>
0046:         * This implementation guarantees that the method, fields and constructors can be retrieved in the same order as they were in the bytecode
0047:         * (it can depends of the compiler and might not be the order of the source code - f.e. IBM compiler)
0048:         *
0049:         * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
0050:         * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
0051:         */
0052:        public class AsmClassInfo implements  ClassInfo {
0053:
0054:            protected final static String[] EMPTY_STRING_ARRAY = new String[0];
0055:
0056:            protected final static List EMPTY_LIST = new ArrayList();
0057:
0058:            private final static Attribute[] NO_ATTRIBUTES = new Attribute[0];
0059:
0060:            /**
0061:             * The class loader wrapped in a weak ref.
0062:             */
0063:            private final WeakReference m_loaderRef;
0064:
0065:            /**
0066:             * The name of the class (with dots and not slashes)
0067:             */
0068:            private String m_name;
0069:
0070:            /**
0071:             * The signature of the class.
0072:             */
0073:            private String m_signature;
0074:
0075:            /**
0076:             * The modifiers.
0077:             */
0078:            private int m_modifiers;
0079:
0080:            /**
0081:             * Is the class an interface.
0082:             */
0083:            private boolean m_isInterface = false;
0084:
0085:            /**
0086:             * Is the class a primitive type.
0087:             */
0088:            private boolean m_isPrimitive = false;
0089:
0090:            /**
0091:             * Is the class of type array.
0092:             */
0093:            private boolean m_isArray = false;
0094:
0095:            /**
0096:             * Flag for the static initializer method.
0097:             */
0098:            private boolean m_hasStaticInitializer = false;
0099:
0100:            /**
0101:             * Lazy instance that represents the static initializer if present, else null
0102:             */
0103:            private StaticInitializationInfo m_staticInitializer = null;
0104:
0105:            /**
0106:             * A list with the <code>ConstructorInfo</code> instances.
0107:             * When visiting the bytecode, we keep track of the order of the visit.
0108:             * The first time the getConstructors() gets called, we build an array and then reuse it directly.
0109:             */
0110:            private final TIntObjectHashMap m_constructors = new TIntObjectHashMap();
0111:            private TIntArrayList m_sortedConstructorHashes = new TIntArrayList();
0112:            private ConstructorInfo[] m_constructorsLazy = null;
0113:
0114:            /**
0115:             * A list with the <code>MethodInfo</code> instances.
0116:             * When visiting the bytecode, we keep track of the order of the visit.
0117:             * The first time the getMethods() gets called, we build an array and then reuse it directly.
0118:             */
0119:            private final TIntObjectHashMap m_methods = new TIntObjectHashMap();
0120:            private TIntArrayList m_sortedMethodHashes = new TIntArrayList();
0121:            private MethodInfo[] m_methodsLazy = null;
0122:
0123:            /**
0124:             * A list with the <code>FieldInfo</code> instances.
0125:             * When visiting the bytecode, we keep track of the order of the visit.
0126:             * The first time the getFields() gets called, we build an array and then reuse it directly.
0127:             */
0128:            private final TIntObjectHashMap m_fields = new TIntObjectHashMap();
0129:            private TIntArrayList m_sortedFieldHashes = new TIntArrayList();
0130:            private FieldInfo[] m_fieldsLazy = null;
0131:
0132:            /**
0133:             * A list with the interfaces class names.
0134:             */
0135:            private String[] m_interfaceClassNames = null;
0136:
0137:            /**
0138:             * A list with the interfaces.
0139:             */
0140:            private ClassInfo[] m_interfaces = null;
0141:
0142:            /**
0143:             * The super class name.
0144:             */
0145:            private String m_super ClassName = null;
0146:
0147:            /**
0148:             * The super class.
0149:             */
0150:            private ClassInfo m_super Class = null;
0151:
0152:            /**
0153:             * The annotations.
0154:             * Lazily populated.
0155:             */
0156:            private List m_annotations = null;
0157:
0158:            /**
0159:             * The component type name if array type. Can be an array itself.
0160:             */
0161:            private String m_componentTypeName = null;
0162:
0163:            /**
0164:             * The component type if array type. Can be an array itself.
0165:             */
0166:            private ClassInfo m_componentType = null;
0167:
0168:            /**
0169:             * The class info repository.
0170:             */
0171:            private final AsmClassInfoRepository m_classInfoRepository;
0172:
0173:            /**
0174:             * Creates a new ClassInfo instance.
0175:             *
0176:             * @param bytecode
0177:             * @param loader
0178:             */
0179:            AsmClassInfo(final byte[] bytecode, final ClassLoader loader,
0180:                    boolean lazyAttributes) {
0181:                if (bytecode == null) {
0182:                    throw new IllegalArgumentException(
0183:                            "bytecode can not be null");
0184:                }
0185:                m_loaderRef = new WeakReference(loader);
0186:                m_classInfoRepository = AsmClassInfoRepository
0187:                        .getRepository(loader);
0188:                try {
0189:                    ClassReader cr = new ClassReader(bytecode);
0190:                    ClassInfoClassAdapter visitor = new ClassInfoClassAdapter(
0191:                            lazyAttributes);
0192:                    cr.accept(visitor, lazyAttributes ? NO_ATTRIBUTES
0193:                            : Attributes.getDefaultAttributes(), false);
0194:                } catch (Throwable t) {
0195:                    t.printStackTrace();
0196:                }
0197:                m_classInfoRepository.addClassInfo(this );
0198:            }
0199:
0200:            /**
0201:             * Creates a new ClassInfo instance.
0202:             *
0203:             * @param resourceStream
0204:             * @param loader
0205:             */
0206:            AsmClassInfo(final InputStream resourceStream,
0207:                    final ClassLoader loader) {
0208:                if (resourceStream == null) {
0209:                    throw new IllegalArgumentException(
0210:                            "resource stream can not be null");
0211:                }
0212:                m_loaderRef = new WeakReference(loader);
0213:                m_classInfoRepository = AsmClassInfoRepository
0214:                        .getRepository(loader);
0215:                try {
0216:                    ClassReader cr = new ClassReader(resourceStream);
0217:                    ClassInfoClassAdapter visitor = new ClassInfoClassAdapter(
0218:                            true);
0219:                    cr.accept(visitor, NO_ATTRIBUTES, false);
0220:                } catch (Throwable t) {
0221:                    t.printStackTrace();
0222:                }
0223:                m_classInfoRepository.addClassInfo(this );
0224:            }
0225:
0226:            /**
0227:             * Create a ClassInfo based on a component type and a given dimension Due to java.lang.reflect. behavior, the
0228:             * ClassInfo is almost empty. It is not an interface, only subclass of java.lang.Object, no methods, fields, or
0229:             * constructor, no annotation.
0230:             *
0231:             * @param className
0232:             * @param loader
0233:             * @param componentInfo
0234:             */
0235:            AsmClassInfo(final String className, final ClassLoader loader,
0236:                    final ClassInfo componentInfo) {
0237:                m_loaderRef = new WeakReference(loader);
0238:                m_name = className.replace('/', '.');
0239:                m_classInfoRepository = AsmClassInfoRepository
0240:                        .getRepository(loader);
0241:                m_isArray = true;
0242:                m_componentType = componentInfo;
0243:                m_componentTypeName = componentInfo.getName();
0244:                m_modifiers = componentInfo.getModifiers() | Modifier.ABSTRACT
0245:                        | Modifier.FINAL;
0246:                m_isInterface = false;//as in java.reflect
0247:                m_super Class = JavaClassInfo.getClassInfo(Object.class);
0248:                m_super ClassName = m_super Class.getName();
0249:                m_interfaceClassNames = new String[0];
0250:                m_interfaces = new ClassInfo[0];
0251:                m_signature = AsmHelper.getClassDescriptor(this );
0252:                m_classInfoRepository.addClassInfo(this );
0253:            }
0254:
0255:            /**
0256:             * Returns a completely new class info for a specific class. Does not cache.
0257:             *
0258:             * @param bytecode
0259:             * @param loader
0260:             * @return the class info
0261:             */
0262:            public static ClassInfo newClassInfo(final byte[] bytecode,
0263:                    final ClassLoader loader) {
0264:                final String className = AsmClassInfo
0265:                        .retrieveClassNameFromBytecode(bytecode);
0266:                AsmClassInfoRepository repository = AsmClassInfoRepository
0267:                        .getRepository(loader);
0268:                repository.removeClassInfo(className);
0269:                return new AsmClassInfo(bytecode, loader, true);
0270:            }
0271:
0272:            /**
0273:             * Returns the class info for a specific class.
0274:             *
0275:             * @param className
0276:             * @param loader
0277:             * @return the class info
0278:             */
0279:            public static ClassInfo getClassInfo(final String className,
0280:                    final ClassLoader loader) {
0281:                final String javaClassName = getJavaClassName(className);
0282:                AsmClassInfoRepository repository = AsmClassInfoRepository
0283:                        .getRepository(loader);
0284:                ClassInfo classInfo = repository.getClassInfo(javaClassName);
0285:                if (classInfo == null) {
0286:                    classInfo = createClassInfoFromStream(javaClassName,
0287:                            loader, true);
0288:                }
0289:                return classInfo;
0290:            }
0291:
0292:            /**
0293:             * Returns the class info for a specific class.
0294:             *
0295:             * @param bytecode
0296:             * @param loader
0297:             * @return the class info
0298:             */
0299:            public static ClassInfo getClassInfo(final byte[] bytecode,
0300:                    final ClassLoader loader) {
0301:                final String className = AsmClassInfo
0302:                        .retrieveClassNameFromBytecode(bytecode);
0303:                AsmClassInfoRepository repository = AsmClassInfoRepository
0304:                        .getRepository(loader);
0305:                ClassInfo classInfo = repository.getClassInfo(className);
0306:                if (classInfo == null) {
0307:                    classInfo = new AsmClassInfo(bytecode, loader, true);
0308:                }
0309:                return classInfo;
0310:            }
0311:
0312:            /**
0313:             * Returns the class info for a specific class.
0314:             *
0315:             * @param stream
0316:             * @param loader
0317:             * @return the class info
0318:             */
0319:            public static ClassInfo getClassInfo(final InputStream stream,
0320:                    final ClassLoader loader) {
0321:                try {
0322:                    ClassReader cr = new ClassReader(stream);
0323:                    // keep a copy of the bytecode, since me way want to "reuse the stream"
0324:                    byte[] bytes = cr.b;
0325:                    ClassNameRetrievalClassAdapter visitor = new ClassNameRetrievalClassAdapter();
0326:                    cr.accept(visitor, NO_ATTRIBUTES, true);
0327:                    final String className = visitor.getClassName();
0328:                    AsmClassInfoRepository repository = AsmClassInfoRepository
0329:                            .getRepository(loader);
0330:                    ClassInfo classInfo = repository.getClassInfo(className);
0331:                    if (classInfo == null) {
0332:                        classInfo = new AsmClassInfo(bytes, loader, true);
0333:                    }
0334:                    return classInfo;
0335:                } catch (IOException e) {
0336:                    throw new WrappedRuntimeException(e);
0337:                }
0338:            }
0339:
0340:            /**
0341:             * Returns the class info for a specific class.
0342:             *
0343:             * @param stream
0344:             * @param loader
0345:             * @param lazyAttributes
0346:             * @return the class info
0347:             */
0348:            public static ClassInfo getClassInfo(final InputStream stream,
0349:                    final ClassLoader loader, boolean lazyAttributes) {
0350:                if (lazyAttributes) {
0351:                    return getClassInfo(stream, loader);
0352:                }
0353:                try {
0354:                    ClassReader cr = new ClassReader(stream);
0355:                    // keep a copy of the bytecode, since me way want to "reuse the stream"
0356:                    byte[] bytes = cr.b;
0357:                    ClassNameRetrievalClassAdapter visitor = new ClassNameRetrievalClassAdapter();
0358:                    cr.accept(visitor, NO_ATTRIBUTES, true);
0359:                    String className = visitor.getClassName();
0360:                    AsmClassInfoRepository repository = AsmClassInfoRepository
0361:                            .getRepository(loader);
0362:                    ClassInfo classInfo = repository.getClassInfo(className);
0363:                    if (classInfo == null) {
0364:                        classInfo = new AsmClassInfo(bytes, loader,
0365:                                lazyAttributes);
0366:                    }
0367:                    return classInfo;
0368:                } catch (IOException e) {
0369:                    throw new WrappedRuntimeException(e);
0370:                }
0371:            }
0372:
0373:            /**
0374:             * Marks the class as dirty (since it has been modified and needs to be rebuild).
0375:             *
0376:             * @param className
0377:             */
0378:            public static void markDirty(final String className,
0379:                    final ClassLoader loader) {
0380:                AsmClassInfoRepository.getRepository(loader).removeClassInfo(
0381:                        className);
0382:            }
0383:
0384:            /**
0385:             * Retrieves the class name from the bytecode of a class.
0386:             *
0387:             * @param bytecode
0388:             * @return the class name
0389:             */
0390:            public static String retrieveClassNameFromBytecode(
0391:                    final byte[] bytecode) {
0392:                ClassReader cr = new ClassReader(bytecode);
0393:                ClassNameRetrievalClassAdapter visitor = new ClassNameRetrievalClassAdapter();
0394:                cr.accept(visitor, NO_ATTRIBUTES, true);
0395:                return visitor.getClassName();
0396:            }
0397:
0398:            /**
0399:             * Checks if the class is a of a primitive type, if so create and return the class for the type else return null.
0400:             *
0401:             * @param className
0402:             * @return the class for the primitive type or null
0403:             */
0404:            public static Class getPrimitiveClass(final String className) {
0405:                if (className.equals("void")) {
0406:                    return void.class;
0407:                } else if (className.equals("long")) {
0408:                    return long.class;
0409:                } else if (className.equals("int")) {
0410:                    return int.class;
0411:                } else if (className.equals("short")) {
0412:                    return short.class;
0413:                } else if (className.equals("double")) {
0414:                    return double.class;
0415:                } else if (className.equals("float")) {
0416:                    return float.class;
0417:                } else if (className.equals("byte")) {
0418:                    return byte.class;
0419:                } else if (className.equals("boolean")) {
0420:                    return boolean.class;
0421:                } else if (className.equals("char")) {
0422:                    return char.class;
0423:                } else {
0424:                    return null;
0425:                }
0426:            }
0427:
0428:            /**
0429:             * Returns the annotations infos.
0430:             *
0431:             * @return the annotations infos
0432:             */
0433:            public List getAnnotations() {
0434:                if (m_annotations == null) {
0435:                    if (isPrimitive() || isArray()) {
0436:                        m_annotations = EMPTY_LIST;
0437:                    } else {
0438:                        try {
0439:                            InputStream in = null;
0440:                            ClassReader cr = null;
0441:                            try {
0442:                                if ((ClassLoader) m_loaderRef.get() != null) {
0443:                                    in = ((ClassLoader) m_loaderRef.get())
0444:                                            .getResourceAsStream(m_name
0445:                                                    .replace('.', '/')
0446:                                                    + ".class");
0447:                                } else {
0448:                                    in = ClassLoader.getSystemClassLoader()
0449:                                            .getResourceAsStream(
0450:                                                    m_name.replace('.', '/')
0451:                                                            + ".class");
0452:                                }
0453:                                if (in == null) {
0454:                                    in = ProxyCompiler
0455:                                            .getProxyResourceAsStream(
0456:                                                    (ClassLoader) m_loaderRef
0457:                                                            .get(), m_name);
0458:                                }
0459:                                cr = new ClassReader(in);
0460:                            } finally {
0461:                                try {
0462:                                    in.close();
0463:                                } catch (Exception e) {
0464:                                    ;
0465:                                }
0466:                            }
0467:                            List annotations = new ArrayList();
0468:                            cr
0469:                                    .accept(
0470:                                            new AsmAnnotationHelper.ClassAnnotationExtractor(
0471:                                                    annotations,
0472:                                                    (ClassLoader) m_loaderRef
0473:                                                            .get()), Attributes
0474:                                                    .getDefaultAttributes(),
0475:                                            true);
0476:                            m_annotations = annotations;
0477:                        } catch (IOException e) {
0478:                            // unlikely to occur since ClassInfo relies on getResourceAsStream
0479:                            System.err.println("AW::WARNING  could not load "
0480:                                    + m_name
0481:                                    + " as a resource to retrieve annotations");
0482:                            m_annotations = EMPTY_LIST;
0483:                        }
0484:                    }
0485:                }
0486:                return m_annotations;
0487:            }
0488:
0489:            /**
0490:             * Returns the name of the class.
0491:             *
0492:             * @return the name of the class
0493:             */
0494:            public String getName() {
0495:                return m_name;
0496:            }
0497:
0498:            /**
0499:             * Returns the signature for the class.
0500:             *
0501:             * @return the signature for the class
0502:             */
0503:            public String getSignature() {
0504:                return m_signature;
0505:            }
0506:
0507:            /**
0508:             * Returns the class modifiers.
0509:             *
0510:             * @return the class modifiers
0511:             */
0512:            public int getModifiers() {
0513:                return m_modifiers;
0514:            }
0515:
0516:            /**
0517:             * Returns the class loader that loaded this class.
0518:             *
0519:             * @return the class loader
0520:             */
0521:            public ClassLoader getClassLoader() {
0522:                return (ClassLoader) m_loaderRef.get();
0523:            }
0524:
0525:            /**
0526:             * Checks if the class has a static initalizer.
0527:             *
0528:             * @return
0529:             */
0530:            public boolean hasStaticInitializer() {
0531:                return m_hasStaticInitializer;
0532:            }
0533:
0534:            /**
0535:             * Return the static initializer info or null if not present
0536:             * 
0537:             * @see org.codehaus.aspectwerkz.reflect.ClassInfo#staticInitializer()
0538:             */
0539:            public StaticInitializationInfo staticInitializer() {
0540:                if (hasStaticInitializer() && m_staticInitializer == null) {
0541:                    m_staticInitializer = new StaticInitializationInfoImpl(this );
0542:                }
0543:                return m_staticInitializer;
0544:            }
0545:
0546:            /**
0547:             * Returns a constructor info by its hash.
0548:             *
0549:             * @param hash
0550:             * @return
0551:             */
0552:            public ConstructorInfo getConstructor(final int hash) {
0553:                ConstructorInfo constructor = (ConstructorInfo) m_constructors
0554:                        .get(hash);
0555:                if (constructor == null && getSuperclass() != null) {
0556:                    constructor = getSuperclass().getConstructor(hash);
0557:                }
0558:                return constructor;
0559:            }
0560:
0561:            /**
0562:             * Returns a list with all the constructors info.
0563:             *
0564:             * @return the constructors info
0565:             */
0566:            public ConstructorInfo[] getConstructors() {
0567:                if (m_constructorsLazy == null) {
0568:                    ConstructorInfo[] constructorInfos = new ConstructorInfo[m_sortedConstructorHashes
0569:                            .size()];
0570:                    for (int i = 0; i < m_sortedConstructorHashes.size(); i++) {
0571:                        constructorInfos[i] = (ConstructorInfo) m_constructors
0572:                                .get(m_sortedConstructorHashes.get(i));
0573:                    }
0574:                    m_constructorsLazy = constructorInfos;
0575:                }
0576:                return m_constructorsLazy;
0577:            }
0578:
0579:            /**
0580:             * Returns a method info by its hash.
0581:             *
0582:             * @param hash
0583:             * @return
0584:             */
0585:            public MethodInfo getMethod(final int hash) {
0586:                MethodInfo method = (MethodInfo) m_methods.get(hash);
0587:                if (method == null) {
0588:                    for (int i = 0; i < getInterfaces().length; i++) {
0589:                        method = getInterfaces()[i].getMethod(hash);
0590:                        if (method != null) {
0591:                            break;
0592:                        }
0593:                    }
0594:                }
0595:                if (method == null && getSuperclass() != null) {
0596:                    method = getSuperclass().getMethod(hash);
0597:                }
0598:                return method;
0599:            }
0600:
0601:            /**
0602:             * Returns a list with all the methods info.
0603:             *
0604:             * @return the methods info
0605:             */
0606:            public MethodInfo[] getMethods() {
0607:                if (m_methodsLazy == null) {
0608:                    MethodInfo[] methodInfos = new MethodInfo[m_sortedMethodHashes
0609:                            .size()];
0610:                    for (int i = 0; i < m_sortedMethodHashes.size(); i++) {
0611:                        methodInfos[i] = (MethodInfo) m_methods
0612:                                .get(m_sortedMethodHashes.get(i));
0613:                    }
0614:                    m_methodsLazy = methodInfos;
0615:                }
0616:                return m_methodsLazy;
0617:            }
0618:
0619:            /**
0620:             * Returns a field info by its hash.
0621:             *
0622:             * @param hash
0623:             * @return
0624:             */
0625:            public FieldInfo getField(final int hash) {
0626:                FieldInfo field = (FieldInfo) m_fields.get(hash);
0627:                if (field == null && getSuperclass() != null) {
0628:                    field = getSuperclass().getField(hash);
0629:                }
0630:                return field;
0631:            }
0632:
0633:            /**
0634:             * Returns a list with all the field info.
0635:             *
0636:             * @return the field info
0637:             */
0638:            public FieldInfo[] getFields() {
0639:                if (m_fieldsLazy == null) {
0640:                    FieldInfo[] fieldInfos = new FieldInfo[m_sortedFieldHashes
0641:                            .size()];
0642:                    for (int i = 0; i < m_sortedFieldHashes.size(); i++) {
0643:                        fieldInfos[i] = (FieldInfo) m_fields
0644:                                .get(m_sortedFieldHashes.get(i));
0645:                    }
0646:                    m_fieldsLazy = fieldInfos;
0647:                }
0648:                return m_fieldsLazy;
0649:            }
0650:
0651:            /**
0652:             * Returns the interfaces.
0653:             *
0654:             * @return the interfaces
0655:             */
0656:            public ClassInfo[] getInterfaces() {
0657:                if (m_interfaces == null) {
0658:                    m_interfaces = new ClassInfo[m_interfaceClassNames.length];
0659:                    for (int i = 0; i < m_interfaceClassNames.length; i++) {
0660:                        m_interfaces[i] = AsmClassInfo.getClassInfo(
0661:                                m_interfaceClassNames[i],
0662:                                (ClassLoader) m_loaderRef.get());
0663:                    }
0664:                }
0665:                return m_interfaces;
0666:            }
0667:
0668:            /**
0669:             * Returns the super class.
0670:             *
0671:             * @return the super class
0672:             */
0673:            public ClassInfo getSuperclass() {
0674:                if (m_super Class == null && m_super ClassName != null) {
0675:                    m_super Class = AsmClassInfo.getClassInfo(m_super ClassName,
0676:                            (ClassLoader) m_loaderRef.get());
0677:                }
0678:                return m_super Class;
0679:            }
0680:
0681:            /**
0682:             * Returns the component type if array type else null.
0683:             *
0684:             * @return the component type
0685:             */
0686:            public ClassInfo getComponentType() {
0687:                if (isArray() && (m_componentTypeName == null)) {
0688:                    m_componentType = AsmClassInfo.getClassInfo(
0689:                            m_componentTypeName, (ClassLoader) m_loaderRef
0690:                                    .get());
0691:                }
0692:                return m_componentType;
0693:            }
0694:
0695:            /**
0696:             * Is the class an interface.
0697:             *
0698:             * @return
0699:             */
0700:            public boolean isInterface() {
0701:                return m_isInterface;
0702:            }
0703:
0704:            /**
0705:             * Is the class a primitive type.
0706:             *
0707:             * @return
0708:             */
0709:            public boolean isPrimitive() {
0710:                return m_isPrimitive;
0711:            }
0712:
0713:            /**
0714:             * Is the class an array type.
0715:             *
0716:             * @return
0717:             */
0718:            public boolean isArray() {
0719:                return m_isArray;
0720:            }
0721:
0722:            /**
0723:             * @see java.lang.Object#equals(java.lang.Object)
0724:             */
0725:            public boolean equals(Object o) {
0726:                if (this  == o) {
0727:                    return true;
0728:                }
0729:                if (!(o instanceof  ClassInfo)) {
0730:                    return false;
0731:                }
0732:                ClassInfo classInfo = (ClassInfo) o;
0733:                return m_name.equals(classInfo.getName());
0734:            }
0735:
0736:            /**
0737:             * @see java.lang.Object#hashCode()
0738:             */
0739:            public int hashCode() {
0740:                return m_name.hashCode();
0741:            }
0742:
0743:            public String toString() {
0744:                return m_name;
0745:            }
0746:
0747:            /**
0748:             * Create a ClassInfo based on a component type which can be himself an array
0749:             *
0750:             * @param className
0751:             * @param loader
0752:             * @param componentClassInfo
0753:             * @return
0754:             */
0755:            public static ClassInfo getArrayClassInfo(final String className,
0756:                    final ClassLoader loader, final ClassInfo componentClassInfo) {
0757:                return new AsmClassInfo(className, loader, componentClassInfo);
0758:            }
0759:
0760:            /**
0761:             * Creates a ClassInfo based on the stream retrieved from the class loader through
0762:             * <code>getResourceAsStream</code>.
0763:             *
0764:             * @param name java name as in source code
0765:             * @param loader
0766:             * @param lazyAttributes
0767:             */
0768:            private static ClassInfo createClassInfoFromStream(
0769:                    final String name, final ClassLoader loader,
0770:                    boolean lazyAttributes) {
0771:                final String className = name.replace('.', '/');
0772:
0773:                // to handle primitive type we need to know the array dimension
0774:                if (name.indexOf('/') < 0) {
0775:                    // it might be one
0776:                    // gets its non array component type and the dimension
0777:                    int dimension = 0;
0778:                    for (int i = className.indexOf('['); i > 0; i = className
0779:                            .indexOf('[', i + 1)) {
0780:                        dimension++;
0781:                    }
0782:                    String unidimComponentName = className;
0783:                    if (dimension > 0) {
0784:                        int unidimComponentTypeIndex = className.indexOf('[');
0785:                        unidimComponentName = className.substring(0,
0786:                                unidimComponentTypeIndex);
0787:                    }
0788:                    Class primitiveClass = AsmClassInfo
0789:                            .getPrimitiveClass(unidimComponentName);
0790:                    if (primitiveClass != null && primitiveClass.isPrimitive()) {
0791:                        if (dimension == 0) {
0792:                            return JavaClassInfo.getClassInfo(primitiveClass);
0793:                        } else {
0794:                            Class arrayClass = Array.newInstance(
0795:                                    primitiveClass, new int[dimension])
0796:                                    .getClass();
0797:                            return JavaClassInfo.getClassInfo(arrayClass);
0798:                        }
0799:                    }
0800:                }
0801:
0802:                // for non primitive, we need to chain component type ala java.lang.reflect
0803:                // to support multi. dim. arrays
0804:                int componentTypeIndex = className.lastIndexOf('[');
0805:                String componentName = className;
0806:                boolean isArray = false;
0807:                if (componentTypeIndex > 0) {
0808:                    componentName = className.substring(0, componentTypeIndex);
0809:                    isArray = true;
0810:                }
0811:
0812:                ClassInfo componentInfo = null;
0813:
0814:                // is component yet another array ie this name is a multi dim array ?
0815:                if (componentName.indexOf('[') > 0) {
0816:                    componentInfo = getClassInfo(componentName, loader);
0817:                } else {
0818:                    InputStream componentClassAsStream = null;
0819:                    if (loader != null) {
0820:                        componentClassAsStream = loader
0821:                                .getResourceAsStream(componentName + ".class");
0822:                    } else {
0823:                        // boot class loader, fall back to system classloader that will see it anyway
0824:                        componentClassAsStream = ClassLoader
0825:                                .getSystemClassLoader().getResourceAsStream(
0826:                                        componentName + ".class");
0827:                    }
0828:                    if (componentClassAsStream == null) {
0829:                        // might be more than one dimension
0830:                        if (componentName.indexOf('[') > 0) {
0831:                            return getClassInfo(componentName, loader);
0832:                        }
0833:                        System.out
0834:                                .println("AW::WARNING - could not load class ["
0835:                                        + componentName
0836:                                        + "] as a resource in loader ["
0837:                                        + loader + "]");
0838:                        componentInfo = new ClassInfo.NullClassInfo();
0839:                    }
0840:                    try {
0841:                        componentInfo = AsmClassInfo.getClassInfo(
0842:                                componentClassAsStream, loader, lazyAttributes);
0843:                    } finally {
0844:                        try {
0845:                            componentClassAsStream.close();
0846:                        } catch (Exception e) {
0847:                            ;
0848:                        }
0849:                    }
0850:                }
0851:
0852:                if (!isArray) {
0853:                    return componentInfo;
0854:                } else {
0855:                    return AsmClassInfo.getArrayClassInfo(className, loader,
0856:                            componentInfo);
0857:                }
0858:            }
0859:
0860:            //    /**
0861:            //     * Creates a string with the annotation key value pairs.
0862:            //     *
0863:            //     * @param annotation
0864:            //     * @return the string
0865:            //     */
0866:            //    private static String createAnnotationKeyValueString(final Annotation annotation) {
0867:            //        List elementValues = annotation.elementValues;
0868:            //        StringBuffer annotationValues = new StringBuffer();
0869:            //        if (elementValues.size() != 0) {
0870:            //            int i = 0;
0871:            //            for (Iterator iterator = elementValues.iterator(); iterator.hasNext();) {
0872:            //                Object[] keyValuePair = (Object[]) iterator.next();
0873:            //                annotationValues.append((String) keyValuePair[0]);
0874:            //                annotationValues.append('=');
0875:            //                annotationValues.append(keyValuePair[1].toString());
0876:            //                if (i < elementValues.size() - 1) {
0877:            //                    annotationValues.append(',');
0878:            //                }
0879:            //            }
0880:            //        }
0881:            //        return annotationValues.toString();
0882:            //    }
0883:
0884:            /**
0885:             * ASM bytecode visitor that retrieves the class name from the bytecode.
0886:             *
0887:             * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
0888:             */
0889:            public static class ClassNameRetrievalClassAdapter extends
0890:                    AsmAnnotationHelper.NullClassAdapter {
0891:
0892:                private String m_className;
0893:
0894:                public void visit(final int version, final int access,
0895:                        final String name, final String super Name,
0896:                        final String[] interfaces, final String sourceFile) {
0897:                    m_className = name.replace('/', '.');
0898:                }
0899:
0900:                public String getClassName() {
0901:                    return m_className;
0902:                }
0903:            }
0904:
0905:            /**
0906:             * ASM bytecode visitor that gathers info about the class.
0907:             *
0908:             * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
0909:             */
0910:            private class ClassInfoClassAdapter extends
0911:                    AsmAnnotationHelper.NullClassAdapter {
0912:
0913:                public boolean m_lazyAttributes = true;
0914:
0915:                public ClassInfoClassAdapter(boolean lazyAttributes) {
0916:                    m_lazyAttributes = lazyAttributes;
0917:                }
0918:
0919:                public void visit(final int version, final int access,
0920:                        final String name, final String super Name,
0921:                        final String[] interfaces, final String sourceFile) {
0922:
0923:                    m_name = name.replace('/', '.');
0924:                    m_modifiers = access;
0925:                    m_isInterface = Modifier.isInterface(m_modifiers);
0926:                    // special case for java.lang.Object, which does not extend anything
0927:                    m_super ClassName = super Name == null ? null : super Name
0928:                            .replace('/', '.');
0929:                    m_interfaceClassNames = new String[interfaces.length];
0930:                    for (int i = 0; i < interfaces.length; i++) {
0931:                        m_interfaceClassNames[i] = interfaces[i].replace('/',
0932:                                '.');
0933:                    }
0934:                    // FIXME this algo for array types does most likely NOT WORK (since
0935:                    // I assume that ASM is handling arrays
0936:                    // using the internal desriptor format '[L' and the algo is using '[]')
0937:                    if (m_name.endsWith("[]")) {
0938:                        m_isArray = true;
0939:                        int index = m_name.indexOf('[');
0940:                        m_componentTypeName = m_name.substring(0, index);
0941:                    } else if (m_name.equals("long") || m_name.equals("int")
0942:                            || m_name.equals("short")
0943:                            || m_name.equals("double")
0944:                            || m_name.equals("float") || m_name.equals("byte")
0945:                            || m_name.equals("boolean")
0946:                            || m_name.equals("char")) {
0947:                        m_isPrimitive = true;
0948:                    }
0949:                }
0950:
0951:                public void visitAttribute(final Attribute attribute) {
0952:                    // attributes
0953:                    if (!m_lazyAttributes) {
0954:                        List annotations = new ArrayList();
0955:                        annotations = AsmAnnotationHelper.extractAnnotations(
0956:                                annotations, attribute,
0957:                                (ClassLoader) m_loaderRef.get());
0958:                        m_annotations = annotations;
0959:                    }
0960:                }
0961:
0962:                public void visitField(final int access, final String name,
0963:                        final String desc, final Object value,
0964:                        final Attribute attrs) {
0965:                    final FieldStruct struct = new FieldStruct();
0966:                    struct.modifiers = access;
0967:                    struct.name = name;
0968:                    struct.desc = desc;
0969:                    struct.value = value;
0970:                    AsmFieldInfo fieldInfo = new AsmFieldInfo(struct, m_name,
0971:                            (ClassLoader) m_loaderRef.get());
0972:                    // attributes
0973:                    if (!m_lazyAttributes) {
0974:                        List annotations = new ArrayList();
0975:                        annotations = AsmAnnotationHelper.extractAnnotations(
0976:                                annotations, attrs, (ClassLoader) m_loaderRef
0977:                                        .get());
0978:                        fieldInfo.m_annotations = annotations;
0979:                    }
0980:                    int hash = AsmHelper.calculateFieldHash(name, desc);
0981:                    m_fields.put(hash, fieldInfo);
0982:                    m_sortedFieldHashes.add(hash);
0983:                }
0984:
0985:                public CodeVisitor visitMethod(final int access,
0986:                        final String name, final String desc,
0987:                        final String[] exceptions, final Attribute attrs) {
0988:                    final MethodStruct struct = new MethodStruct();
0989:                    struct.modifiers = access;
0990:                    struct.name = name;
0991:                    struct.desc = desc;
0992:                    struct.exceptions = exceptions;
0993:                    int hash = AsmHelper.calculateMethodHash(name, desc);
0994:                    // the methodInfo that should be updated when we will visit the method parameter names info if needed.
0995:                    AsmMethodInfo methodInfo = null;
0996:                    if (name.equals(TransformationConstants.CLINIT_METHOD_NAME)) {
0997:                        m_hasStaticInitializer = true;
0998:                    } else {
0999:                        AsmMemberInfo memberInfo = null;
1000:                        if (name
1001:                                .equals(TransformationConstants.INIT_METHOD_NAME)) {
1002:                            memberInfo = new AsmConstructorInfo(struct, m_name,
1003:                                    (ClassLoader) m_loaderRef.get());
1004:                            m_constructors.put(hash, memberInfo);
1005:                            m_sortedConstructorHashes.add(hash);
1006:                        } else {
1007:                            memberInfo = new AsmMethodInfo(struct, m_name,
1008:                                    (ClassLoader) m_loaderRef.get());
1009:                            m_methods.put(hash, memberInfo);
1010:                            m_sortedMethodHashes.add(hash);
1011:                            methodInfo = (AsmMethodInfo) memberInfo;
1012:                        }
1013:                        // attributes
1014:                        if (!m_lazyAttributes) {
1015:                            List annotations = new ArrayList();
1016:                            annotations = AsmAnnotationHelper
1017:                                    .extractAnnotations(annotations, attrs,
1018:                                            (ClassLoader) m_loaderRef.get());
1019:                            memberInfo.m_annotations = annotations;
1020:                        }
1021:                    }
1022:                    if (methodInfo != null) {
1023:                        // visit the method to access the parameter names as required to support Aspect with bindings
1024:                        // TODO: should we make this optional - similar to m_lazyAttributes ?
1025:                        Type[] parameterTypes = Type.getArgumentTypes(desc);
1026:                        if (parameterTypes.length > 0) {
1027:                            CodeVisitor methodParameterNamesVisitor = new MethodParameterNamesCodeAdapter(
1028:                                    Modifier.isStatic(access),
1029:                                    parameterTypes.length, methodInfo);
1030:                            return methodParameterNamesVisitor;
1031:                        } else {
1032:                            methodInfo.m_parameterNames = EMPTY_STRING_ARRAY;
1033:                        }
1034:                    }
1035:                    return AsmAnnotationHelper.NullCodeAdapter.NULL_CODE_ADAPTER;
1036:                }
1037:
1038:                public void visitEnd() {
1039:                    m_signature = AsmHelper
1040:                            .getClassDescriptor(AsmClassInfo.this );
1041:                }
1042:            }
1043:
1044:            /**
1045:             * Extracts method parameter names as they appear in the source code from debug infos
1046:             *
1047:             * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
1048:             */
1049:            static class MethodParameterNamesCodeAdapter extends
1050:                    AsmAnnotationHelper.NullCodeAdapter {
1051:                private final boolean m_isStatic;
1052:                private final int m_parameterCount;
1053:                private AsmMethodInfo m_methodInfo;
1054:                private int m_signatureParameterRegisterDepth = 0;
1055:
1056:                public MethodParameterNamesCodeAdapter(boolean isStatic,
1057:                        int parameterCount, AsmMethodInfo methodInfo) {
1058:                    m_isStatic = isStatic;
1059:                    m_parameterCount = parameterCount;
1060:                    m_methodInfo = methodInfo;
1061:                    m_methodInfo.m_parameterNames = new String[m_parameterCount];
1062:
1063:                    // compute the max index of the arguments that appear in the method signature
1064:                    // including "this" on register 0 for non static methods
1065:                    // a long or double needs 2 registers
1066:                    if (!m_isStatic) {
1067:                        m_signatureParameterRegisterDepth++;// index 0 = this
1068:                    }
1069:                    m_signatureParameterRegisterDepth += AsmHelper
1070:                            .getRegisterDepth(Type
1071:                                    .getArgumentTypes(m_methodInfo.m_member.desc));
1072:                }
1073:
1074:                /**
1075:                 * Do not assume to visit the local variable with index always increasing since it is a wrong assumption
1076:                 * [ see f.e. test.args.ArgsAspect.withArray advice ]
1077:                 * @param name
1078:                 * @param desc
1079:                 * @param start
1080:                 * @param end
1081:                 * @param index the index of the argument on the stack
1082:                 */
1083:                public void visitLocalVariable(String name, String desc,
1084:                        Label start, Label end, int index) {
1085:                    if (index < m_signatureParameterRegisterDepth) {
1086:                        // this is not a local variable
1087:                        if (index == 0) {
1088:                            if (!m_isStatic) {
1089:                                ;//skip this
1090:                            } else {
1091:                                m_methodInfo.pushParameterNameFromRegister(
1092:                                        index, name);
1093:                            }
1094:                        } else {
1095:                            m_methodInfo.pushParameterNameFromRegister(index,
1096:                                    name);
1097:                        }
1098:                    } else {
1099:                        ;// skip code block locals
1100:                    }
1101:                }
1102:            }
1103:
1104:            /**
1105:             * Converts the class name from VM type class name to Java type class name.
1106:             *
1107:             * @param className the VM type class name
1108:             * @return the Java type class name
1109:             */
1110:            private static String getJavaClassName(final String className) {
1111:                String javaClassName;
1112:                if (className.startsWith("[")) {
1113:                    javaClassName = Type.getType(className).getClassName();
1114:                } else {
1115:                    javaClassName = className.replace('/', '.');
1116:                }
1117:                return javaClassName;
1118:            }
1119:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.