Source Code Cross Referenced for AsmClassInfo.java in  » Net » Terracotta » com » tc » 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 » Net » Terracotta » com.tc.aspectwerkz.reflect.impl.asm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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