Source Code Cross Referenced for AsmHelper.java in  » Aspect-oriented » aspectwerkz-2.0 » org » codehaus » aspectwerkz » transform » inlining » 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.transform.inlining 
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.transform.inlining;
0008:
0009:        import org.codehaus.aspectwerkz.util.ContextClassLoader;
0010:        import org.codehaus.aspectwerkz.reflect.ClassInfo;
0011:        import org.codehaus.aspectwerkz.reflect.MethodInfo;
0012:        import org.codehaus.aspectwerkz.reflect.ConstructorInfo;
0013:        import org.codehaus.aspectwerkz.reflect.FieldInfo;
0014:        import org.codehaus.aspectwerkz.reflect.impl.java.JavaClassInfo;
0015:        import org.codehaus.aspectwerkz.transform.TransformationConstants;
0016:        import org.codehaus.aspectwerkz.transform.AspectWerkzPreProcessor;
0017:        import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
0018:        import org.objectweb.asm.ClassWriter;
0019:        import org.objectweb.asm.CodeVisitor;
0020:        import org.objectweb.asm.Type;
0021:        import org.objectweb.asm.Label;
0022:        import org.objectweb.asm.ClassReader;
0023:
0024:        import java.io.File;
0025:        import java.io.FileOutputStream;
0026:        import java.io.IOException;
0027:        import java.lang.reflect.Constructor;
0028:        import java.lang.reflect.Method;
0029:        import java.lang.reflect.InvocationTargetException;
0030:        import java.security.ProtectionDomain;
0031:        import java.security.AccessController;
0032:        import java.security.PrivilegedAction;
0033:
0034:        /**
0035:         * Helper class with utility methods for the ASM library.
0036:         *
0037:         * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
0038:         * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
0039:         */
0040:        public class AsmHelper implements  TransformationConstants {
0041:
0042:            public final static ClassInfo INTEGER = JavaClassInfo
0043:                    .getClassInfo(Integer.TYPE);
0044:            public final static ClassInfo VOID = JavaClassInfo
0045:                    .getClassInfo(Void.TYPE);
0046:            public final static ClassInfo BOOLEAN = JavaClassInfo
0047:                    .getClassInfo(Boolean.TYPE);
0048:            public final static ClassInfo BYTE = JavaClassInfo
0049:                    .getClassInfo(Byte.TYPE);
0050:            public final static ClassInfo CHARACTER = JavaClassInfo
0051:                    .getClassInfo(Character.TYPE);
0052:            public final static ClassInfo SHORT = JavaClassInfo
0053:                    .getClassInfo(Short.TYPE);
0054:            public final static ClassInfo DOUBLE = JavaClassInfo
0055:                    .getClassInfo(Double.TYPE);
0056:            public final static ClassInfo FLOAT = JavaClassInfo
0057:                    .getClassInfo(Float.TYPE);
0058:            public final static ClassInfo LONG = JavaClassInfo
0059:                    .getClassInfo(Long.TYPE);
0060:
0061:            private static Class CLASS_LOADER;
0062:            private static Method CLASS_LOADER_DEFINE;
0063:            private static final ProtectionDomain PROTECTION_DOMAIN;
0064:
0065:            static {
0066:                PROTECTION_DOMAIN = (ProtectionDomain) AccessController
0067:                        .doPrivileged(new PrivilegedAction() {
0068:                            public Object run() {
0069:                                return AsmHelper.class.getProtectionDomain();
0070:                            }
0071:                        });
0072:
0073:                AccessController.doPrivileged(new PrivilegedAction() {
0074:                    public Object run() {
0075:                        try {
0076:                            CLASS_LOADER = Class
0077:                                    .forName(CLASS_LOADER_REFLECT_CLASS_NAME);
0078:                            CLASS_LOADER_DEFINE = CLASS_LOADER
0079:                                    .getDeclaredMethod(
0080:                                            DEFINE_CLASS_METHOD_NAME,
0081:                                            new Class[] { String.class,
0082:                                                    byte[].class, int.class,
0083:                                                    int.class,
0084:                                                    ProtectionDomain.class });
0085:                            CLASS_LOADER_DEFINE.setAccessible(true);
0086:                        } catch (Throwable t) {
0087:                            throw new Error(t.toString());
0088:                        }
0089:                        return null;
0090:                    }
0091:                });
0092:            }
0093:
0094:            /**
0095:             * A boolean to check if we have a J2SE 5 support
0096:             */
0097:            public final static boolean IS_JAVA_5;
0098:            public static int JAVA_VERSION = V1_3;
0099:
0100:            static {
0101:                Class annotation = null;
0102:                try {
0103:                    annotation = Class
0104:                            .forName("java.lang.annotation.Annotation");
0105:                    ClassReader cr = new ClassReader(
0106:                            "java.lang.annotation.Annotation");
0107:                    JAVA_VERSION = V1_5;
0108:                } catch (Throwable e) {
0109:                    annotation = null;
0110:                }
0111:                if (annotation == null) {
0112:                    IS_JAVA_5 = false;
0113:                } else {
0114:                    IS_JAVA_5 = true;
0115:                }
0116:            }
0117:
0118:            /**
0119:             * Factory method for ASM ClassWriter and J2SE 5 support
0120:             * See http://www.objectweb.org/wws/arc/asm/2004-08/msg00005.html
0121:             *
0122:             * @param computeMax
0123:             * @return
0124:             */
0125:            public static ClassWriter newClassWriter(boolean computeMax) {
0126:                return new ClassWriter(computeMax, true);
0127:            }
0128:
0129:            /**
0130:             * Gets the argument types for a constructor. <p/>Parts of code in this method is taken from the ASM codebase.
0131:             *
0132:             * @param constructor
0133:             * @return the ASM argument types for the constructor
0134:             */
0135:            public static Type[] getArgumentTypes(final Constructor constructor) {
0136:                Class[] classes = constructor.getParameterTypes();
0137:                Type[] types = new Type[classes.length];
0138:                for (int i = classes.length - 1; i >= 0; --i) {
0139:                    types[i] = Type.getType(classes[i]);
0140:                }
0141:                return types;
0142:            }
0143:
0144:            /**
0145:             * Dumps an ASM class to disk.
0146:             *
0147:             * @param dumpDir
0148:             * @param className
0149:             * @param bytes
0150:             * @throws java.io.IOException
0151:             */
0152:            public static void dumpClass(final String dumpDir,
0153:                    final String className, final byte[] bytes)
0154:                    throws IOException {
0155:                final File dir;
0156:                if (className.lastIndexOf('/') > 0) {
0157:                    dir = new File(dumpDir
0158:                            + File.separator
0159:                            + className
0160:                                    .substring(0, className.lastIndexOf('/')));
0161:                } else {
0162:                    dir = new File(dumpDir);
0163:                }
0164:                dir.mkdirs();
0165:                String fileName = dumpDir + File.separator + className
0166:                        + ".class";
0167:                if (AspectWerkzPreProcessor.VERBOSE) {
0168:                    System.out.println("AW INFO: dumping class " + className
0169:                            + " to " + dumpDir);
0170:                }
0171:                FileOutputStream os = new FileOutputStream(fileName);
0172:                os.write(bytes);
0173:                os.close();
0174:            }
0175:
0176:            /**
0177:             * Dumps an ASM class to disk.
0178:             *
0179:             * @param dumpDir
0180:             * @param className
0181:             * @param cw
0182:             * @throws java.io.IOException
0183:             */
0184:            public static void dumpClass(final String dumpDir,
0185:                    final String className, final ClassWriter cw)
0186:                    throws IOException {
0187:                File dir = new File(dumpDir + File.separator
0188:                        + className.substring(0, className.lastIndexOf('/')));
0189:                dir.mkdirs();
0190:                String fileName = dumpDir + File.separator + className
0191:                        + ".class";
0192:                if (AspectWerkzPreProcessor.VERBOSE) {
0193:                    System.out.println("AW INFO: dumping class " + className
0194:                            + " to " + dumpDir);
0195:                }
0196:                FileOutputStream os = new FileOutputStream(fileName);
0197:                os.write(cw.toByteArray());
0198:                os.close();
0199:            }
0200:
0201:            /**
0202:             * Adds a class to a class loader and loads it.
0203:             *
0204:             * @param loader the class loader (if null the context class loader will be used)
0205:             * @param bytes  the bytes for the class
0206:             * @param name   the name of the class
0207:             * @return the class
0208:             */
0209:            public static Class defineClass(ClassLoader loader,
0210:                    final byte[] bytes, final String name) {
0211:                String className = name.replace('/', '.');
0212:                try {
0213:                    if (loader == null) {
0214:                        loader = ContextClassLoader.getLoader();
0215:                    }
0216:
0217:                    // TODO: what if we don't have rights to set this method to
0218:                    // accessible on this specific CL? Load it in System CL?
0219:                    //CLASS_LOADER_DEFINE.setAccessible(true);
0220:                    Object[] args = new Object[] { className, bytes,
0221:                            new Integer(0), new Integer(bytes.length),
0222:                            PROTECTION_DOMAIN };
0223:                    Class clazz = (Class) CLASS_LOADER_DEFINE.invoke(loader,
0224:                            args);
0225:
0226:                    //CLASS_LOADER_DEFINE.setAccessible(false);
0227:                    return clazz;
0228:
0229:                } catch (InvocationTargetException e) {
0230:                    // JIT failovering for Thread concurrency
0231:                    // AW-222 (Tomcat and WLS were reported for AW-222)
0232:                    if (e.getTargetException() instanceof  LinkageError) {
0233:                        Class failoverJoinpointClass = forName(loader,
0234:                                className);
0235:                        if (failoverJoinpointClass != null) {
0236:                            return failoverJoinpointClass;
0237:                        }
0238:                    }
0239:                    throw new WrappedRuntimeException(e);
0240:                } catch (Exception e) {
0241:                    throw new WrappedRuntimeException(e);
0242:                }
0243:            }
0244:
0245:            /**
0246:             * Tries to load a class if unsuccessful returns null.
0247:             *
0248:             * @param loader the class loader
0249:             * @param name   the name of the class
0250:             * @return the class
0251:             */
0252:            public static Class forName(ClassLoader loader, final String name) {
0253:                String className = name.replace('/', '.');
0254:                try {
0255:                    if (loader == null) {
0256:                        loader = ContextClassLoader.getLoader();
0257:                    }
0258:                    // Use Class.forName since loader.loadClass fails on JBoss UCL
0259:                    return Class.forName(className, false, loader);
0260:                } catch (Exception e) {
0261:                    return null;
0262:                }
0263:            }
0264:
0265:            /**
0266:             * Calculates the method hash. The computation MUST be the same as in ReflectHelper, thus we switch back the names
0267:             * to Java style. Note that for array type, Java.reflect is using "[Lpack.foo;" style unless primitive.
0268:             *
0269:             * @param name
0270:             * @param desc
0271:             * @return
0272:             */
0273:            public static int calculateMethodHash(final String name,
0274:                    final String desc) {
0275:                int hash = 17;
0276:                hash = (37 * hash) + name.replace('/', '.').hashCode();
0277:                Type[] argumentTypes = Type.getArgumentTypes(desc);
0278:                for (int i = 0; i < argumentTypes.length; i++) {
0279:                    hash = (37 * hash)
0280:                            + AsmHelper.convertTypeDescToReflectDesc(
0281:                                    argumentTypes[i].getDescriptor())
0282:                                    .hashCode();
0283:                }
0284:                return hash;
0285:            }
0286:
0287:            /**
0288:             * Calculates the constructor hash.
0289:             *
0290:             * @param desc
0291:             * @return
0292:             */
0293:            public static int calculateConstructorHash(final String desc) {
0294:                return AsmHelper.calculateMethodHash(INIT_METHOD_NAME, desc);
0295:            }
0296:
0297:            //    /**
0298:            //     * Calculates the joinpoint constructor call/execution hash.
0299:            //     * It depends on the callee class name else we won't be able to distinguish joinpoint on different targets.
0300:            //     *
0301:            //     * @param declaringClassName
0302:            //     * @param desc
0303:            //     * @return
0304:            //     */
0305:            //    public static int calculateConstructorJoinPointHash(final String declaringClassName, final String desc) {
0306:            //        int hash = 17;
0307:            //        hash = (37 * hash) + AsmHelper.calculateClassHash("L" + declaringClassName + ";");
0308:            //        hash = (37 * hash) + AsmHelper.calculateMethodHash(INIT_METHOD_NAME, desc);
0309:            //        return hash;
0310:            //    }
0311:
0312:            /**
0313:             * Calculates the field hash.
0314:             *
0315:             * @param name
0316:             * @param desc
0317:             * @return
0318:             */
0319:            public static int calculateFieldHash(final String name,
0320:                    final String desc) {
0321:                int hash = 17;
0322:                hash = (37 * hash) + name.hashCode();
0323:                Type type = Type.getType(desc);
0324:                hash = (37 * hash)
0325:                        + AsmHelper.convertTypeDescToReflectDesc(
0326:                                type.getDescriptor()).hashCode();
0327:                return hash;
0328:            }
0329:
0330:            /**
0331:             * Calculates the class hash.
0332:             *
0333:             * @param declaringType
0334:             * @return
0335:             */
0336:            public static int calculateClassHash(final String declaringType) {
0337:                return AsmHelper.convertTypeDescToReflectDesc(declaringType)
0338:                        .hashCode();
0339:            }
0340:
0341:            /**
0342:             * Converts an internal Java array type name ([Lblabla) to the a the format used by the expression matcher
0343:             * (blabla[])
0344:             *
0345:             * @param typeName is type name
0346:             * @return
0347:             */
0348:            public static String convertArrayTypeName(final String typeName) {
0349:                int index = typeName.lastIndexOf('[');
0350:                if (index != -1) {
0351:                    StringBuffer arrayType = new StringBuffer();
0352:                    if (typeName.endsWith("I")) {
0353:                        arrayType.append("int");
0354:                    } else if (typeName.endsWith("J")) {
0355:                        arrayType.append("long");
0356:                    } else if (typeName.endsWith("S")) {
0357:                        arrayType.append("short");
0358:                    } else if (typeName.endsWith("F")) {
0359:                        arrayType.append("float");
0360:                    } else if (typeName.endsWith("D")) {
0361:                        arrayType.append("double");
0362:                    } else if (typeName.endsWith("Z")) {
0363:                        arrayType.append("boolean");
0364:                    } else if (typeName.endsWith("C")) {
0365:                        arrayType.append("char");
0366:                    } else if (typeName.endsWith("B")) {
0367:                        arrayType.append("byte");
0368:                    } else {
0369:                        arrayType.append(typeName.substring(index + 2, typeName
0370:                                .length() - 1));
0371:                    }
0372:                    for (int i = 0; i < (index + 1); i++) {
0373:                        arrayType.append("[]");
0374:                    }
0375:                    return arrayType.toString();
0376:                } else {
0377:                    return typeName;
0378:                }
0379:            }
0380:
0381:            /**
0382:             * Converts an ASM type descriptor" (I, [I, [Ljava/lang/String;, Ljava/lang/String;) to a Java.reflect one (int, [I,
0383:             * [Ljava.lang.String;, java.lang.String)
0384:             *
0385:             * @param typeDesc
0386:             * @return the Java.reflect string representation
0387:             */
0388:            public static String convertTypeDescToReflectDesc(
0389:                    final String typeDesc) {
0390:                if (typeDesc == null) {
0391:                    return null;
0392:                }
0393:                String result = null;
0394:                // change needed for array types only
0395:                if (typeDesc.startsWith("[")) {
0396:                    result = typeDesc;
0397:                } else {
0398:                    // support for single dimension type
0399:                    if (typeDesc.startsWith("L") && typeDesc.endsWith(";")) {
0400:                        result = typeDesc.substring(1, typeDesc.length() - 1);
0401:                    } else {
0402:                        // primitive type, single dimension
0403:                        if (typeDesc.equals("I")) {
0404:                            result = "int";
0405:                        } else if (typeDesc.equals("J")) {
0406:                            result = "long";
0407:                        } else if (typeDesc.equals("S")) {
0408:                            result = "short";
0409:                        } else if (typeDesc.equals("F")) {
0410:                            result = "float";
0411:                        } else if (typeDesc.equals("D")) {
0412:                            result = "double";
0413:                        } else if (typeDesc.equals("Z")) {
0414:                            result = "boolean";
0415:                        } else if (typeDesc.equals("C")) {
0416:                            result = "char";
0417:                        } else if (typeDesc.equals("B")) {
0418:                            result = "byte";
0419:                        } else {
0420:                            throw new RuntimeException(
0421:                                    "unknown primitive type " + typeDesc);
0422:                        }
0423:                    }
0424:                }
0425:                return result.replace('/', '.');
0426:            }
0427:
0428:            /**
0429:             * Converts a java reflect type desc to ASM type desc.
0430:             *
0431:             * @param desc
0432:             * @return
0433:             */
0434:            public static String convertReflectDescToTypeDesc(final String desc) {
0435:                if (desc == null) {
0436:                    return null;
0437:                }
0438:                String typeDesc = desc;
0439:                int dimension = 0;
0440:                char[] arr = desc.toCharArray();
0441:                for (int i = 0; i < arr.length; i++) {
0442:                    if (arr[i] == ']') {
0443:                        dimension++;
0444:                    }
0445:                }
0446:                typeDesc = desc.substring(0, desc.length() - dimension * 2);
0447:                if (typeDesc.equals("int")) {
0448:                    typeDesc = "I";
0449:                } else if (typeDesc.equals("short")) {
0450:                    typeDesc = "S";
0451:                } else if (typeDesc.equals("long")) {
0452:                    typeDesc = "J";
0453:                } else if (typeDesc.equals("float")) {
0454:                    typeDesc = "F";
0455:                } else if (typeDesc.equals("double")) {
0456:                    typeDesc = "D";
0457:                } else if (typeDesc.equals("byte")) {
0458:                    typeDesc = "B";
0459:                } else if (typeDesc.equals("char")) {
0460:                    typeDesc = "C";
0461:                } else if (typeDesc.equals("boolean")) {
0462:                    typeDesc = "Z";
0463:                } else {
0464:                    typeDesc = 'L' + typeDesc + ';';
0465:                }
0466:                for (int i = 0; i < dimension; i++) {
0467:                    typeDesc = '[' + typeDesc;
0468:                }
0469:                return typeDesc.replace('.', '/');
0470:            }
0471:
0472:            /**
0473:             * Adds the correct return statement.
0474:             *
0475:             * @param mv
0476:             * @param type
0477:             */
0478:            public static void addReturnStatement(final CodeVisitor mv,
0479:                    final Type type) {
0480:                switch (type.getSort()) {
0481:                case Type.VOID:
0482:                    mv.visitInsn(RETURN);
0483:                    break;
0484:                case Type.LONG:
0485:                    mv.visitInsn(LRETURN);
0486:                    break;
0487:                case Type.INT:
0488:                    mv.visitInsn(IRETURN);
0489:                    break;
0490:                case Type.SHORT:
0491:                    mv.visitInsn(IRETURN);
0492:                    break;
0493:                case Type.DOUBLE:
0494:                    mv.visitInsn(DRETURN);
0495:                    break;
0496:                case Type.FLOAT:
0497:                    mv.visitInsn(FRETURN);
0498:                    break;
0499:                case Type.BYTE:
0500:                    mv.visitInsn(IRETURN);
0501:                    break;
0502:                case Type.BOOLEAN:
0503:                    mv.visitInsn(IRETURN);
0504:                    break;
0505:                case Type.CHAR:
0506:                    mv.visitInsn(IRETURN);
0507:                    break;
0508:                case Type.ARRAY:
0509:                    mv.visitInsn(ARETURN);
0510:                    break;
0511:                case Type.OBJECT:
0512:                    mv.visitInsn(ARETURN);
0513:                    break;
0514:                }
0515:            }
0516:
0517:            /**
0518:             * Loads argument types.
0519:             *
0520:             * @param mv
0521:             * @param argumentTypes
0522:             */
0523:            public static void loadArgumentTypes(final CodeVisitor mv,
0524:                    final Type[] argumentTypes, final boolean staticMethod) {
0525:                int index;
0526:                if (staticMethod) {
0527:                    index = 0;
0528:                } else {
0529:                    index = 1;
0530:                }
0531:                for (int i = 0; i < argumentTypes.length; i++) {
0532:                    index = loadType(mv, index, argumentTypes[i]);
0533:                }
0534:            }
0535:
0536:            /**
0537:             * Loads a type.
0538:             *
0539:             * @param cv
0540:             * @param index
0541:             * @param type
0542:             * @return the incremented index
0543:             */
0544:            public static int loadType(final CodeVisitor cv, int index,
0545:                    final Type type) {
0546:                switch (type.getSort()) {
0547:                case Type.LONG:
0548:                    cv.visitVarInsn(LLOAD, index++);
0549:                    index++;
0550:                    break;
0551:                case Type.INT:
0552:                    cv.visitVarInsn(ILOAD, index++);
0553:                    break;
0554:                case Type.SHORT:
0555:                    cv.visitVarInsn(ILOAD, index++);
0556:                    break;
0557:                case Type.DOUBLE:
0558:                    cv.visitVarInsn(DLOAD, index++);
0559:                    index++;
0560:                    break;
0561:                case Type.FLOAT:
0562:                    cv.visitVarInsn(FLOAD, index++);
0563:                    break;
0564:                case Type.BYTE:
0565:                    cv.visitVarInsn(ILOAD, index++);
0566:                    break;
0567:                case Type.BOOLEAN:
0568:                    cv.visitVarInsn(ILOAD, index++);
0569:                    break;
0570:                case Type.CHAR:
0571:                    cv.visitVarInsn(ILOAD, index++);
0572:                    break;
0573:                case Type.ARRAY:
0574:                    cv.visitVarInsn(ALOAD, index++);
0575:                    break;
0576:                case Type.OBJECT:
0577:                    cv.visitVarInsn(ALOAD, index++);
0578:                    break;
0579:                }
0580:                return index;
0581:            }
0582:
0583:            /**
0584:             * Stores a type.
0585:             *
0586:             * @param cv
0587:             * @param index
0588:             * @param type
0589:             * @return the incremented index
0590:             */
0591:            public static int storeType(final CodeVisitor cv, int index,
0592:                    final Type type) {
0593:                switch (type.getSort()) {
0594:                case Type.VOID:
0595:                    break;
0596:                case Type.LONG:
0597:                    cv.visitVarInsn(LSTORE, index++);
0598:                    index++;
0599:                    break;
0600:                case Type.INT:
0601:                    cv.visitVarInsn(ISTORE, index++);
0602:                    break;
0603:                case Type.SHORT:
0604:                    cv.visitVarInsn(ISTORE, index++);
0605:                    break;
0606:                case Type.DOUBLE:
0607:                    cv.visitVarInsn(DSTORE, index++);
0608:                    index++;
0609:                    break;
0610:                case Type.FLOAT:
0611:                    cv.visitVarInsn(FSTORE, index++);
0612:                    break;
0613:                case Type.BYTE:
0614:                    cv.visitVarInsn(ISTORE, index++);
0615:                    break;
0616:                case Type.BOOLEAN:
0617:                    cv.visitVarInsn(ISTORE, index++);
0618:                    break;
0619:                case Type.CHAR:
0620:                    cv.visitVarInsn(ISTORE, index++);
0621:                    break;
0622:                case Type.ARRAY:
0623:                    cv.visitVarInsn(ASTORE, index++);
0624:                    break;
0625:                case Type.OBJECT:
0626:                    cv.visitVarInsn(ASTORE, index++);
0627:                    break;
0628:                }
0629:                return index;
0630:            }
0631:
0632:            /**
0633:             * Creates and adds the correct parameter index for integer types.
0634:             *
0635:             * @param cv
0636:             * @param index
0637:             */
0638:            public static void loadIntegerConstant(final CodeVisitor cv,
0639:                    final int index) {
0640:                switch (index) {
0641:                case 0:
0642:                    cv.visitInsn(ICONST_0);
0643:                    break;
0644:                case 1:
0645:                    cv.visitInsn(ICONST_1);
0646:                    break;
0647:                case 2:
0648:                    cv.visitInsn(ICONST_2);
0649:                    break;
0650:                case 3:
0651:                    cv.visitInsn(ICONST_3);
0652:                    break;
0653:                case 4:
0654:                    cv.visitInsn(ICONST_4);
0655:                    break;
0656:                case 5:
0657:                    cv.visitInsn(ICONST_5);
0658:                    break;
0659:                default:
0660:                    cv.visitIntInsn(BIPUSH, index);
0661:                    break;
0662:                }
0663:            }
0664:
0665:            /**
0666:             * Prepares the wrapping or a primitive type.
0667:             *
0668:             * @param cv
0669:             * @param type
0670:             */
0671:            public static void prepareWrappingOfPrimitiveType(
0672:                    final CodeVisitor cv, final Type type) {
0673:                switch (type.getSort()) {
0674:                case Type.SHORT:
0675:                    cv.visitTypeInsn(NEW, SHORT_CLASS_NAME);
0676:                    cv.visitInsn(DUP);
0677:                    break;
0678:                case Type.INT:
0679:                    cv.visitTypeInsn(NEW, INTEGER_CLASS_NAME);
0680:                    cv.visitInsn(DUP);
0681:                    break;
0682:                case Type.LONG:
0683:                    cv.visitTypeInsn(NEW, LONG_CLASS_NAME);
0684:                    cv.visitInsn(DUP);
0685:                    break;
0686:                case Type.FLOAT:
0687:                    cv.visitTypeInsn(NEW, FLOAT_CLASS_NAME);
0688:                    cv.visitInsn(DUP);
0689:                    break;
0690:                case Type.DOUBLE:
0691:                    cv.visitTypeInsn(NEW, DOUBLE_CLASS_NAME);
0692:                    cv.visitInsn(DUP);
0693:                    break;
0694:                case Type.BYTE:
0695:                    cv.visitTypeInsn(NEW, BYTE_CLASS_NAME);
0696:                    cv.visitInsn(DUP);
0697:                    break;
0698:                case Type.BOOLEAN:
0699:                    cv.visitTypeInsn(NEW, BOOLEAN_CLASS_NAME);
0700:                    cv.visitInsn(DUP);
0701:                    break;
0702:                case Type.CHAR:
0703:                    cv.visitTypeInsn(NEW, CHARACTER_CLASS_NAME);
0704:                    cv.visitInsn(DUP);
0705:                    break;
0706:                }
0707:            }
0708:
0709:            /**
0710:             * Handles the wrapping of a primitive type.
0711:             *
0712:             * @param cv
0713:             * @param type
0714:             */
0715:            public static void wrapPrimitiveType(final CodeVisitor cv,
0716:                    final Type type) {
0717:                switch (type.getSort()) {
0718:                case Type.VOID:
0719:                    cv.visitInsn(ACONST_NULL);
0720:                    break;
0721:                case Type.SHORT:
0722:                    cv
0723:                            .visitMethodInsn(INVOKESPECIAL, SHORT_CLASS_NAME,
0724:                                    INIT_METHOD_NAME,
0725:                                    SHORT_CLASS_INIT_METHOD_SIGNATURE);
0726:                    break;
0727:                case Type.INT:
0728:                    cv.visitMethodInsn(INVOKESPECIAL, INTEGER_CLASS_NAME,
0729:                            INIT_METHOD_NAME,
0730:                            INTEGER_CLASS_INIT_METHOD_SIGNATURE);
0731:                    break;
0732:                case Type.LONG:
0733:                    cv.visitMethodInsn(INVOKESPECIAL, LONG_CLASS_NAME,
0734:                            INIT_METHOD_NAME, LONG_CLASS_INIT_METHOD_SIGNATURE);
0735:                    break;
0736:                case Type.FLOAT:
0737:                    cv
0738:                            .visitMethodInsn(INVOKESPECIAL, FLOAT_CLASS_NAME,
0739:                                    INIT_METHOD_NAME,
0740:                                    FLOAT_CLASS_INIT_METHOD_SIGNATURE);
0741:                    break;
0742:                case Type.DOUBLE:
0743:                    cv.visitMethodInsn(INVOKESPECIAL, DOUBLE_CLASS_NAME,
0744:                            INIT_METHOD_NAME,
0745:                            DOUBLE_CLASS_INIT_METHOD_SIGNATURE);
0746:                    break;
0747:                case Type.BYTE:
0748:                    cv.visitMethodInsn(INVOKESPECIAL, BYTE_CLASS_NAME,
0749:                            INIT_METHOD_NAME, BYTE_CLASS_INIT_METHOD_SIGNATURE);
0750:                    break;
0751:                case Type.BOOLEAN:
0752:                    cv.visitMethodInsn(INVOKESPECIAL, BOOLEAN_CLASS_NAME,
0753:                            INIT_METHOD_NAME,
0754:                            BOOLEAN_CLASS_INIT_METHOD_SIGNATURE);
0755:                    break;
0756:                case Type.CHAR:
0757:                    cv.visitMethodInsn(INVOKESPECIAL, CHARACTER_CLASS_NAME,
0758:                            INIT_METHOD_NAME,
0759:                            CHARACTER_CLASS_INIT_METHOD_SIGNATURE);
0760:                    break;
0761:                }
0762:            }
0763:
0764:            /**
0765:             * Handles the unwrapping of a type, unboxing of primitives and casting to the correct object type.
0766:             * Takes care of null value replaced by default primitive value.
0767:             * <pre>(obj==null)?0L:((Long)obj).longValue();</pre>
0768:             *
0769:             * @param cv
0770:             * @param type
0771:             */
0772:            public static void unwrapType(final CodeVisitor cv, final Type type) {
0773:                // void, object and array type handling
0774:                switch (type.getSort()) {
0775:                case Type.OBJECT:
0776:                    String objectTypeName = type.getClassName().replace('.',
0777:                            '/');
0778:                    cv.visitTypeInsn(CHECKCAST, objectTypeName);
0779:                    return;
0780:                case Type.ARRAY:
0781:                    cv.visitTypeInsn(CHECKCAST, type.getDescriptor());
0782:                    return;
0783:                case Type.VOID:
0784:                    return;
0785:                }
0786:                // primitive type handling
0787:                Label l0If = new Label();
0788:                Label l1End = new Label();
0789:                // if != null
0790:                cv.visitInsn(DUP);
0791:                cv.visitJumpInsn(IFNONNULL, l0If);
0792:                // else, default value
0793:                cv.visitInsn(POP);
0794:                addDefaultValue(cv, type);
0795:                // end
0796:                cv.visitJumpInsn(GOTO, l1End);
0797:                // if body
0798:                cv.visitLabel(l0If);
0799:                switch (type.getSort()) {
0800:                case Type.SHORT:
0801:                    cv.visitTypeInsn(CHECKCAST, SHORT_CLASS_NAME);
0802:                    cv.visitMethodInsn(INVOKEVIRTUAL, SHORT_CLASS_NAME,
0803:                            SHORT_VALUE_METHOD_NAME,
0804:                            SHORT_VALUE_METHOD_SIGNATURE);
0805:                    break;
0806:                case Type.INT:
0807:                    cv.visitTypeInsn(CHECKCAST, INTEGER_CLASS_NAME);
0808:                    cv.visitMethodInsn(INVOKEVIRTUAL, INTEGER_CLASS_NAME,
0809:                            INT_VALUE_METHOD_NAME, INT_VALUE_METHOD_SIGNATURE);
0810:                    break;
0811:                case Type.LONG:
0812:                    cv.visitTypeInsn(CHECKCAST, LONG_CLASS_NAME);
0813:                    cv
0814:                            .visitMethodInsn(INVOKEVIRTUAL, LONG_CLASS_NAME,
0815:                                    LONG_VALUE_METHOD_NAME,
0816:                                    LONG_VALUE_METHOD_SIGNATURE);
0817:                    break;
0818:                case Type.FLOAT:
0819:                    cv.visitTypeInsn(CHECKCAST, FLOAT_CLASS_NAME);
0820:                    cv.visitMethodInsn(INVOKEVIRTUAL, FLOAT_CLASS_NAME,
0821:                            FLOAT_VALUE_METHOD_NAME,
0822:                            FLOAT_VALUE_METHOD_SIGNATURE);
0823:                    break;
0824:                case Type.DOUBLE:
0825:                    cv.visitTypeInsn(CHECKCAST, DOUBLE_CLASS_NAME);
0826:                    cv.visitMethodInsn(INVOKEVIRTUAL, DOUBLE_CLASS_NAME,
0827:                            DOUBLE_VALUE_METHOD_NAME,
0828:                            DOUBLE_VALUE_METHOD_SIGNATURE);
0829:                    break;
0830:                case Type.BYTE:
0831:                    cv.visitTypeInsn(CHECKCAST, BYTE_CLASS_NAME);
0832:                    cv
0833:                            .visitMethodInsn(INVOKEVIRTUAL, BYTE_CLASS_NAME,
0834:                                    BYTE_VALUE_METHOD_NAME,
0835:                                    BYTE_VALUE_METHOD_SIGNATURE);
0836:                    break;
0837:                case Type.BOOLEAN:
0838:                    cv.visitTypeInsn(CHECKCAST, BOOLEAN_CLASS_NAME);
0839:                    cv.visitMethodInsn(INVOKEVIRTUAL, BOOLEAN_CLASS_NAME,
0840:                            BOOLEAN_VALUE_METHOD_NAME,
0841:                            BOOLEAN_VALUE_METHOD_SIGNATURE);
0842:                    break;
0843:                case Type.CHAR:
0844:                    cv.visitTypeInsn(CHECKCAST, CHARACTER_CLASS_NAME);
0845:                    cv
0846:                            .visitMethodInsn(INVOKEVIRTUAL,
0847:                                    CHARACTER_CLASS_NAME,
0848:                                    CHAR_VALUE_METHOD_NAME,
0849:                                    CHAR_VALUE_METHOD_SIGNATURE);
0850:                    break;
0851:                }
0852:                cv.visitLabel(l1End);
0853:            }
0854:
0855:            /**
0856:             * Adds the default value for a type.
0857:             *
0858:             * @param cv
0859:             * @param type
0860:             */
0861:            public static void addDefaultValue(final CodeVisitor cv,
0862:                    final Type type) {
0863:                switch (type.getSort()) {
0864:                case Type.OBJECT:
0865:                    cv.visitInsn(ACONST_NULL);
0866:                    break;
0867:                case Type.ARRAY:
0868:                    cv.visitInsn(ACONST_NULL);
0869:                    break;
0870:                case Type.INT:
0871:                    cv.visitInsn(ICONST_0);
0872:                    break;
0873:                case Type.LONG:
0874:                    cv.visitInsn(LCONST_0);
0875:                    break;
0876:                case Type.SHORT:
0877:                    cv.visitInsn(ICONST_0);
0878:                    break;
0879:                case Type.FLOAT:
0880:                    cv.visitInsn(FCONST_0);
0881:                    break;
0882:                case Type.DOUBLE:
0883:                    cv.visitInsn(DCONST_0);
0884:                    break;
0885:                case Type.BYTE:
0886:                    cv.visitInsn(ICONST_0);
0887:                    break;
0888:                case Type.BOOLEAN:
0889:                    cv.visitInsn(ICONST_0);
0890:                    break;
0891:                case Type.CHAR:
0892:                    cv.visitInsn(ICONST_0);
0893:                    break;
0894:                }
0895:            }
0896:
0897:            /**
0898:             * Adds a string and inserts null if the string is null.
0899:             *
0900:             * @param cv
0901:             * @param value
0902:             */
0903:            public static void addNullableString(final CodeVisitor cv,
0904:                    final String value) {
0905:                if (value == null) {
0906:                    cv.visitInsn(ACONST_NULL);
0907:                } else {
0908:                    cv.visitLdcInsn(value);
0909:                }
0910:            }
0911:
0912:            /**
0913:             * Compute the register depth, based on an array of types (long, double = 2 bytes address)
0914:             *
0915:             * @param typesOnStack
0916:             * @return depth of the stack
0917:             */
0918:            public static int getRegisterDepth(final Type[] typesOnStack) {
0919:                int depth = 0;
0920:                for (int i = 0; i < typesOnStack.length; i++) {
0921:                    Type type = typesOnStack[i];
0922:                    depth++;
0923:                    switch (type.getSort()) {
0924:                    case Type.LONG:
0925:                        depth++;
0926:                        break;
0927:                    case Type.DOUBLE:
0928:                        depth++;
0929:                        break;
0930:                    }
0931:                }
0932:                return depth;
0933:            }
0934:
0935:            /**
0936:             * Compute the index on the stack of a given argument based on its index in the signature
0937:             *
0938:             * @param typesOnStack
0939:             * @param typeIndex
0940:             * @return
0941:             */
0942:            public static int getRegisterIndexOf(final Type[] typesOnStack,
0943:                    final int typeIndex) {
0944:                int depth = 0;
0945:                for (int i = 0; i < typeIndex; i++) {
0946:                    Type type = typesOnStack[i];
0947:                    depth++;
0948:                    switch (type.getSort()) {
0949:                    case Type.LONG:
0950:                        depth++;
0951:                        break;
0952:                    case Type.DOUBLE:
0953:                        depth++;
0954:                        break;
0955:                    }
0956:                }
0957:                return depth;
0958:            }
0959:
0960:            /**
0961:             * Compute the index on the signature of a given argument based on its index as if it was on the stack
0962:             * where the stack would start at the first argument
0963:             *
0964:             * @param typesOnStack
0965:             * @param registerIndex
0966:             * @return
0967:             */
0968:            public static int getTypeIndexOf(final Type[] typesOnStack,
0969:                    final int registerIndex) {
0970:                for (int i = 0; i < typesOnStack.length; i++) {
0971:                    int presumedRegisterIndex = getRegisterIndexOf(
0972:                            typesOnStack, i);
0973:                    if (registerIndex == presumedRegisterIndex) {
0974:                        return i;
0975:                    }
0976:                }
0977:                return -1;
0978:            }
0979:
0980:            /**
0981:             * Checks if the Type is a primitive.
0982:             *
0983:             * @param returnType
0984:             * @return TRUE/FALSE
0985:             */
0986:            public static boolean isPrimitive(final Type returnType) {
0987:                if (returnType.getSort() == Type.INT
0988:                        || returnType.getSort() == Type.SHORT
0989:                        || returnType.getSort() == Type.LONG
0990:                        || returnType.getSort() == Type.FLOAT
0991:                        || returnType.getSort() == Type.DOUBLE
0992:                        || returnType.getSort() == Type.BYTE
0993:                        || returnType.getSort() == Type.CHAR
0994:                        || returnType.getSort() == Type.BOOLEAN
0995:                        || returnType.getSort() == Type.VOID) {
0996:                    return true;
0997:                } else {
0998:                    return false;
0999:                }
1000:            }
1001:
1002:            /**
1003:             * Increments the index (takes doubles and longs in to account).
1004:             *
1005:             * @param index
1006:             * @param type
1007:             * @return the incremented index
1008:             */
1009:            public static int incrementIndex(int index, final Type type) {
1010:                if (type.getSort() == Type.LONG
1011:                        || type.getSort() == Type.DOUBLE) {
1012:                    index += 2;
1013:                } else {
1014:                    index++;
1015:                }
1016:                return index;
1017:            }
1018:
1019:            /**
1020:             * Returns the descriptor corresponding to the given method info.
1021:             * Adapted from ASM Type.getMethodDescriptor(<Method>)
1022:             *
1023:             * @param method
1024:             * @return the descriptor of the given method.
1025:             */
1026:            public static String getMethodDescriptor(final MethodInfo method) {
1027:                ClassInfo[] parameters = method.getParameterTypes();
1028:                StringBuffer buf = new StringBuffer();
1029:                buf.append('(');
1030:                for (int i = 0; i < parameters.length; ++i) {
1031:                    getClassDescriptor(buf, parameters[i]);
1032:                }
1033:                buf.append(')');
1034:                getClassDescriptor(buf, method.getReturnType());
1035:                return buf.toString();
1036:            }
1037:
1038:            /**
1039:             * Returns the descriptor corresponding to the given constructor info.
1040:             *
1041:             * @param constructor
1042:             * @return the descriptor of the given constructor.
1043:             */
1044:            public static String getConstructorDescriptor(
1045:                    final ConstructorInfo constructor) {
1046:                ClassInfo[] parameters = constructor.getParameterTypes();
1047:                StringBuffer buf = new StringBuffer();
1048:                buf.append('(');
1049:                for (int i = 0; i < parameters.length; ++i) {
1050:                    getClassDescriptor(buf, parameters[i]);
1051:                }
1052:                buf.append(')');
1053:                getClassDescriptor(buf, VOID);
1054:                return buf.toString();
1055:            }
1056:
1057:            /**
1058:             * Returns the descriptor corresponding to the given field info.
1059:             *
1060:             * @param field
1061:             * @return the descriptor of the given field.
1062:             */
1063:            public static String getFieldDescriptor(final FieldInfo field) {
1064:                return getClassDescriptor(field.getType());
1065:            }
1066:
1067:            /**
1068:             * Returns the descriptor corresponding to the given Java type.
1069:             * Adapted from ASM Type.getClassDescriptor(Class)
1070:             * <p/>
1071:             * TODO remove the delegation to private method
1072:             *
1073:             * @param c an object class, a primitive class or an array class.
1074:             * @return the descriptor corresponding to the given class.
1075:             */
1076:            public static String getClassDescriptor(final ClassInfo c) {
1077:                StringBuffer buf = new StringBuffer();
1078:                getClassDescriptor(buf, c);
1079:                return buf.toString();
1080:            }
1081:
1082:            /**
1083:             * Appends the descriptor of the given class to the given string buffer.
1084:             * Adapted from ASM Type.getClassDescriptor(StringBuffer, Class)
1085:             *
1086:             * @param buf   the string buffer to which the descriptor must be appended.
1087:             * @param klass the class whose descriptor must be computed.
1088:             */
1089:            private static void getClassDescriptor(final StringBuffer buf,
1090:                    final ClassInfo klass) {
1091:                ClassInfo d = klass;
1092:                while (true) {
1093:                    if (d.isPrimitive()) {
1094:                        char car;
1095:                        if (d.equals(INTEGER)) {
1096:                            car = 'I';
1097:                        } else if (d.equals(VOID)) {
1098:                            car = 'V';
1099:                        } else if (d.equals(BOOLEAN)) {
1100:                            car = 'Z';
1101:                        } else if (d.equals(BYTE)) {
1102:                            car = 'B';
1103:                        } else if (d.equals(CHARACTER)) {
1104:                            car = 'C';
1105:                        } else if (d.equals(SHORT)) {
1106:                            car = 'S';
1107:                        } else if (d.equals(DOUBLE)) {
1108:                            car = 'D';
1109:                        } else if (d.equals(FLOAT)) {
1110:                            car = 'F';
1111:                        } else if (d.equals(LONG)) {
1112:                            car = 'J';
1113:                        } else {
1114:                            throw new Error("should not happen");
1115:                        }
1116:                        buf.append(car);
1117:                        return;
1118:                    } else if (d.isArray()) {
1119:                        buf.append('[');
1120:                        d = d.getComponentType();
1121:                    } else {
1122:                        buf.append('L');
1123:                        String name = d.getName();
1124:                        int len = name.length();
1125:                        for (int i = 0; i < len; ++i) {
1126:                            char car = name.charAt(i);
1127:                            buf.append(car == '.' ? '/' : car);
1128:                        }
1129:                        buf.append(';');
1130:                        return;
1131:                    }
1132:                }
1133:            }
1134:
1135:            /**
1136:             * Returns the Java types corresponding to the argument types of the given
1137:             * method.
1138:             * Adapted from ASM getArgumentTypes(Method)
1139:             *
1140:             * @param method a method.
1141:             * @return the Java types corresponding to the argument types of the given
1142:             *         method.
1143:             */
1144:            public static Type[] getArgumentTypes(final MethodInfo method) {
1145:                ClassInfo[] classes = method.getParameterTypes();
1146:                Type[] types = new Type[classes.length];
1147:                for (int i = classes.length - 1; i >= 0; --i) {
1148:                    types[i] = getType(classes[i]);
1149:                }
1150:                return types;
1151:            }
1152:
1153:            /**
1154:             * Returns the Java type corresponding to the given class.
1155:             * Adapted from ASM getType(Class)
1156:             *
1157:             * @param c a class.
1158:             * @return the Java type corresponding to the given class.
1159:             */
1160:            public static Type getType(final ClassInfo c) {
1161:                if (c.isPrimitive()) {
1162:                    if (c.equals(INTEGER)) {
1163:                        return Type.INT_TYPE;
1164:                    } else if (c.equals(VOID)) {
1165:                        return Type.VOID_TYPE;
1166:                    } else if (c.equals(BOOLEAN)) {
1167:                        return Type.BOOLEAN_TYPE;
1168:                    } else if (c.equals(BYTE)) {
1169:                        return Type.BYTE_TYPE;
1170:                    } else if (c.equals(CHARACTER)) {
1171:                        return Type.CHAR_TYPE;
1172:                    } else if (c.equals(SHORT)) {
1173:                        return Type.SHORT_TYPE;
1174:                    } else if (c.equals(DOUBLE)) {
1175:                        return Type.DOUBLE_TYPE;
1176:                    } else if (c.equals(FLOAT)) {
1177:                        return Type.FLOAT_TYPE;
1178:                    } else if (c.equals(LONG)) {
1179:                        return Type.LONG_TYPE;
1180:                    } else {
1181:                        throw new Error("should not happen");
1182:                    }
1183:                } else {
1184:                    return Type.getType(getClassDescriptor(c));
1185:                }
1186:            }
1187:
1188:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.