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