Example usage for org.objectweb.asm MethodVisitor visitTryCatchBlock

List of usage examples for org.objectweb.asm MethodVisitor visitTryCatchBlock

Introduction

In this page you can find the example usage for org.objectweb.asm MethodVisitor visitTryCatchBlock.

Prototype

public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) 

Source Link

Document

Visits a try catch block.

Usage

From source file:org.jboss.byteman.agent.JigsawAccessEnablerGenerator.java

License:Open Source License

private static byte[] getJigsawAccessibleFieldSetterClassBytes() {
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
    FieldVisitor fv;//w ww  .j a  v  a  2 s.co  m
    MethodVisitor mv;

    cw.visit(V9, ACC_PUBLIC + ACC_SUPER, "org/jboss/byteman/jigsaw/JigsawAccessibleFieldSetter", null,
            "java/lang/Object", new String[] { "org/jboss/byteman/agent/AccessibleFieldSetter" });

    cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup",
            ACC_PUBLIC + ACC_FINAL + ACC_STATIC);

    {
        fv = cw.visitField(ACC_PRIVATE, "handle", "Ljava/lang/invoke/MethodHandle;", null, null);
        fv.visitEnd();
    }
    {
        fv = cw.visitField(0, "isStatic", "Z", null, null);
        fv.visitEnd();
    }
    {
        fv = cw.visitField(ACC_PRIVATE, "field", "Ljava/lang/reflect/Field;", null, null);
        fv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PUBLIC, "<init>",
                "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/reflect/Field;)V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        Label l1 = new Label();
        Label l2 = new Label();
        mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Exception");
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Field", "getModifiers", "()I", false);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/reflect/Modifier", "isStatic", "(I)Z", false);
        mv.visitFieldInsn(PUTFIELD, "org/jboss/byteman/jigsaw/JigsawAccessibleFieldSetter", "isStatic", "Z");
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, "org/jboss/byteman/jigsaw/JigsawAccessibleFieldSetter", "isStatic", "Z");
        Label l3 = new Label();
        mv.visitJumpInsn(IFEQ, l3);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Field", "getDeclaringClass", "()Ljava/lang/Class;",
                false);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Field", "getName", "()Ljava/lang/String;", false);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Field", "getType", "()Ljava/lang/Class;", false);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "findStaticSetter",
                "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle;", false);
        mv.visitFieldInsn(PUTFIELD, "org/jboss/byteman/jigsaw/JigsawAccessibleFieldSetter", "handle",
                "Ljava/lang/invoke/MethodHandle;");
        mv.visitJumpInsn(GOTO, l1);
        mv.visitLabel(l3);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Field", "getDeclaringClass", "()Ljava/lang/Class;",
                false);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Field", "getName", "()Ljava/lang/String;", false);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Field", "getType", "()Ljava/lang/Class;", false);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "findSetter",
                "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/MethodHandle;", false);
        mv.visitFieldInsn(PUTFIELD, "org/jboss/byteman/jigsaw/JigsawAccessibleFieldSetter", "handle",
                "Ljava/lang/invoke/MethodHandle;");
        mv.visitLabel(l1);
        Label l4 = new Label();
        mv.visitJumpInsn(GOTO, l4);
        mv.visitLabel(l2);
        mv.visitVarInsn(ASTORE, 3);
        mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
        mv.visitInsn(DUP);
        mv.visitLdcInsn("JigsawAccessibleFieldSetter : exception creating etter method handle for field ");
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>",
                "(Ljava/lang/String;Ljava/lang/Throwable;)V", false);
        mv.visitInsn(ATHROW);
        mv.visitLabel(l4);
        mv.visitInsn(RETURN);
        mv.visitMaxs(5, 4);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        Label l1 = new Label();
        Label l2 = new Label();
        mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable");
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, "org/jboss/byteman/jigsaw/JigsawAccessibleFieldSetter", "isStatic", "Z");
        Label l3 = new Label();
        mv.visitJumpInsn(IFEQ, l3);
        mv.visitVarInsn(ALOAD, 1);
        Label l4 = new Label();
        mv.visitJumpInsn(IFNULL, l4);
        mv.visitTypeInsn(NEW, "org/jboss/byteman/rule/exception/ExecuteException");
        mv.visitInsn(DUP);
        mv.visitLdcInsn("JigsawAccessibleFieldSetter.set : expecting null owner for static set!");
        mv.visitMethodInsn(INVOKESPECIAL, "org/jboss/byteman/rule/exception/ExecuteException", "<init>",
                "(Ljava/lang/String;)V", false);
        mv.visitInsn(ATHROW);
        mv.visitLabel(l4);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, "org/jboss/byteman/jigsaw/JigsawAccessibleFieldSetter", "handle",
                "Ljava/lang/invoke/MethodHandle;");
        mv.visitInsn(ICONST_1);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_0);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitInsn(AASTORE);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invokeWithArguments",
                "([Ljava/lang/Object;)Ljava/lang/Object;", false);
        mv.visitInsn(POP);
        mv.visitJumpInsn(GOTO, l1);
        mv.visitLabel(l3);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, "org/jboss/byteman/jigsaw/JigsawAccessibleFieldSetter", "handle",
                "Ljava/lang/invoke/MethodHandle;");
        mv.visitInsn(ICONST_2);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_1);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitInsn(AASTORE);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invokeWithArguments",
                "([Ljava/lang/Object;)Ljava/lang/Object;", false);
        mv.visitInsn(POP);
        mv.visitLabel(l1);
        Label l5 = new Label();
        mv.visitJumpInsn(GOTO, l5);
        mv.visitLabel(l2);
        mv.visitVarInsn(ASTORE, 3);
        mv.visitTypeInsn(NEW, "org/jboss/byteman/rule/exception/ExecuteException");
        mv.visitInsn(DUP);
        mv.visitLdcInsn("JigsawAccessibleFieldSetter.set : exception invoking setter methodhandle ");
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKESPECIAL, "org/jboss/byteman/rule/exception/ExecuteException", "<init>",
                "(Ljava/lang/String;Ljava/lang/Throwable;)V", false);
        mv.visitInsn(ATHROW);
        mv.visitLabel(l5);
        mv.visitInsn(RETURN);
        mv.visitMaxs(5, 4);
        mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
}

From source file:org.lwjglx.autostack.Transformer.java

License:Open Source License

public byte[] transform(ClassLoader loader, final String className, Class<?> classBeingRedefined,
        ProtectionDomain protectionDomain, byte[] classfileBuffer) {
    try {/*from  www .j a v a  2s. c o  m*/
        if (className == null || className.startsWith("java/") || className.startsWith("sun/")
                || className.startsWith("jdk/internal/") || className.startsWith("org/lwjgl/"))
            return null;
        for (String pack : packages)
            if (!className.startsWith(pack))
                return null;
        ClassReader cr = new ClassReader(classfileBuffer);
        final Map<String, Integer> stackMethods = new HashMap<String, Integer>();
        // Scan all methods that need auto-stack
        if (debugTransform)
            System.out.println("[autostack] scanning methods in class: " + className.replace('/', '.'));
        cr.accept(new ClassVisitor(ASM7) {
            public MethodVisitor visitMethod(final int access, final String methodName, final String methodDesc,
                    String signature, String[] exceptions) {
                if ((access & (ACC_NATIVE | ACC_ABSTRACT)) != 0) {
                    // Don't try to analyze native or abstract methods.
                    return null;
                }
                MethodVisitor mv = new MethodVisitor(ASM7) {
                    boolean mark, catches, notransform, nostackparam, forcestack;

                    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                        if ("Lorg/lwjglx/autostack/NoTransform;".equals(desc))
                            notransform = true;
                        else if ("Lorg/lwjglx/autostack/NoStackParam;".equals(desc))
                            nostackparam = true;
                        else if ("Lorg/lwjglx/autostack/UseNewStack;".equals(desc))
                            forcestack = true;
                        return null;
                    }

                    public void visitMethodInsn(int opcode, String owner, String name, String desc,
                            boolean itf) {
                        if (opcode == INVOKESTATIC && !itf && (owner.startsWith("org/lwjgl/")
                                && (name.equals("mallocStack") || name.equals("callocStack"))
                                || owner.equals(MEMORYSTACK) && (name.equals("stackGet")
                                        || name.equals("stackPop") || name.equals("stackPush")
                                        || name.startsWith("stackMalloc") || name.startsWith("stackCalloc")
                                        || name.startsWith("nstackMalloc") || name.startsWith("nstackCalloc")
                                        || name.equals("stackUTF8") || name.equals("stackASCII")
                                        || name.equals("stackUTF16") || name.equals("stackFloats")
                                        || name.equals("stackInts") || name.equals("stackBytes")
                                        || name.equals("stackShorts") || name.equals("stackPointers")
                                        || name.equals("stackLongs")))) {
                            mark = true;
                        }
                    }

                    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
                        catches = true;
                    }

                    public void visitEnd() {
                        int flag = (access & ACC_PRIVATE) != 0 ? 8 : 0;
                        flag |= nostackparam ? 16 : 0;
                        if (mark || notransform || forcestack || nostackparam) {
                            if (notransform) {
                                flag |= 2;
                                if (debugTransform)
                                    System.out.println("[autostack]   will not transform method: "
                                            + className.replace('/', '.') + "." + methodName);
                            } else {
                                if (checkStack)
                                    flag |= 4;
                                flag |= catches ? 1 : 0;
                                if (debugTransform)
                                    System.out.println("[autostack]   will transform method: "
                                            + className.replace('/', '.') + "." + methodName);
                            }
                            stackMethods.put(methodName + methodDesc, Integer.valueOf(flag));
                        }
                    }
                };
                return mv;
            }
        }, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
        if (stackMethods.isEmpty())
            return null;

        // Now, transform all such methods
        if (debugTransform)
            System.out.println("[autostack] transforming methods in class: " + className.replace('/', '.'));
        ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
        cr.accept(new ClassVisitor(ASM7, cw) {
            boolean classDefaultNewStack = defaultNewStack;
            boolean classNoTransform;

            @Override
            public void visit(int version, int access, String name, String signature, String superName,
                    String[] interfaces) {
                cv.visit(version, access, name, signature, superName, interfaces);
                if (!checkStack) {
                    return;
                }
                /* Generate simple synthetic "compare stack pointers and throw if not equal" method */
                MethodVisitor mv = cv.visitMethod(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, "$checkStack$",
                        "(II)V", null, new String[] { "java/lang/AssertionError" });
                {
                    mv.visitCode();
                    mv.visitVarInsn(ILOAD, 0);
                    mv.visitVarInsn(ILOAD, 1);
                    Label l0 = new Label();
                    mv.visitJumpInsn(IF_ICMPEQ, l0);
                    mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
                    mv.visitInsn(DUP);
                    mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
                    mv.visitInsn(DUP);
                    mv.visitLdcInsn("Stack pointers differ: ");
                    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>",
                            "(Ljava/lang/String;)V", false);
                    mv.visitVarInsn(ILOAD, 0);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(I)Ljava/lang/StringBuilder;", false);
                    mv.visitLdcInsn(" != ");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
                    mv.visitVarInsn(ILOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(I)Ljava/lang/StringBuilder;", false);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
                            "()Ljava/lang/String;", false);
                    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>",
                            "(Ljava/lang/String;)V", false);
                    mv.visitInsn(ATHROW);
                    mv.visitLabel(l0);
                    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                    mv.visitInsn(RETURN);
                    mv.visitMaxs(5, 2);
                    mv.visitEnd();
                }

                mv = cv.visitMethod(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, "$checkStackWithThrowable$",
                        "(Ljava/lang/Throwable;II)Ljava/lang/Throwable;", null, null);
                {
                    mv.visitCode();
                    mv.visitVarInsn(ILOAD, 1);
                    mv.visitVarInsn(ILOAD, 2);
                    Label l0 = new Label();
                    mv.visitJumpInsn(IF_ICMPEQ, l0);
                    mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
                    mv.visitInsn(DUP);
                    mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
                    mv.visitInsn(DUP);
                    mv.visitLdcInsn("Stack pointers differ: ");
                    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>",
                            "(Ljava/lang/String;)V", false);
                    mv.visitVarInsn(ILOAD, 1);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(I)Ljava/lang/StringBuilder;", false);
                    mv.visitLdcInsn(" != ");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
                    mv.visitVarInsn(ILOAD, 2);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                            "(I)Ljava/lang/StringBuilder;", false);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
                            "()Ljava/lang/String;", false);
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>",
                            "(Ljava/lang/String;Ljava/lang/Throwable;)V", false);
                    mv.visitInsn(ARETURN);
                    mv.visitLabel(l0);
                    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitInsn(ARETURN);
                    mv.visitMaxs(5, 3);
                    mv.visitEnd();
                }
            }

            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                if ("Lorg/lwjglx/autostack/UseCallerStack;".equals(desc)) {
                    if (debugTransform)
                        System.out.println(
                                "[autostack]   class declares to use caller stack for all methods, unless overridden by method");
                    classDefaultNewStack = false;
                    return null;
                } else if ("Lorg/lwjglx/autostack/UseNewStack;".equals(desc)) {
                    if (debugTransform)
                        System.out.println(
                                "[autostack]   class declares to use new stack for all methods, unless overridden by method");
                    classDefaultNewStack = true;
                    return null;
                } else if ("Lorg/lwjglx/autostack/NoTransform;".equals(desc)) {
                    if (debugTransform)
                        System.out.println("[autostack]   class declares to not transform any methods");
                    classNoTransform = true;
                    return null;
                }
                return cv.visitAnnotation(desc, visible);
            }

            public MethodVisitor visitMethod(final int access, final String name, final String desc,
                    String signature, String[] exceptions) {
                Integer info = stackMethods.get(name + desc);
                if (info == null)
                    return super.visitMethod(access, name, desc, signature, exceptions);
                boolean catches = (info.intValue() & 1) == 1;
                final boolean notransform = classNoTransform || (info.intValue() & 2) == 2;
                if (debugTransform && !notransform)
                    System.out.println(
                            "[autostack]   transform method: " + className.replace('/', '.') + "." + name);
                final boolean memoryStackParam = stackAsParameter && (access & ACC_PRIVATE) != 0
                        && (info.intValue() & 16) == 0;
                MethodVisitor mv;
                final Type[] paramTypes = Type.getArgumentTypes(desc);
                final boolean isStatic = (access & ACC_STATIC) != 0;
                final boolean isConstructor = "<init>".equals(name);
                if (memoryStackParam) {
                    if (debugTransform)
                        System.out.println(
                                "[autostack]     changing signature of method to add additional MemoryStack parameter");

                    // Add additional MemoryStack parameter to the method signature index of the local stays the same
                    int paramEndIndex = desc.indexOf(')');
                    String beforeDesc = desc.substring(0, paramEndIndex);
                    String afterDesc = desc.substring(paramEndIndex);
                    mv = super.visitMethod(access | ACC_SYNTHETIC, name,
                            beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, signature, exceptions);

                    // Re-introduce the original method which just delegates
                    if (debugTransform)
                        System.out.println("[autostack]     adding delegate method with original signature");
                    MethodVisitor omv = super.visitMethod(access, name, desc, signature, exceptions);
                    omv.visitCode();
                    int param = 0;
                    if (!isStatic) {
                        omv.visitVarInsn(ALOAD, 0);
                        param++;
                    }
                    for (int i = 0; i < paramTypes.length; i++) {
                        omv.visitVarInsn(paramTypes[i].getOpcode(ILOAD), param);
                        param += paramTypes[i].getSize();
                    }
                    omv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, "stackGet", "()L" + MEMORYSTACK + ";",
                            false);
                    boolean isPrivate = (access & ACC_PRIVATE) != 0;
                    int opcode = isStatic ? INVOKESTATIC : isPrivate ? INVOKESPECIAL : INVOKEVIRTUAL;
                    omv.visitMethodInsn(opcode, className, name,
                            beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, false);
                    Type retType = Type.getReturnType(desc);
                    omv.visitInsn(retType.getOpcode(IRETURN));
                    omv.visitMaxs(-1, -1);
                    omv.visitEnd();
                } else {
                    mv = super.visitMethod(access, name, desc, signature, exceptions);
                }
                if (catches)
                    mv = new TryCatchBlockSorter(mv, access, name, desc, signature, exceptions);
                mv = new MethodVisitor(ASM7, mv) {
                    Label tryLabel = new Label();
                    Label finallyLabel = new Label();
                    int lastLine = 0;
                    boolean newStack = classDefaultNewStack;
                    int stackVarIndex;
                    int stackPointerVarIndex;
                    int firstAdditionalLocal;
                    int additionalLocals;
                    Object[] replacedLocals;

                    public void visitInsn(int opcode) {
                        if (notransform) {
                            mv.visitInsn(opcode);
                            return;
                        }
                        if (opcode >= IRETURN && opcode <= RETURN && (newStack || checkStack)) {
                            if (debugRuntime && newStack && !checkStack) {
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("[autostack] restore stack pointer because of return at "
                                        + className.replace('/', '.') + "." + name + ":" + lastLine);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                        "(Ljava/lang/String;)V", false);
                            }
                            if (newStack && !checkStack) {
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "setPointer", "(I)V", false);
                            } else if (checkStack) {
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false);
                                mv.visitMethodInsn(INVOKESTATIC, className, "$checkStack$", "(II)V", false);
                            }
                        }
                        mv.visitInsn(opcode);
                    }

                    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                        if ("Lorg/lwjglx/autostack/UseCallerStack;".equals(desc)) {
                            if (!notransform) {
                                if (debugTransform)
                                    System.out.println("[autostack]     method declares to use caller stack");
                                newStack = false;
                            }
                            return null;
                        } else if ("Lorg/lwjglx/autostack/UseNewStack;".equals(desc)) {
                            if (!notransform) {
                                if (debugTransform)
                                    System.out.println("[autostack]     method declares to use new stack");
                                newStack = true;
                            }
                            return null;
                        } else if ("Lorg/lwjglx/autostack/NoTransform;".equals(desc)) {
                            return null;
                        } else if ("Lorg/lwjglx/autostack/NoStackParam;".equals(desc)) {
                            return null;
                        }
                        return mv.visitAnnotation(desc, visible);
                    }

                    public void visitVarInsn(int opcode, int var) {
                        if (notransform) {
                            mv.visitVarInsn(opcode, var);
                            return;
                        }
                        if (var >= firstAdditionalLocal)
                            var += additionalLocals;
                        mv.visitVarInsn(opcode, var);
                    }

                    public void visitIincInsn(int var, int increment) {
                        if (notransform) {
                            mv.visitIincInsn(var, increment);
                            return;
                        }
                        if (var >= firstAdditionalLocal)
                            var += additionalLocals;
                        mv.visitIincInsn(var, increment);
                    }

                    public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
                        if (notransform) {
                            mv.visitFrame(type, nLocal, local, nStack, stack);
                            return;
                        }
                        if (type == F_FULL) {
                            int noThis = isStatic ? 0 : 1;
                            Object[] locals = new Object[local.length + additionalLocals];
                            if (!isStatic)
                                locals[0] = local[0];
                            int replacementLength = replacedLocals.length;
                            System.arraycopy(replacedLocals, noThis, locals, noThis,
                                    replacementLength - noThis);
                            int len = locals.length - replacementLength;
                            System.arraycopy(local, replacementLength - additionalLocals, locals,
                                    replacementLength, len);
                            mv.visitFrame(type, nLocal + additionalLocals, locals, nStack, stack);
                        } else
                            mv.visitFrame(type, nLocal, local, nStack, stack);
                    }

                    public void visitLocalVariable(String name, String desc, String signature, Label start,
                            Label end, int index) {
                        if (notransform) {
                            mv.visitLocalVariable(name, desc, signature, start, end, index);
                            return;
                        }
                        if (index >= firstAdditionalLocal)
                            index += additionalLocals;
                        mv.visitLocalVariable(name, desc, signature, start, end, index);
                    }

                    private boolean doesNotTakeStackItself(String desc) {
                        return desc.lastIndexOf("L" + MEMORYSTACK + ";)") == -1;
                    }

                    public void visitMethodInsn(int opcode, String owner, String name, String desc,
                            boolean itf) {
                        String completeName = name + desc;
                        Integer info = stackMethods.get(completeName);
                        if (opcode != INVOKESTATIC || notransform) {
                            mv.visitMethodInsn(opcode, owner, name, desc, itf);
                            return;
                        }
                        if (stackAsParameter && info != null && (info.intValue() & 8) != 0
                                && (info.intValue() & 16) == 0) {
                            /* Rewrite invocation to have additional MemoryStack parameter */
                            if (debugTransform)
                                System.out.println(
                                        "[autostack]     rewrite invocation of " + owner.replace('/', '.') + "."
                                                + name + " at line " + lastLine + " --> "
                                                + owner.replace('/', '.') + "." + name + "(..., MemoryStack)");
                            int paramEndIndex = desc.indexOf(')');
                            String beforeDesc = desc.substring(0, paramEndIndex);
                            String afterDesc = desc.substring(paramEndIndex);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            mv.visitMethodInsn(opcode, owner, name,
                                    beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, itf);
                            return;
                        }
                        if (owner.startsWith("org/lwjgl/")
                                && (name.equals("mallocStack") || name.equals("callocStack"))
                                && doesNotTakeStackItself(desc)) {
                            if (debugTransform)
                                System.out.println(
                                        "[autostack]     rewrite invocation of " + owner.replace('/', '.') + "."
                                                + name + " at line " + lastLine + " --> aload " + stackVarIndex
                                                + "; invokestatic " + owner.replace('/', '.') + "." + name);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            int paramEndIndex = desc.indexOf(')');
                            String beforeDesc = desc.substring(0, paramEndIndex);
                            String afterDesc = desc.substring(paramEndIndex);
                            mv.visitMethodInsn(opcode, owner, name,
                                    beforeDesc + "L" + MEMORYSTACK + ";" + afterDesc, false);
                        } else if (owner.equals(MEMORYSTACK) && name.equals("stackGet")) {
                            if (debugTransform)
                                System.out.println("[autostack]     rewrite invocation of "
                                        + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                        + " --> aload " + stackVarIndex);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                        } else if (owner.equals(MEMORYSTACK)
                                && (name.equals("stackPush") || name.equals("stackPop"))) {
                            String newName = "p" + name.substring(6);
                            if (debugTransform)
                                System.out.println("[autostack]     rewrite invocation of "
                                        + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                        + " --> aload " + stackVarIndex + "; invokevirtual "
                                        + MEMORYSTACK.replace('/', '.') + "." + newName);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                        } else if (owner.equals(MEMORYSTACK)
                                && (name.startsWith("stackMalloc") || name.startsWith("stackCalloc"))) {
                            String newName = name.substring(5, 6).toLowerCase() + name.substring(6);
                            if (debugTransform)
                                System.out.println("[autostack]     rewrite invocation of "
                                        + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                        + " --> aload " + stackVarIndex + "; invokevirtual "
                                        + MEMORYSTACK.replace('/', '.') + "." + newName);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            mv.visitInsn(SWAP);
                            mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                        } else if (owner.equals(MEMORYSTACK)
                                && (name.startsWith("nstackMalloc") || name.startsWith("nstackCalloc"))) {
                            String newName = "n" + name.substring(6, 7).toLowerCase() + name.substring(7);
                            if (debugTransform)
                                System.out.println("[autostack]     rewrite invocation of "
                                        + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                        + " --> aload " + stackVarIndex + "; invokevirtual "
                                        + MEMORYSTACK.replace('/', '.') + "." + newName);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            if ("(I)J".equals(desc)) {
                                mv.visitInsn(SWAP);
                            } else {
                                // (II)J
                                mv.visitInsn(DUP_X2);
                                mv.visitInsn(POP);
                            }
                            mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                        } else if (owner.equals(MEMORYSTACK) && (name.equals("stackASCII")
                                || name.equals("stackUTF8") || name.equals("stackUTF16"))) {
                            String newName = name.substring(5);
                            boolean withBoolean = desc.startsWith("(Ljava/lang/CharSequence;Z");
                            if (debugTransform)
                                System.out.println("[autostack]     rewrite invocation of "
                                        + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                        + " --> aload " + stackVarIndex + "; invokevirtual "
                                        + MEMORYSTACK.replace('/', '.') + "." + newName);
                            mv.visitVarInsn(ALOAD, stackVarIndex);
                            if (withBoolean) {
                                mv.visitInsn(DUP_X2);
                                mv.visitInsn(POP);
                            } else {
                                mv.visitInsn(SWAP);
                            }
                            mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                        } else if (owner.equals(MEMORYSTACK)
                                && (name.equals("stackFloats") || name.equals("stackInts")
                                        || name.equals("stackBytes") || name.equals("stackShorts")
                                        || name.equals("stackPointers")
                                                && (desc.startsWith("([Lorg/lwjgl/system/Pointer;")
                                                        || desc.startsWith("(Lorg/lwjgl/system/Pointer;")))) {
                            String newName = name.substring(5, 6).toLowerCase() + name.substring(6);
                            Type[] argTypes = Type.getArgumentTypes(desc);
                            if (argTypes.length == 1 && argTypes[0].getSort() == Type.ARRAY) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(SWAP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else if (argTypes.length == 1) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(SWAP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else if (argTypes.length == 2) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(DUP_X2);
                                mv.visitInsn(POP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else if (argTypes.length == 3) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(DUP2_X2);
                                mv.visitInsn(POP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                                mv.visitInsn(SWAP);
                                mv.visitInsn(POP);
                            } else {
                                if (debugTransform)
                                    System.out.println("[autostack]     failed to rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + ". Not yet implemented.");
                                /* Give up. Not possible without an additional local */
                                mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, name, desc, itf);
                            }
                        } else if (owner.equals(MEMORYSTACK) && name.equals("stackLongs")) {
                            String newName = name.substring(5, 6).toLowerCase() + name.substring(6);
                            Type[] argTypes = Type.getArgumentTypes(desc);
                            if (argTypes.length == 1 && argTypes[0].getSort() == Type.ARRAY) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(SWAP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else if (argTypes.length == 1) {
                                if (debugTransform)
                                    System.out.println("[autostack]     rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + " --> aload " + stackVarIndex + "; invokevirtual "
                                            + MEMORYSTACK.replace('/', '.') + "." + newName);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitInsn(DUP_X2);
                                mv.visitInsn(POP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, newName, desc, itf);
                            } else {
                                if (debugTransform)
                                    System.out.println("[autostack]     failed to rewrite invocation of "
                                            + owner.replace('/', '.') + "." + name + " at line " + lastLine
                                            + ". Not yet implemented.");
                                /* Give up. Not possible without an additional local */
                                mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, name, desc, itf);
                            }
                        } else {
                            mv.visitMethodInsn(opcode, owner, name, desc, itf);
                        }
                    }

                    public void visitLineNumber(int line, Label start) {
                        mv.visitLineNumber(line, start);
                        lastLine = line;
                    }

                    public void visitCode() {
                        if (notransform) {
                            mv.visitCode();
                            return;
                        }
                        additionalLocals = newStack || checkStack ? 2 : 1;
                        replacedLocals = new Object[paramTypes.length + additionalLocals + (isStatic ? 0 : 1)];
                        if (!newStack && !checkStack) {
                            replacedLocals[replacedLocals.length - 1] = MEMORYSTACK;
                        } else {
                            replacedLocals[replacedLocals.length - 2] = MEMORYSTACK;
                            replacedLocals[replacedLocals.length - 1] = INTEGER;
                        }
                        if (!isStatic)
                            replacedLocals[0] = isConstructor ? TOP : className;
                        int var = isStatic ? 0 : 1;
                        for (int t = 0, i = var; t < paramTypes.length; t++, i++) {
                            Type type = paramTypes[t];
                            var += type.getSize();
                            switch (type.getSort()) {
                            case Type.INT:
                            case Type.BYTE:
                            case Type.BOOLEAN:
                            case Type.SHORT:
                            case Type.CHAR:
                                replacedLocals[i] = INTEGER;
                                break;
                            case Type.LONG:
                                replacedLocals[i] = LONG;
                                break;
                            case Type.FLOAT:
                                replacedLocals[i] = FLOAT;
                                break;
                            case Type.DOUBLE:
                                replacedLocals[i] = DOUBLE;
                                break;
                            case Type.OBJECT:
                            case Type.ARRAY:
                                replacedLocals[i] = type.getInternalName();
                                break;
                            default:
                                throw new AssertionError("Unhandled parameter type: " + type);
                            }
                        }
                        firstAdditionalLocal = var;
                        stackVarIndex = var;
                        stackPointerVarIndex = var + 1;
                        mv.visitCode();
                        if (newStack && !checkStack || checkStack) {
                            if (!memoryStackParam) {
                                mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, "stackGet",
                                        "()L" + MEMORYSTACK + ";", false);
                                mv.visitInsn(DUP);
                                mv.visitVarInsn(ASTORE, stackVarIndex);
                            } else {
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                            }
                            mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false);
                            mv.visitVarInsn(ISTORE, stackPointerVarIndex);
                            if (debugRuntime && newStack && !checkStack) {
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("[autostack] save stack pointer [");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "toString",
                                        "(I)Ljava/lang/String;", false);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("] at begin of " + className.replace('/', '.') + "." + name);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                        "(Ljava/lang/String;)V", false);
                            }
                            mv.visitLabel(tryLabel);
                            if (!memoryStackParam)
                                mv.visitFrame(F_APPEND, 2, new Object[] { MEMORYSTACK, INTEGER }, 0, null);
                            else
                                mv.visitFrame(F_APPEND, 1, new Object[] { INTEGER }, 0, null);
                        } else if (!newStack && !checkStack) {
                            if (!memoryStackParam) {
                                mv.visitMethodInsn(INVOKESTATIC, MEMORYSTACK, "stackGet",
                                        "()L" + MEMORYSTACK + ";", false);
                                mv.visitVarInsn(ASTORE, stackVarIndex);
                            }
                            if (debugRuntime) {
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("[autostack] current stack pointer is [");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false);
                                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "toString",
                                        "(I)Ljava/lang/String;", false);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("] at begin of " + className.replace('/', '.') + "." + name);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                        "(Ljava/lang/String;)V", false);
                            }
                            mv.visitLabel(tryLabel);
                            if (!memoryStackParam)
                                mv.visitFrame(F_APPEND, 1, new Object[] { MEMORYSTACK }, 0, null);
                        }
                    }

                    public void visitMaxs(int maxStack, int maxLocals) {
                        if (notransform) {
                            mv.visitMaxs(maxStack, maxLocals);
                            return;
                        }
                        if (newStack && !checkStack || checkStack) {
                            mv.visitLabel(finallyLabel);
                            mv.visitFrame(F_FULL, replacedLocals.length, replacedLocals, 1,
                                    new Object[] { "java/lang/Throwable" });
                            mv.visitTryCatchBlock(tryLabel, finallyLabel, finallyLabel, null);
                            if (debugRuntime && newStack && !checkStack) {
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn("[autostack] restore stack pointer because of throw [");
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitInsn(DUP);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitInsn(SWAP);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "toString",
                                        "()Ljava/lang/String;", false);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print",
                                        "(Ljava/lang/String;)V", false);
                                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");
                                mv.visitLdcInsn(
                                        "] at " + className.replace('/', '.') + "." + name + ":" + lastLine);
                                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
                                        "(Ljava/lang/String;)V", false);
                            }
                            if (newStack && !checkStack) {
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "setPointer", "(I)V", false);
                            }
                            if (checkStack) {
                                mv.visitVarInsn(ILOAD, stackPointerVarIndex);
                                mv.visitVarInsn(ALOAD, stackVarIndex);
                                mv.visitMethodInsn(INVOKEVIRTUAL, MEMORYSTACK, "getPointer", "()I", false);
                                mv.visitMethodInsn(INVOKESTATIC, className, "$checkStackWithThrowable$",
                                        "(Ljava/lang/Throwable;II)Ljava/lang/Throwable;", false);
                            }
                            mv.visitInsn(ATHROW);
                        }
                        mv.visitMaxs(-1, maxLocals + additionalLocals);
                    }
                };
                return mv;
            }
        }, 0);
        byte[] arr = cw.toByteArray();
        if (trace) {
            cr = new ClassReader(arr);
            cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), 0);
        }
        return arr;
    } catch (Throwable t) {
        t.printStackTrace();
        throw new RuntimeException(t);
    }
}

From source file:org.mbte.groovypp.compiler.asm.VisitTryCatchBlock.java

License:Apache License

public void visit(MethodVisitor mv) {
    mv.visitTryCatchBlock(start, end, handler, type);
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

/**
 * Generate the exception table entry(/entries) for a try/catch block.
 * This can be done in any order, any time after all labels passed as arguments have been visited.
 * //from  w ww  . j  a  v  a  2 s.c om
 * Jump and return instructions are excluded from any exception handling blocks if they cause the next executed instruction 
 *   to escape the bounds of the try statement.
 * 
 * eg. if there is a return statement in a try block in a try-catch statement, the corresponding return instruction will
 *     be excluded from the exception table entry.
 *     if there is a jump (eg. goto) statement in a try block of a try-catch statement, the jump instruction will be
 *     excluded from the exception table entry if the jump destination lies outside the try statement.
 * 
 * Exclusion of the instruction will cause the exception table entry to be split or reduced:
 *   one entry will include the part before the excluded instruction, 
 *   the other will include the part after it, if it is not the instruction at the end of the block.
 * 
 * 
 * An interesting case to consider is a try/catch nested with respect to a while(true) statement, with a continue statement in the body:
 * 
 *     try {
 *         while (true) {
 *             (statements)
 *             continue;
 *             (more statements)
 *         }
 *     } catch (Exception e) {
 *     }
 * 
 *   versus
 * 
 *     while (true) {
 *         try {
 *             (statements)
 *             continue;
 *             (more statements)
 *         } catch (Exception e) {
 *         }
 *     }
 * 
 * In both cases, the continue is encoded as a goto instruction whose destination is the first instruction in (statements).
 * In the first case, the target "while" statement is nested within the try block, therefore the goto is not excluded.
 * In the second case, the target "while" statement is outside of the try block, therefore the goto is excluded.
 * ie. even though the instructions for the try body are the same, and the instructions for (statements) lies both within
 *   the while block and the try block, a jump to the first statement may or may not be viewed as escaping the try block,
 *   depending on which case was compiled.
 * 
 * 
 * @param tryStartLabel
 * @param tryEndLabel
 * @param catchLabel
 * @param exceptionType
 * @param tryBlockContext
 */
private static void encodeTryCatchBlock(Label tryStartLabel, Label tryEndLabel, Label catchLabel,
        JavaTypeName exceptionType, GenerationContext tryBlockContext) {

    MethodVisitor mv = tryBlockContext.getMethodVisitor();

    // The start label for the next table entry to be visited.
    Label exceptionEntryStartLabel = tryStartLabel;

    for (final JumpReturnLabelInfo jumpReturnLabelInfo : tryBlockContext.getJumpReturnLabelInfoList()) {

        // Only exclude the jump/return instruction (ie. split the exception block) 
        //   if the destination label is outside the scope of the try block
        Label destinationLabel = jumpReturnLabelInfo.getDestinationLabel();
        if (destinationLabel != null && tryBlockContext.containsStatementJumpLabel(destinationLabel)) {
            continue;
        }

        // The next entry goes from the start label (inclusive) to the return or continue label (exclusive).
        Label returnContinueLabel = jumpReturnLabelInfo.getInstructionLabel();
        if (exceptionEntryStartLabel.getOffset() != returnContinueLabel.getOffset()) {
            // When there are consecutive instructions which jump/return outside the scope of the try block,
            // after the first iteration of the loop we will have the exception entry start label and the
            // return continue label both pointing to the same offset (ie. the offset of the nth consecutive
            // jump/return instruction on iteration n).
            mv.visitTryCatchBlock(exceptionEntryStartLabel, returnContinueLabel, catchLabel,
                    exceptionType.getJVMInternalName());
        }

        // Set the start label for the next table entry to be visited.
        exceptionEntryStartLabel = jumpReturnLabelInfo.getAfterInstructionLabel(); // afterReturnLabel
    }

    // Check for the case where the last return instruction comes at the end of the try block.
    if (exceptionEntryStartLabel.getOffset() != tryEndLabel.getOffset()) {
        // Add the final entry, which ends at the tryEndLabel.
        mv.visitTryCatchBlock(exceptionEntryStartLabel, tryEndLabel, catchLabel,
                exceptionType.getJVMInternalName());
    }
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

/**
 * Encode a method invocation that is wrapped in a synchronized block.
 *   See Sun bug id #4414101 for a discussion of this generated code.
 * /*from  w  w  w .ja  v  a2s. com*/
 * @param smi - the SynchronizedMethodInvocation object.
 * @param context - the context of the code generation.
 * @return - true if the SynchronizedMethodInvocation is terminating.
 * @throws JavaGenerationException
 */
private static boolean encodeSynchronizedMethodInvocation(JavaStatement.SynchronizedMethodInvocation smi,
        GenerationContext context) throws JavaGenerationException {

    MethodVisitor mv = context.getMethodVisitor();

    // Get the JavaExpression for the object to synchronize on and generate the bytecode. 
    JavaExpression objectToSynchOn = smi.getSynchronizingObject();
    encodeExpr(objectToSynchOn, context);

    // The object to synchronize on is now on the stack.  Duplicate it, 
    // move one to storage as a local variable, and to MONITORENTER on the other. 
    mv.visitInsn(Opcodes.DUP);

    int mutexIndex = context.addLocalVar("$mutex", JavaTypeName.OBJECT);
    mv.visitVarInsn(Opcodes.ASTORE, mutexIndex);

    mv.visitInsn(Opcodes.MONITORENTER);

    // We need to wrap the method invocation in a try/catch block so 
    // the monitor can be exited properly if the method invocation throws
    // an exception.
    Label tryCatchStart = new Label();
    mv.visitLabel(tryCatchStart);

    // Note: if this is generalized to handle any synchronized statement (for example, a synchronized block), 
    //   then the scope of entries in the exception table here will have to be modified to exclude return instructions.
    //   See encodeTryCatchStatement() for how to do this.
    //   Here, the only statement in the try block is a single expressionStatement, which has no return instructions, 
    //     so we don't have to worry about handling this case.

    // Get the method invocation and generate the corresponding bytecode.
    MethodInvocation methodInvocation = smi.getMethodInvocation();
    encodeExpr(methodInvocation, context);

    // Load the mutex object back onto the stack and do MonitorExit.
    mv.visitVarInsn(Opcodes.ALOAD, mutexIndex);
    mv.visitInsn(Opcodes.MONITOREXIT);

    // Label the end of the try block around the method invocation.
    Label tryEnd = new Label();
    mv.visitLabel(tryEnd);

    // At this point we want to code an instruction to jump past the exception handling
    // code.
    Label tryCatchEnd = new Label();
    mv.visitJumpInsn(Opcodes.GOTO, tryCatchEnd);

    // Label the start of the exception handling code.
    Label catchStart = new Label();
    mv.visitLabel(catchStart);

    // The exception is on the stack.  Store it as a local.
    int exceptionIndex = context.addLocalVar("exception", JavaTypeName.OBJECT);
    mv.visitVarInsn(Opcodes.ASTORE, exceptionIndex);

    // Retrieve the mutex object and do MONITOREXIT.
    mv.visitVarInsn(Opcodes.ALOAD, mutexIndex);
    mv.visitInsn(Opcodes.MONITOREXIT);

    // Label the end of the exception handling code that deals with the monitor.
    Label exceptionMonitorExitEnd = new Label();
    mv.visitLabel(exceptionMonitorExitEnd);

    // Retrieve the exception and throw it.
    mv.visitVarInsn(Opcodes.ALOAD, exceptionIndex);
    mv.visitInsn(Opcodes.ATHROW);

    // Vist the label to mark the end of the try/catch.
    mv.visitLabel(tryCatchEnd);

    // Set up the try/catch block to catch exceptions thrown by the method invocation
    // and handle exiting the monitor.
    mv.visitTryCatchBlock(tryCatchStart, tryEnd, catchStart, null);

    // Set up a try catch block so that if an exception is thrown by trying to exit 
    // the monitor in the case of an exception from the method invocation we will keep trying to 
    // exit the monitor.
    mv.visitTryCatchBlock(catchStart, exceptionMonitorExitEnd, catchStart, null);

    return false;
}

From source file:org.qi4j.runtime.composite.FragmentClassLoader.java

License:Open Source License

public static byte[] generateClass(String name, Class baseClass) throws ClassNotFoundException {
    String classSlash = name.replace('.', '/');
    String baseClassSlash = getInternalName(baseClass);

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);

    // Class definition start
    cw.visit(jdkVersion, ACC_PUBLIC + ACC_SUPER, classSlash, null, baseClassSlash, null);

    // Composite reference
    {/*from   w ww. j  a  va 2 s. co m*/
        cw.visitField(ACC_PUBLIC, "_instance", "Lorg/qi4j/api/composite/CompositeInvoker;", null, null)
                .visitEnd();
    }

    // Static Method references
    boolean hasProxyMethods = false;
    {
        int idx = 1;
        for (Method method : baseClass.getMethods()) {
            if (isOverridden(method, baseClass)) {
                cw.visitField(ACC_PRIVATE + ACC_STATIC, "m" + idx++, "Ljava/lang/reflect/Method;", null, null)
                        .visitEnd();
                hasProxyMethods = true;
            }
        }
    }

    // Constructors
    for (Constructor constructor : baseClass.getDeclaredConstructors()) {
        if (Modifier.isPublic(constructor.getModifiers()) || Modifier.isProtected(constructor.getModifiers())) {
            String desc = org.objectweb.asm.commons.Method.getMethod(constructor).getDescriptor();
            MethodVisitor cmv = cw.visitMethod(ACC_PUBLIC, "<init>", desc, null, null);
            cmv.visitCode();
            cmv.visitVarInsn(ALOAD, 0);

            int idx = 1;
            for (Class aClass : constructor.getParameterTypes()) {
                final int opcode;
                if (aClass.equals(Integer.TYPE)) {
                    opcode = ILOAD;
                } else if (aClass.equals(Long.TYPE)) {
                    opcode = LLOAD;
                } else if (aClass.equals(Float.TYPE)) {
                    opcode = FLOAD;
                } else if (aClass.equals(Double.TYPE)) {
                    opcode = DLOAD;
                } else {
                    opcode = ALOAD;
                }
                cmv.visitVarInsn(opcode, idx++);
            }

            cmv.visitMethodInsn(INVOKESPECIAL, baseClassSlash, "<init>", desc);
            cmv.visitInsn(RETURN);
            cmv.visitMaxs(idx, idx);
            cmv.visitEnd();
        }
    }

    // Overloaded and unimplemented methods
    if (hasProxyMethods) {
        Method[] methods = baseClass.getMethods();
        int idx = 0;
        List<Label> exceptionLabels = new ArrayList<Label>();
        for (Method method : methods) {
            if (isOverridden(method, baseClass)) {
                idx++;
                String methodName = method.getName();
                String desc = org.objectweb.asm.commons.Method.getMethod(method).getDescriptor();

                String[] exceptions = null;
                {
                    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, desc, null, exceptions);
                    if (isInternalQi4jMethod(method, baseClass)) {
                        // generate a NoOp method...
                        mv.visitInsn(RETURN);
                    } else {
                        Label endLabel = null; // Use this if return type is void
                        if (method.getExceptionTypes().length > 0) {
                            exceptions = new String[method.getExceptionTypes().length];
                            for (int i = 0; i < method.getExceptionTypes().length; i++) {
                                Class<?> aClass = method.getExceptionTypes()[i];
                                exceptions[i] = getInternalName(aClass);
                            }
                        }
                        mv.visitCode();
                        Label l0 = new Label();
                        Label l1 = new Label();

                        exceptionLabels.clear();
                        for (Class<?> declaredException : method.getExceptionTypes()) {
                            Label ld = new Label();
                            mv.visitTryCatchBlock(l0, l1, ld, getInternalName(declaredException));
                            exceptionLabels.add(ld); // Reuse this further down for the catch
                        }

                        Label lruntime = new Label();
                        mv.visitTryCatchBlock(l0, l1, lruntime, "java/lang/RuntimeException");
                        Label lerror = new Label();
                        mv.visitTryCatchBlock(l0, l1, lerror, "java/lang/Throwable");

                        mv.visitLabel(l0);
                        mv.visitVarInsn(ALOAD, 0);
                        mv.visitFieldInsn(GETFIELD, classSlash, "_instance",
                                "Lorg/qi4j/api/composite/CompositeInvoker;");
                        mv.visitFieldInsn(GETSTATIC, classSlash, "m" + idx, "Ljava/lang/reflect/Method;");

                        int paramCount = method.getParameterTypes().length;
                        int stackIdx = 0;
                        if (paramCount == 0) {
                            // Send in null as parameter
                            mv.visitInsn(ACONST_NULL);
                        } else {
                            insn(mv, paramCount);
                            mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
                            int pidx = 0;
                            for (Class<?> aClass : method.getParameterTypes()) {
                                mv.visitInsn(DUP);
                                insn(mv, pidx++);
                                stackIdx = wrapParameter(mv, aClass, stackIdx + 1);
                                mv.visitInsn(AASTORE);
                            }
                        }

                        // Call method
                        mv.visitMethodInsn(INVOKEINTERFACE, "org/qi4j/api/composite/CompositeInvoker",
                                "invokeComposite",
                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");

                        // Return value
                        if (!method.getReturnType().equals(Void.TYPE)) {
                            unwrapResult(mv, method.getReturnType(), l1);
                        } else {
                            mv.visitInsn(POP);
                            mv.visitLabel(l1);
                            endLabel = new Label();
                            mv.visitJumpInsn(GOTO, endLabel);
                        }

                        // Increase stack to beyond method args
                        stackIdx++;

                        // Declared exceptions
                        int exceptionIdx = 0;
                        for (Class<?> aClass : method.getExceptionTypes()) {
                            mv.visitLabel(exceptionLabels.get(exceptionIdx++));
                            mv.visitFrame(Opcodes.F_SAME1, 0, null, 1,
                                    new Object[] { getInternalName(aClass) });
                            mv.visitVarInsn(ASTORE, stackIdx);
                            mv.visitVarInsn(ALOAD, stackIdx);
                            mv.visitInsn(ATHROW);
                        }

                        // RuntimeException and Error catch-all
                        mv.visitLabel(lruntime);
                        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1,
                                new Object[] { "java/lang/RuntimeException" });
                        mv.visitVarInsn(ASTORE, stackIdx);
                        mv.visitVarInsn(ALOAD, stackIdx);
                        mv.visitInsn(ATHROW);

                        mv.visitLabel(lerror);
                        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Throwable" });
                        mv.visitVarInsn(ASTORE, stackIdx);
                        mv.visitVarInsn(ALOAD, stackIdx);
                        mv.visitTypeInsn(CHECKCAST, "java/lang/Error");
                        mv.visitInsn(ATHROW);

                        // Return type = void
                        if (endLabel != null) {
                            mv.visitLabel(endLabel);
                            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                            mv.visitInsn(RETURN);
                        }

                        mv.visitMaxs(0, 0);
                        mv.visitEnd();
                    }
                }

                if (!Modifier.isAbstract(method.getModifiers())) {
                    // Add method with _ as prefix
                    MethodVisitor mv;
                    mv = cw.visitMethod(ACC_PUBLIC, "_" + method.getName(), desc, null, exceptions);
                    mv.visitCode();
                    mv.visitVarInsn(ALOAD, 0);

                    // Parameters
                    int stackIdx = 1;
                    for (Class<?> aClass : method.getParameterTypes()) {
                        stackIdx = loadParameter(mv, aClass, stackIdx) + 1;
                    }

                    // Call method
                    mv.visitMethodInsn(INVOKESPECIAL, baseClassSlash, method.getName(), desc);

                    // Return value
                    if (!method.getReturnType().equals(Void.TYPE)) {
                        returnResult(mv, method.getReturnType());
                    } else {
                        mv.visitInsn(RETURN);
                    }

                    mv.visitMaxs(1, 1);
                    mv.visitEnd();
                }
            }
        }

        // Class initializer
        {
            MethodVisitor mv;
            mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
            mv.visitCode();
            Label l0 = new Label();
            Label l1 = new Label();
            Label l2 = new Label();
            mv.visitTryCatchBlock(l0, l1, l2, "java/lang/NoSuchMethodException");
            mv.visitLabel(l0);

            // Lookup methods and store in static variables
            int midx = 0;
            for (Method method : methods) {
                if (isOverridden(method, baseClass)) {
                    method.setAccessible(true);
                    Class methodClass;
                    if (Modifier.isAbstract(method.getModifiers())) {
                        methodClass = method.getDeclaringClass();
                    } else {
                        try {
                            methodClass = getInterfaceMethodDeclaration(method, baseClass); // Overridden method lookup
                        } catch (NoSuchMethodException e) {
                            throw new ClassNotFoundException(name, e);
                        }
                    }

                    midx++;

                    mv.visitLdcInsn(Type.getType(methodClass));
                    mv.visitLdcInsn(method.getName());
                    insn(mv, method.getParameterTypes().length);
                    mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");

                    int pidx = 0;
                    for (Class<?> aClass : method.getParameterTypes()) {
                        mv.visitInsn(DUP);
                        insn(mv, pidx++);
                        type(mv, aClass);
                        mv.visitInsn(AASTORE);
                    }

                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethod",
                            "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
                    mv.visitFieldInsn(PUTSTATIC, classSlash, "m" + midx, "Ljava/lang/reflect/Method;");
                }
            }

            mv.visitLabel(l1);
            Label l3 = new Label();
            mv.visitJumpInsn(GOTO, l3);
            mv.visitLabel(l2);
            mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/NoSuchMethodException" });
            mv.visitVarInsn(ASTORE, 0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "printStackTrace", "()V");
            mv.visitLabel(l3);
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
            mv.visitInsn(RETURN);
            mv.visitMaxs(6, 1);
            mv.visitEnd();
        }
    }
    cw.visitEnd();
    return cw.toByteArray();
}

From source file:org.qi4j.runtime.composite.TransientClassLoader.java

License:Open Source License

public static byte[] generateClass(String name, Class baseClass) throws ClassNotFoundException {
    String classSlash = name.replace('.', '/');
    String baseClassSlash = getInternalName(baseClass);

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    FieldVisitor fv;/*from   w  ww . j a  va 2s.  c o  m*/
    MethodVisitor mv;
    AnnotationVisitor av0;

    // Class definition start
    cw.visit(jdkVersion, ACC_PUBLIC + ACC_SUPER, classSlash, null, baseClassSlash, null);

    // Composite reference
    {
        fv = cw.visitField(ACC_PUBLIC, "_instance", "Lorg/qi4j/api/composite/CompositeInvoker;", null, null);
        fv.visitEnd();
    }

    // Static Method references
    {
        int idx = 1;
        for (Method method : baseClass.getMethods()) {
            if (isOverloaded(method, baseClass)) {
                fv = cw.visitField(ACC_PRIVATE + ACC_STATIC, "m" + idx++, "Ljava/lang/reflect/Method;", null,
                        null);
                fv.visitEnd();
            }
        }
    }

    // Constructors
    for (Constructor constructor : baseClass.getDeclaredConstructors()) {
        if (Modifier.isPublic(constructor.getModifiers()) || Modifier.isProtected(constructor.getModifiers())) {
            String desc = org.objectweb.asm.commons.Method.getMethod(constructor).getDescriptor();
            mv = cw.visitMethod(ACC_PUBLIC, "<init>", desc, null, null);
            mv.visitCode();
            mv.visitVarInsn(ALOAD, 0);

            int idx = 1;
            for (Class aClass : constructor.getParameterTypes()) {
                // TODO Handle other types than objects (?)
                mv.visitVarInsn(ALOAD, idx++);
            }

            mv.visitMethodInsn(INVOKESPECIAL, baseClassSlash, "<init>", desc);
            mv.visitInsn(RETURN);
            mv.visitMaxs(idx, idx);
            mv.visitEnd();
        }
    }

    // Overloaded and unimplemented methods
    Method[] methods = baseClass.getMethods();
    int idx = 0;
    List<Label> exceptionLabels = new ArrayList<Label>();
    for (Method method : methods) {
        if (isOverloaded(method, baseClass)) {
            idx++;
            String methodName = method.getName();
            String desc = org.objectweb.asm.commons.Method.getMethod(method).getDescriptor();

            String[] exceptions = null;
            {
                mv = cw.visitMethod(ACC_PUBLIC, methodName, desc, null, exceptions);
                if (isInternalQi4jMethod(method, baseClass)) {
                    // generate a NoOp method...
                    mv.visitInsn(RETURN);
                } else {
                    Label endLabel = null; // Use this if return type is void
                    if (method.getExceptionTypes().length > 0) {
                        exceptions = new String[method.getExceptionTypes().length];
                        for (int i = 0; i < method.getExceptionTypes().length; i++) {
                            Class<?> aClass = method.getExceptionTypes()[i];
                            exceptions[i] = getInternalName(aClass);
                        }
                    }
                    mv.visitCode();
                    Label l0 = new Label();
                    Label l1 = new Label();

                    exceptionLabels.clear();
                    for (Class<?> declaredException : method.getExceptionTypes()) {
                        Label ld = new Label();
                        mv.visitTryCatchBlock(l0, l1, ld, getInternalName(declaredException));
                        exceptionLabels.add(ld); // Reuse this further down for the catch
                    }

                    Label lruntime = new Label();
                    mv.visitTryCatchBlock(l0, l1, lruntime, "java/lang/RuntimeException");
                    Label lerror = new Label();
                    mv.visitTryCatchBlock(l0, l1, lerror, "java/lang/Throwable");

                    mv.visitLabel(l0);
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitFieldInsn(GETFIELD, classSlash, "_instance",
                            "Lorg/qi4j/api/composite/CompositeInvoker;");
                    mv.visitFieldInsn(GETSTATIC, classSlash, "m" + idx, "Ljava/lang/reflect/Method;");

                    int paramCount = method.getParameterTypes().length;
                    int stackIdx = 0;
                    if (paramCount == 0) {
                        // Send in null as parameter
                        mv.visitInsn(ACONST_NULL);
                    } else {
                        insn(mv, paramCount);
                        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
                        int pidx = 0;
                        for (Class<?> aClass : method.getParameterTypes()) {
                            mv.visitInsn(DUP);
                            insn(mv, pidx++);
                            stackIdx = wrapParameter(mv, aClass, stackIdx + 1);
                            mv.visitInsn(AASTORE);
                        }
                    }

                    // Call method
                    mv.visitMethodInsn(INVOKEINTERFACE, "org/qi4j/api/composite/CompositeInvoker",
                            "invokeComposite",
                            "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");

                    // Return value
                    if (!method.getReturnType().equals(Void.TYPE)) {
                        unwrapResult(mv, method.getReturnType(), l1);
                    } else {
                        mv.visitInsn(POP);
                        mv.visitLabel(l1);
                        endLabel = new Label();
                        mv.visitJumpInsn(GOTO, endLabel);
                    }

                    // Increase stack to beyond method args
                    stackIdx++;

                    // Declared exceptions
                    int exceptionIdx = 0;
                    for (Class<?> aClass : method.getExceptionTypes()) {
                        mv.visitLabel(exceptionLabels.get(exceptionIdx++));
                        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { getInternalName(aClass) });
                        mv.visitVarInsn(ASTORE, stackIdx);
                        mv.visitVarInsn(ALOAD, stackIdx);
                        mv.visitInsn(ATHROW);
                    }

                    // RuntimeException and Error catch-all
                    mv.visitLabel(lruntime);
                    mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/RuntimeException" });
                    mv.visitVarInsn(ASTORE, stackIdx);
                    mv.visitVarInsn(ALOAD, stackIdx);
                    mv.visitInsn(ATHROW);

                    mv.visitLabel(lerror);
                    mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Throwable" });
                    mv.visitVarInsn(ASTORE, stackIdx);
                    mv.visitVarInsn(ALOAD, stackIdx);
                    mv.visitTypeInsn(CHECKCAST, "java/lang/Error");
                    mv.visitInsn(ATHROW);

                    // Return type = void
                    if (endLabel != null) {
                        mv.visitLabel(endLabel);
                        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                        mv.visitInsn(RETURN);
                    }

                    mv.visitMaxs(0, 0);
                    mv.visitEnd();
                }
            }

            if (!Modifier.isAbstract(method.getModifiers())) {
                // Add method with _ as prefix
                mv = cw.visitMethod(ACC_PUBLIC, "_" + method.getName(), desc, null, exceptions);
                mv.visitCode();
                mv.visitVarInsn(ALOAD, 0);

                // Parameters
                int stackIdx = 1;
                for (Class<?> aClass : method.getParameterTypes()) {
                    stackIdx = loadParameter(mv, aClass, stackIdx) + 1;
                }

                // Call method
                mv.visitMethodInsn(INVOKESPECIAL, baseClassSlash, method.getName(), desc);

                // Return value
                if (!method.getReturnType().equals(Void.TYPE)) {
                    returnResult(mv, method.getReturnType());
                } else {
                    mv.visitInsn(RETURN);
                }

                mv.visitMaxs(1, 1);
                mv.visitEnd();
            }
        }
    }

    // Class initializer
    {
        mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        Label l1 = new Label();
        Label l2 = new Label();
        mv.visitTryCatchBlock(l0, l1, l2, "java/lang/NoSuchMethodException");
        mv.visitLabel(l0);

        // Lookup methods and store in static variables
        int midx = 0;
        for (Method method : methods) {
            if (isOverloaded(method, baseClass)) {
                method.setAccessible(true);
                Class methodClass;
                methodClass = method.getDeclaringClass();

                midx++;

                mv.visitLdcInsn(Type.getType(methodClass));
                mv.visitLdcInsn(method.getName());
                insn(mv, method.getParameterTypes().length);
                mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");

                int pidx = 0;
                for (Class<?> aClass : method.getParameterTypes()) {
                    mv.visitInsn(DUP);
                    insn(mv, pidx++);
                    type(mv, aClass);
                    mv.visitInsn(AASTORE);
                }

                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethod",
                        "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
                mv.visitFieldInsn(PUTSTATIC, classSlash, "m" + midx, "Ljava/lang/reflect/Method;");
            }
        }

        mv.visitLabel(l1);
        Label l3 = new Label();
        mv.visitJumpInsn(GOTO, l3);
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/NoSuchMethodException" });
        mv.visitVarInsn(ASTORE, 0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "printStackTrace", "()V");
        mv.visitLabel(l3);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitInsn(RETURN);
        mv.visitMaxs(6, 1);
        mv.visitEnd();
    }

    cw.visitEnd();

    return cw.toByteArray();
}

From source file:org.qi4j.test.ASMTest.java

License:Open Source License

public static byte[] generateClass() {
    ClassWriter cw = new ClassWriter(0);
    FieldVisitor fv;//from  w  w  w  .ja  v  a2 s .  c o m
    MethodVisitor mv;
    AnnotationVisitor av0;

    cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "org/qi4j/satisfiedBy/SomeMixin_Stub", null,
            "org/qi4j/satisfiedBy/SomeMixin", null);

    {
        fv = cw.visitField(ACC_PUBLIC, "_instance", "Lorg/qi4j/spi/composite/CompositeInvoker;", null, null);
        fv.visitEnd();
    }
    {
        fv = cw.visitField(ACC_PRIVATE + ACC_STATIC, "m1", "Ljava/lang/reflect/Method;", null, null);
        fv.visitEnd();
    }
    {
        fv = cw.visitField(ACC_PRIVATE + ACC_STATIC, "m2", "Ljava/lang/reflect/Method;", null, null);
        fv.visitEnd();
    }
    {
        fv = cw.visitField(ACC_PRIVATE + ACC_STATIC, "m3", "Ljava/lang/reflect/Method;", null, null);
        fv.visitEnd();
    }
    {
        fv = cw.visitField(ACC_PRIVATE + ACC_STATIC, "m4", "Ljava/lang/reflect/Method;", null, null);
        fv.visitEnd();
    }
    {
        fv = cw.visitField(ACC_PRIVATE + ACC_STATIC, "m5", "Ljava/lang/reflect/Method;", null, null);
        fv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, "org/qi4j/satisfiedBy/SomeMixin", "<init>", "()V");
        mv.visitInsn(RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/lang/String;)V", null, null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKESPECIAL, "org/qi4j/satisfiedBy/SomeMixin", "<init>", "(Ljava/lang/String;)V");
        mv.visitInsn(RETURN);
        mv.visitMaxs(2, 2);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PUBLIC, "other", "()Ljava/lang/String;", null, null);
        mv.visitCode();
        Label l0 = new Label();
        Label l1 = new Label();
        Label l2 = new Label();
        mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable");
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, "org/qi4j/satisfiedBy/SomeMixin_Stub", "_instance",
                "Lorg/qi4j/spi/composite/CompositeInvoker;");
        mv.visitFieldInsn(GETSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m1", "Ljava/lang/reflect/Method;");
        mv.visitInsn(ACONST_NULL);
        mv.visitMethodInsn(INVOKEINTERFACE, "org/qi4j/spi/composite/CompositeInvoker", "invokeComposite",
                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitTypeInsn(CHECKCAST, "java/lang/String");
        mv.visitLabel(l1);
        mv.visitInsn(ARETURN);
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Throwable" });
        mv.visitVarInsn(ASTORE, 1);
        mv.visitTypeInsn(NEW, "java/lang/reflect/UndeclaredThrowableException");
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
                "(Ljava/lang/Throwable;)V");
        mv.visitInsn(ATHROW);
        mv.visitMaxs(3, 2);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PUBLIC, "foo", "(Ljava/lang/String;I)Ljava/lang/String;", null,
                new String[] { "java/lang/IllegalArgumentException" });
        mv.visitCode();
        Label l0 = new Label();
        Label l1 = new Label();
        Label l2 = new Label();
        mv.visitTryCatchBlock(l0, l1, l2, "java/lang/IllegalArgumentException");
        Label l3 = new Label();
        mv.visitTryCatchBlock(l0, l1, l3, "java/lang/Throwable");
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, "org/qi4j/satisfiedBy/SomeMixin_Stub", "_instance",
                "Lorg/qi4j/spi/composite/CompositeInvoker;");
        mv.visitFieldInsn(GETSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m2", "Ljava/lang/reflect/Method;");
        mv.visitInsn(ICONST_2);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_1);
        mv.visitVarInsn(ILOAD, 2);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
        mv.visitInsn(AASTORE);
        mv.visitMethodInsn(INVOKEINTERFACE, "org/qi4j/spi/composite/CompositeInvoker", "invokeComposite",
                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitTypeInsn(CHECKCAST, "java/lang/String");
        mv.visitLabel(l1);
        mv.visitInsn(ARETURN);
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/IllegalArgumentException" });
        mv.visitVarInsn(ASTORE, 3);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitInsn(ATHROW);
        mv.visitLabel(l3);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Throwable" });
        mv.visitVarInsn(ASTORE, 3);
        mv.visitTypeInsn(NEW, "java/lang/reflect/UndeclaredThrowableException");
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
                "(Ljava/lang/Throwable;)V");
        mv.visitInsn(ATHROW);
        mv.visitMaxs(6, 4);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PUBLIC, "bar", "(DZFCIJSBLjava/lang/Double;[Ljava/lang/Object;[I)V", null,
                null);
        mv.visitCode();
        Label l0 = new Label();
        Label l1 = new Label();
        Label l2 = new Label();
        mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable");
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, "org/qi4j/satisfiedBy/SomeMixin_Stub", "_instance",
                "Lorg/qi4j/spi/composite/CompositeInvoker;");
        mv.visitFieldInsn(GETSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m3", "Ljava/lang/reflect/Method;");
        mv.visitIntInsn(BIPUSH, 11);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_0);
        mv.visitVarInsn(DLOAD, 1);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_1);
        mv.visitVarInsn(ILOAD, 3);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_2);
        mv.visitVarInsn(FLOAD, 4);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_3);
        mv.visitVarInsn(ILOAD, 5);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_4);
        mv.visitVarInsn(ILOAD, 6);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_5);
        mv.visitVarInsn(LLOAD, 7);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitIntInsn(BIPUSH, 6);
        mv.visitVarInsn(ILOAD, 9);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitIntInsn(BIPUSH, 7);
        mv.visitVarInsn(ILOAD, 10);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitIntInsn(BIPUSH, 8);
        mv.visitVarInsn(ALOAD, 11);
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitIntInsn(BIPUSH, 9);
        mv.visitVarInsn(ALOAD, 12);
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitIntInsn(BIPUSH, 10);
        mv.visitVarInsn(ALOAD, 13);
        mv.visitInsn(AASTORE);
        mv.visitMethodInsn(INVOKEINTERFACE, "org/qi4j/spi/composite/CompositeInvoker", "invokeComposite",
                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitInsn(POP);
        mv.visitLabel(l1);
        Label l3 = new Label();
        mv.visitJumpInsn(GOTO, l3);
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Throwable" });
        mv.visitVarInsn(ASTORE, 14);
        mv.visitTypeInsn(NEW, "java/lang/reflect/UndeclaredThrowableException");
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 14);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
                "(Ljava/lang/Throwable;)V");
        mv.visitInsn(ATHROW);
        mv.visitLabel(l3);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitInsn(RETURN);
        mv.visitMaxs(7, 15);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PUBLIC, "multiEx", "(Ljava/lang/String;)V", null,
                new String[] { "org/qi4j/satisfiedBy/Exception1", "org/qi4j/satisfiedBy/Exception2" });
        mv.visitCode();
        Label l0 = new Label();
        Label l1 = new Label();
        Label l2 = new Label();
        mv.visitTryCatchBlock(l0, l1, l2, "org/qi4j/satisfiedBy/Exception1");
        Label l3 = new Label();
        mv.visitTryCatchBlock(l0, l1, l3, "org/qi4j/satisfiedBy/Exception2");
        Label l4 = new Label();
        mv.visitTryCatchBlock(l0, l1, l4, "java/lang/Throwable");
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, "org/qi4j/satisfiedBy/SomeMixin_Stub", "_instance",
                "Lorg/qi4j/spi/composite/CompositeInvoker;");
        mv.visitFieldInsn(GETSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m4", "Ljava/lang/reflect/Method;");
        mv.visitInsn(ICONST_1);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitInsn(AASTORE);
        mv.visitMethodInsn(INVOKEINTERFACE, "org/qi4j/spi/composite/CompositeInvoker", "invokeComposite",
                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitInsn(POP);
        mv.visitLabel(l1);
        Label l5 = new Label();
        mv.visitJumpInsn(GOTO, l5);
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "org/qi4j/satisfiedBy/Exception1" });
        mv.visitVarInsn(ASTORE, 2);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitInsn(ATHROW);
        mv.visitLabel(l3);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "org/qi4j/satisfiedBy/Exception2" });
        mv.visitVarInsn(ASTORE, 2);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitInsn(ATHROW);
        mv.visitLabel(l4);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Throwable" });
        mv.visitVarInsn(ASTORE, 2);
        mv.visitTypeInsn(NEW, "java/lang/reflect/UndeclaredThrowableException");
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
                "(Ljava/lang/Throwable;)V");
        mv.visitInsn(ATHROW);
        mv.visitLabel(l5);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitInsn(RETURN);
        mv.visitMaxs(6, 3);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PUBLIC, "unwrapResult", "()I", null, null);
        mv.visitCode();
        Label l0 = new Label();
        Label l1 = new Label();
        Label l2 = new Label();
        mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable");
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, "org/qi4j/satisfiedBy/SomeMixin_Stub", "_instance",
                "Lorg/qi4j/spi/composite/CompositeInvoker;");
        mv.visitFieldInsn(GETSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m5", "Ljava/lang/reflect/Method;");
        mv.visitInsn(ACONST_NULL);
        mv.visitMethodInsn(INVOKEINTERFACE, "org/qi4j/spi/composite/CompositeInvoker", "invokeComposite",
                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
        mv.visitLabel(l1);
        mv.visitInsn(IRETURN);
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Throwable" });
        mv.visitVarInsn(ASTORE, 1);
        mv.visitTypeInsn(NEW, "java/lang/reflect/UndeclaredThrowableException");
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
                "(Ljava/lang/Throwable;)V");
        mv.visitInsn(ATHROW);
        mv.visitMaxs(3, 2);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        Label l1 = new Label();
        Label l2 = new Label();
        mv.visitTryCatchBlock(l0, l1, l2, "java/lang/NoSuchMethodException");
        mv.visitLabel(l0);
        mv.visitLdcInsn(Type.getType("Lorg/qi4j/satisfiedBy/Other;"));
        mv.visitLdcInsn("other");
        mv.visitInsn(ICONST_0);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethod",
                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
        mv.visitFieldInsn(PUTSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m1", "Ljava/lang/reflect/Method;");
        mv.visitLdcInsn(Type.getType("Lorg/qi4j/satisfiedBy/Other;"));
        mv.visitLdcInsn("foo");
        mv.visitInsn(ICONST_2);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_0);
        mv.visitLdcInsn(Type.getType("Ljava/lang/String;"));
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_1);
        mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
        mv.visitInsn(AASTORE);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethod",
                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
        mv.visitFieldInsn(PUTSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m2", "Ljava/lang/reflect/Method;");
        mv.visitLdcInsn(Type.getType("Lorg/qi4j/satisfiedBy/Other;"));
        mv.visitLdcInsn("bar");
        mv.visitIntInsn(BIPUSH, 11);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_0);
        mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_1);
        mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_2);
        mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_3);
        mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_4);
        mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_5);
        mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitIntInsn(BIPUSH, 6);
        mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitIntInsn(BIPUSH, 7);
        mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitIntInsn(BIPUSH, 8);
        mv.visitLdcInsn(Type.getType("Ljava/lang/Double;"));
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitIntInsn(BIPUSH, 9);
        mv.visitLdcInsn(Type.getType("[Ljava/lang/Object;"));
        mv.visitInsn(AASTORE);
        mv.visitInsn(DUP);
        mv.visitIntInsn(BIPUSH, 10);
        mv.visitLdcInsn(Type.getType("[I"));
        mv.visitInsn(AASTORE);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethod",
                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
        mv.visitFieldInsn(PUTSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m3", "Ljava/lang/reflect/Method;");
        mv.visitLdcInsn(Type.getType("Lorg/qi4j/satisfiedBy/Other;"));
        mv.visitLdcInsn("multiEx");
        mv.visitInsn(ICONST_1);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_0);
        mv.visitLdcInsn(Type.getType("Ljava/lang/String;"));
        mv.visitInsn(AASTORE);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethod",
                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
        mv.visitFieldInsn(PUTSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m4", "Ljava/lang/reflect/Method;");
        mv.visitLdcInsn(Type.getType("Lorg/qi4j/satisfiedBy/Other;"));
        mv.visitLdcInsn("unwrapResult");
        mv.visitInsn(ICONST_0);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethod",
                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
        mv.visitFieldInsn(PUTSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m5", "Ljava/lang/reflect/Method;");
        mv.visitLabel(l1);
        Label l3 = new Label();
        mv.visitJumpInsn(GOTO, l3);
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/NoSuchMethodException" });
        mv.visitVarInsn(ASTORE, 0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "printStackTrace", "()V");
        mv.visitLabel(l3);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitInsn(RETURN);
        mv.visitMaxs(6, 1);
        mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
}

From source file:org.simantics.databoard.tests.testASM.java

License:Open Source License

void createImpl(String className, Class<?> interfaze, ClassWriter cw) {
    FieldVisitor fv;//from w  ww.j av  a2 s  . c  om
    MethodVisitor mv;
    AnnotationVisitor av0;

    java.lang.reflect.Method[] methods = interfaze.getMethods();
    Arrays.sort(methods, MethodInterfaceUtil.methodComparator);

    String classResourceName = className.replaceAll("\\.", "/");
    String classTypeDescriptor = "L" + classResourceName + ";";
    String interfaceResourceName = classResourceName.substring(0, classResourceName.length() - 5);
    String interfaceTypeDescriptor = "L" + interfaceResourceName + ";";

    cw.visit(V1_6, ACC_SUPER | ACC_PUBLIC, classResourceName, null, "java/lang/Object",
            new String[] { interfaceResourceName });

    // Imports
    Set<Class<?>> imports = new HashSet<Class<?>>();
    imports.add(AsyncResult.class);
    imports.add(ExecutionError.class);
    imports.add(Method.class);
    imports.add(interfaze);

    for (java.lang.reflect.Method m : methods) {
        for (Class<?> clazz : m.getExceptionTypes()) {
            imports.add(clazz);
        }
        for (Class<?> clazz : m.getParameterTypes()) {
            imports.add(clazz);
        }
        imports.add(m.getReturnType());
    }

    for (Class<?> clazz : imports) {
        if (clazz.isPrimitive())
            continue;
        String name = clazz.getName();
        if (name.startsWith("java.lang"))
            continue;
        String resourceName = name.replaceAll("\\.", "/");
        String outerName = resourceName.contains("$") ? resourceName.substring(0, resourceName.indexOf('$'))
                : null;
        String className_ = clazz.isArray()
                ? clazz.getSimpleName().substring(0, clazz.getSimpleName().length() - 2)
                : clazz.getSimpleName();
        int access = ACC_PUBLIC + ACC_STATIC + (clazz.isInterface() ? ACC_INTERFACE + ACC_ABSTRACT : 0);
        //         System.out.printf("name=%s, outerName=%s, innerName=%s\n", resourceName, outerName, className_);
        cw.visitInnerClass(resourceName, outerName, className_, access);
    }

    // Fields
    {
        fv = cw.visitField(ACC_FINAL + ACC_STATIC, "interfaze", "Ljava/lang/Class;", "Ljava/lang/Class<*>;",
                null);
        fv.visitEnd();
    }
    {
        fv = cw.visitField(ACC_FINAL + ACC_STATIC, "bindings",
                "[Lorg/simantics/databoard/method/MethodBinding;", null, null);
        fv.visitEnd();
    }
    {
        fv = cw.visitField(0, "mi", "Lorg/simantics/data/session/MethodInterface;", null, null);
        fv.visitEnd();
    }
    {
        fv = cw.visitField(0, "methods", "[Lorg/simantics/data/session/MethodInterface$Method;", null, null);
        fv.visitEnd();
    }

    // Init class - static {}
    {
        mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitLdcInsn(Type.getType(interfaceTypeDescriptor));
        mv.visitFieldInsn(PUTSTATIC, classResourceName, "interfaze", "Ljava/lang/Class;");
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitFieldInsn(GETSTATIC, classResourceName, "interfaze", "Ljava/lang/Class;");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethods", "()[Ljava/lang/reflect/Method;");
        mv.visitVarInsn(ASTORE, 0);
        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETSTATIC, "org/simantics/data/network/MethodInterfaceUtil", "methodComparator",
                "Ljava/util/Comparator;");
        mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "sort",
                "([Ljava/lang/Object;Ljava/util/Comparator;)V");
        Label l3 = new Label();
        mv.visitLabel(l3);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitInsn(ARRAYLENGTH);
        mv.visitTypeInsn(ANEWARRAY, "org/simantics/databoard/method/MethodBinding");
        mv.visitFieldInsn(PUTSTATIC, classResourceName, "bindings",
                "[Lorg/simantics/databoard/method/MethodBinding;");
        Label l4 = new Label();
        mv.visitLabel(l4);
        mv.visitInsn(ICONST_0);
        mv.visitVarInsn(ISTORE, 1);
        Label l5 = new Label();
        mv.visitLabel(l5);
        Label l6 = new Label();
        mv.visitJumpInsn(GOTO, l6);
        Label l7 = new Label();
        mv.visitLabel(l7);
        mv.visitFrame(Opcodes.F_APPEND, 2, new Object[] { "[Ljava/lang/reflect/Method;", Opcodes.INTEGER }, 0,
                null);
        mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings",
                "[Lorg/simantics/databoard/method/MethodBinding;");
        mv.visitVarInsn(ILOAD, 1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ILOAD, 1);
        mv.visitInsn(AALOAD);
        mv.visitMethodInsn(INVOKESTATIC, "org/simantics/databoard/DataTypes", "getMethodBinding",
                "(Ljava/lang/reflect/Method;)Lorg/simantics/databoard/method/MethodBinding;");
        mv.visitInsn(AASTORE);
        Label l8 = new Label();
        mv.visitLabel(l8);
        mv.visitIincInsn(1, 1);
        mv.visitLabel(l6);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitVarInsn(ILOAD, 1);
        mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings",
                "[Lorg/simantics/databoard/method/MethodBinding;");
        mv.visitInsn(ARRAYLENGTH);
        mv.visitJumpInsn(IF_ICMPLT, l7);
        Label l9 = new Label();
        mv.visitLabel(l9);
        mv.visitInsn(RETURN);
        Label l10 = new Label();
        mv.visitLabel(l10);
        mv.visitLocalVariable("methods", "[Ljava/lang/reflect/Method;", null, l2, l10, 0);
        mv.visitLocalVariable("i", "I", null, l5, l9, 1);
        mv.visitMaxs(4, 2);
        mv.visitEnd();
    }

    // Constructor
    {
        mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Lorg/simantics/data/session/MethodInterface;)V", null,
                new String[] { "org/simantics/data/error/MethodNotSupportedException" });
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitFieldInsn(PUTFIELD, classResourceName, "mi", "Lorg/simantics/data/session/MethodInterface;");
        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings",
                "[Lorg/simantics/databoard/method/MethodBinding;");
        mv.visitInsn(ARRAYLENGTH);
        mv.visitTypeInsn(ANEWARRAY, "org/simantics/data/session/MethodInterface$Method");
        mv.visitFieldInsn(PUTFIELD, classResourceName, "methods",
                "[Lorg/simantics/data/session/MethodInterface$Method;");
        Label l3 = new Label();
        mv.visitLabel(l3);
        mv.visitInsn(ICONST_0);
        mv.visitVarInsn(ISTORE, 2);
        Label l4 = new Label();
        mv.visitLabel(l4);
        Label l5 = new Label();
        mv.visitJumpInsn(GOTO, l5);
        Label l6 = new Label();
        mv.visitLabel(l6);
        mv.visitFrame(Opcodes.F_FULL, 3, new Object[] { classResourceName,
                "org/simantics/data/session/MethodInterface", Opcodes.INTEGER }, 0, new Object[] {});
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, classResourceName, "methods",
                "[Lorg/simantics/data/session/MethodInterface$Method;");
        mv.visitVarInsn(ILOAD, 2);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings",
                "[Lorg/simantics/databoard/method/MethodBinding;");
        mv.visitVarInsn(ILOAD, 2);
        mv.visitInsn(AALOAD);
        mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/data/session/MethodInterface", "getMethod",
                "(Lorg/simantics/databoard/method/MethodBinding;)Lorg/simantics/data/session/MethodInterface$Method;");
        mv.visitInsn(AASTORE);
        Label l7 = new Label();
        mv.visitLabel(l7);
        mv.visitIincInsn(2, 1);
        mv.visitLabel(l5);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitVarInsn(ILOAD, 2);
        mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings",
                "[Lorg/simantics/databoard/method/MethodBinding;");
        mv.visitInsn(ARRAYLENGTH);
        mv.visitJumpInsn(IF_ICMPLT, l6);
        Label l8 = new Label();
        mv.visitLabel(l8);
        mv.visitInsn(RETURN);
        Label l9 = new Label();
        mv.visitLabel(l9);
        mv.visitLocalVariable("this", classTypeDescriptor, null, l0, l9, 0);
        mv.visitLocalVariable("mi", "Lorg/simantics/data/session/MethodInterface;", null, l0, l9, 1);
        mv.visitLocalVariable("i", "I", null, l4, l8, 2);
        mv.visitMaxs(5, 3);
        mv.visitEnd();
    }

    // Method
    int methodNumber = 0;
    for (java.lang.reflect.Method m : methods) {
        String typeDescription = "";
        Class<?>[] params = m.getParameterTypes();
        for (int i = 0; i < params.length; i++) {
            if (i > 0)
                typeDescription += ";";
            typeDescription += classToTypeDescriptor(params[i]);
        }
        typeDescription = "(" + typeDescription + ")" + classToTypeDescriptor(m.getReturnType());
        System.out.println(typeDescription + " " + m.getName());

        Class<?>[] exceptions = m.getExceptionTypes();
        String[] exceptionResourceNames = new String[exceptions.length];
        for (int i = 0; i < exceptionResourceNames.length; i++) {
            exceptionResourceNames[i] = exceptions[i].getName().replaceAll("\\.", "/");
        }

        // Registers
        // 0 - this
        // 1..argRegs args
        // argRegs+1 - method
        // argRegs+2 - args (the array)
        // argRegs+3 - AsyncResult
        // argRegs+4 - e
        // argRegs+5 - ExecutionError.cause
        // argRegs+6 - e

        int argRegs = 0;
        for (int i = 0; i < params.length; i++) {
            Class<?> clazz = params[i];
            argRegs++;
            if (clazz == long.class || clazz == float.class || clazz == Double.class)
                argRegs++;
        }

        mv = cw.visitMethod(ACC_PUBLIC, m.getName(), typeDescription, null, exceptionResourceNames);
        mv.visitCode();
        Label l0 = new Label();
        Label l1 = new Label();
        Label l2 = new Label();
        mv.visitTryCatchBlock(l0, l1, l2, "org/simantics/data/session/MethodInterface$ExecutionError");
        Label l3 = new Label();
        mv.visitTryCatchBlock(l0, l1, l3, "java/lang/InterruptedException");
        Label l4 = new Label();
        mv.visitLabel(l4);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, classResourceName, "methods",
                "[Lorg/simantics/data/session/MethodInterface$Method;");
        // Method m and puts into register 
        mv.visitLdcInsn(Integer.valueOf(methodNumber));
        mv.visitInsn(AALOAD);
        mv.visitVarInsn(ASTORE, argRegs + 1);
        Label l5 = new Label();
        mv.visitLabel(l5);
        mv.visitLdcInsn(Integer.valueOf(params.length));
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");

        int register = 1; // argument register   
        for (int i = 0; i < params.length; i++) {
            Class<?> clazz = params[i];
            mv.visitInsn(DUP);
            mv.visitLdcInsn(Integer.valueOf(i));

            if (clazz == byte.class) {
                mv.visitVarInsn(ILOAD, register++);
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
            } else if (clazz == char.class) {
                mv.visitVarInsn(ILOAD, register++);
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
            } else if (clazz == boolean.class) {
                mv.visitVarInsn(ILOAD, register++);
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
            } else if (clazz == byte.class) {
                mv.visitVarInsn(ILOAD, register++);
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
            } else if (clazz == int.class) {
                mv.visitVarInsn(ILOAD, register++);
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
            } else if (clazz == long.class) {
                mv.visitVarInsn(LLOAD, register);
                register += 2;
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(F)Ljava/lang/Long;");
            } else if (clazz == float.class) {
                mv.visitVarInsn(FLOAD, register);
                register += 2;
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
            } else if (clazz == Double.class) {
                mv.visitVarInsn(DLOAD, register);
                register += 2;
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
            } else {
                // Push argument to stack 
                mv.visitVarInsn(ALOAD, register++);
            }
            mv.visitInsn(AASTORE);
        }

        // Store args to argRegs+2
        mv.visitVarInsn(ASTORE, argRegs + 2);
        Label l6 = new Label();
        mv.visitLabel(l6);
        mv.visitVarInsn(ALOAD, argRegs + 1 /* m */);
        mv.visitVarInsn(ALOAD, argRegs + 2 /*args*/);
        mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/data/session/MethodInterface$Method", "invoke",
                "(Ljava/lang/Object;)Lorg/simantics/data/session/MethodInterface$AsyncResult;");
        mv.visitVarInsn(ASTORE, argRegs + 3);
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, argRegs + 3);
        mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/data/session/MethodInterface$AsyncResult",
                "waitForResponse", "()Ljava/lang/Object;");
        // TODO Return typecase result
        Class<?> returnType = m.getReturnType();

        if (returnType == void.class) {
            mv.visitInsn(POP);
            mv.visitInsn(RETURN);
        } else if (returnType == int.class) {
            mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
            mv.visitLabel(l1);
            mv.visitInsn(IRETURN);
        } else if (returnType == byte.class) {
            mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "B()");
            mv.visitLabel(l1);
            mv.visitInsn(IRETURN);
        } else if (returnType == char.class) {
            mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C");
            mv.visitLabel(l1);
            mv.visitInsn(IRETURN);
        } else if (returnType == boolean.class) {
            mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
            mv.visitLabel(l1);
            mv.visitInsn(IRETURN);
        } else if (returnType == short.class) {
            mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
            mv.visitLabel(l1);
            mv.visitInsn(IRETURN);
        } else if (returnType == long.class) {
            mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
            mv.visitLabel(l1);
            mv.visitInsn(LRETURN);
        } else if (returnType == double.class) {
            mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
            mv.visitLabel(l1);
            mv.visitInsn(DRETURN);
        } else if (returnType == float.class) {
            mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
            mv.visitLabel(l1);
            mv.visitInsn(FRETURN);
        } else {
            // Object
            mv.visitTypeInsn(CHECKCAST, returnType.getName().replaceAll("\\.", "/"));
            mv.visitLabel(l1);
            mv.visitInsn(ARETURN);
        }

        // Handle exceptions
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_FULL, argRegs + 4,
                new Object[] { classResourceName, "java/lang/Integer",
                        "org/simantics/data/session/MethodInterface$Method", "[Ljava/lang/Object;",
                        "org/simantics/data/session/MethodInterface$AsyncResult" },
                1, new Object[] { "org/simantics/data/session/MethodInterface$ExecutionError" });
        mv.visitVarInsn(ASTORE, argRegs + 4);
        Label l7 = new Label();
        mv.visitLabel(l7);
        mv.visitVarInsn(ALOAD, argRegs + 4);
        mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/data/session/MethodInterface$ExecutionError",
                "getError", "()Ljava/lang/Object;");
        mv.visitVarInsn(ASTORE, argRegs + 5); // argRegs+5 <- ExecutionError.cause

        Class<?>[] exceptionClasses = m.getExceptionTypes();
        Label nextException[] = new Label[exceptionClasses.length];
        for (int i = 0; i < exceptionClasses.length; i++) {
            Class<?> exceptionClass = exceptionClasses[i];
            String exceptionClassResourceName = exceptionClass.getName().replaceAll("\\.", "/");
            nextException[i] = new Label();
            // If instanceof MyException
            Label l8 = new Label();
            mv.visitLabel(l8);
            mv.visitVarInsn(ALOAD, argRegs + 5); // Cause
            mv.visitTypeInsn(INSTANCEOF, exceptionClassResourceName);
            mv.visitJumpInsn(IFEQ, nextException[i]); // If not, go to ExecutionError
            // If so, throw it
            mv.visitVarInsn(ALOAD, argRegs + 5); // e
            mv.visitTypeInsn(CHECKCAST, exceptionClassResourceName);
            mv.visitInsn(ATHROW);
            mv.visitLabel(nextException[i]);
        }

        // ExecutionError
        mv.visitFrame(
                Opcodes.F_APPEND, argRegs + 1, new Object[] {
                        "org/simantics/data/session/MethodInterface$ExecutionError", "java/lang/Object" },
                0, null);
        mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, argRegs + 4);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/Throwable;)V");
        mv.visitInsn(ATHROW);

        // InteruptedException
        mv.visitLabel(l3);
        mv.visitFrame(Opcodes.F_FULL, argRegs + 4,
                new Object[] { classResourceName, "java/lang/Integer",
                        "org/simantics/data/session/MethodInterface$Method", "[Ljava/lang/Object;",
                        "org/simantics/data/session/MethodInterface$AsyncResult" },
                1, new Object[] { "java/lang/InterruptedException" });
        mv.visitVarInsn(ASTORE, argRegs + 4);
        Label l10 = new Label();
        mv.visitLabel(l10);
        mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, argRegs + 4);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/Throwable;)V");
        mv.visitInsn(ATHROW);

        Label l11 = new Label();
        mv.visitLabel(l11);
        mv.visitLocalVariable("this", classTypeDescriptor, null, l4, l11, 0);
        //      mv.visitLocalVariable("arg1", "Ljava/lang/Integer;", null, l4, l11, 1);
        register = 1;
        for (int i = 0; i < params.length; i++) {
            Class<?> clazz = params[i];
            mv.visitLocalVariable("arg" + (i + 1), classToTypeDescriptor(clazz), null, l4, l11, register);
            register++;
            if (clazz == long.class || clazz == float.class || clazz == Double.class)
                argRegs++;
        }
        mv.visitLocalVariable("m", "Lorg/simantics/data/session/MethodInterface$Method;", null, l5, l11,
                argRegs + 1);
        mv.visitLocalVariable("args", "[Ljava/lang/Object;", null, l6, l11, argRegs + 2);
        mv.visitLocalVariable("result", "Lorg/simantics/data/session/MethodInterface$AsyncResult;", null, l0,
                l11, argRegs + 3);
        mv.visitLocalVariable("e", "Lorg/simantics/data/session/MethodInterface$ExecutionError;", null, l7, l3,
                argRegs + 4);
        mv.visitLocalVariable("cause", "Ljava/lang/Object;", null, l7, l3, argRegs + 5);
        mv.visitLocalVariable("e", "Ljava/lang/InterruptedException;", null, l10, l11, argRegs + 4);
        mv.visitMaxs(argRegs + 3, argRegs + 6);
        mv.visitEnd();
        methodNumber++;
    }

    cw.visitEnd();
}

From source file:org.sonatype.restsimple.jaxrs.impl.JAXRSServiceDefinitionGenerator.java

License:Open Source License

/**
 * Generate a JAX RS Resource on the fly, based on the information contained with a {@link ServiceDefinition}
 * @param serviceDefinition a {@link ServiceDefinition}
 */// w  w w  .  j  a v a2s.c  o m
@Override
public void generate(final ServiceDefinition serviceDefinition, ServiceHandlerMapper mapper) {

    for (ServiceHandler sh : serviceDefinition.serviceHandlers()) {
        mapper.addServiceHandler(serviceDefinition.path(), sh);
    }

    ClassWriter cw = new ClassWriter(0);
    FieldVisitor fv;
    MethodVisitor mv;
    AnnotationVisitor av0;

    String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 4);
    String className = "org/sonatype/restsimple/model/ServiceDescriptionResource" + uuid;

    cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, className, null, "java/lang/Object", null);

    {
        String path = serviceDefinition.path().contains("/:") ? convert(serviceDefinition.path())
                : serviceDefinition.path();
        logger.info("Generating jaxrs resource for {} with path {}", serviceDefinition, path);
        if (path == "") {
            path = "/";
        }
        av0 = cw.visitAnnotation("Ljavax/ws/rs/Path;", true);
        av0.visit("value", path);
        av0.visitEnd();
    }
    if (serviceDefinition.mediaToProduce().size() > 0) {
        {
            av0 = cw.visitAnnotation("Ljavax/ws/rs/Produces;", true);
            {
                AnnotationVisitor av1 = av0.visitArray("value");
                for (MediaType m : serviceDefinition.mediaToProduce()) {
                    av1.visit(null, m.toMediaType());
                }
                av1.visitEnd();
            }
            av0.visitEnd();
        }
    }
    if (serviceDefinition.mediaToConsume().size() > 0) {
        {
            av0 = cw.visitAnnotation("Ljavax/ws/rs/Consumes;", true);
            {
                AnnotationVisitor av1 = av0.visitArray("value");
                for (MediaType m : serviceDefinition.mediaToConsume()) {
                    av1.visit(null, m.toMediaType());
                }
                av1.visitEnd();
            }
            av0.visitEnd();
        }
    }
    cw.visitInnerClass("javax/ws/rs/core/Response$ResponseBuilder", "javax/ws/rs/core/Response",
            "ResponseBuilder", ACC_PUBLIC + ACC_STATIC + ACC_ABSTRACT);

    cw.visitInnerClass("javax/ws/rs/core/Response$Status", "javax/ws/rs/core/Response", "Status",
            ACC_PUBLIC + ACC_FINAL + ACC_STATIC + ACC_ENUM);

    cw.visitInnerClass("org/sonatype/restsimple/api/ServiceDefinition$HttpMethod",
            "org/sonatype/restsimple/api/ServiceDefinition", "HttpMethod",
            ACC_PUBLIC + ACC_FINAL + ACC_STATIC + ACC_ENUM);

    {
        fv = cw.visitField(ACC_PRIVATE, "logger", "Lorg/slf4j/Logger;", null, null);
        fv.visitEnd();
    }
    {
        fv = cw.visitField(0, "request", "Ljavax/servlet/http/HttpServletRequest;", null, null);
        {
            av0 = fv.visitAnnotation("Ljavax/ws/rs/core/Context;", true);
            av0.visitEnd();
        }
        fv.visitEnd();
    }
    {
        fv = cw.visitField(0, "mapper", "Lorg/sonatype/restsimple/spi/ServiceHandlerMapper;", null, null);
        {
            av0 = fv.visitAnnotation("Lcom/google/inject/Inject;", true);
            av0.visitEnd();
        }
        fv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
        mv.visitVarInsn(ALOAD, 0);
        mv.visitLdcInsn(Type.getType("L" + className + ";"));
        mv.visitMethodInsn(INVOKESTATIC, "org/slf4j/LoggerFactory", "getLogger",
                "(Ljava/lang/Class;)Lorg/slf4j/Logger;");
        mv.visitFieldInsn(PUTFIELD, className, "logger", "Lorg/slf4j/Logger;");
        mv.visitInsn(RETURN);
        mv.visitMaxs(2, 1);
        mv.visitEnd();
    }
    int duplicateCounter = -1;
    for (ServiceHandler serviceHandler : serviceDefinition.serviceHandlers()) {
        {
            String methodName = serviceHandler.getHttpMethod().name().toLowerCase();
            if (duplicateCounter++ >= 0) {
                methodName = methodName + duplicateCounter;
            }

            if (serviceHandler.getHttpMethod().name().equalsIgnoreCase("get")) {
                mv = cw.visitMethod(ACC_PUBLIC, methodName, "(Ljavax/ws/rs/core/UriInfo;)Ljava/lang/Object;",
                        null, null);
                {
                    String p = convert(serviceHandler.path());
                    if (!p.equals("/") && !p.isEmpty()) {
                        av0 = mv.visitAnnotation("Ljavax/ws/rs/Path;", true);
                        av0.visit("value", p);
                        av0.visitEnd();
                    }
                }
                {
                    av0 = mv.visitAnnotation("Ljavax/ws/rs/GET;", true);
                    av0.visitEnd();
                }
                if (serviceHandler.consumeMediaType() != null) {
                    {
                        av0 = mv.visitAnnotation("Ljavax/ws/rs/Consumes;", true);
                        {
                            AnnotationVisitor av1 = av0.visitArray("value");
                            av1.visit(null, serviceHandler.consumeMediaType().toMediaType());
                            av1.visitEnd();
                        }
                        av0.visitEnd();
                    }
                }
                if (serviceHandler.mediaToProduce().size() > 0) {
                    {
                        av0 = mv.visitAnnotation("Ljavax/ws/rs/Produces;", true);
                        {
                            AnnotationVisitor av1 = av0.visitArray("value");
                            for (MediaType m : serviceHandler.mediaToProduce()) {
                                av1.visit(null, m.toMediaType());
                            }
                            av1.visitEnd();
                        }
                        av0.visitEnd();
                    }
                }
                {
                    av0 = mv.visitParameterAnnotation(0, "Ljavax/ws/rs/core/Context;", true);
                    av0.visitEnd();
                }
                mv.visitCode();
                mv.visitVarInsn(ALOAD, 0);
                mv.visitLdcInsn("get");
                mv.visitVarInsn(ALOAD, 1);
                mv.visitInsn(ACONST_NULL);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKESPECIAL, className, "mapMatrixParam",
                        "(Ljavax/ws/rs/core/UriInfo;)Ljava/util/Map;");
                mv.visitInsn(ACONST_NULL);
                mv.visitMethodInsn(INVOKESPECIAL, className, "invokeAction",
                        "(Ljava/lang/String;Ljavax/ws/rs/core/UriInfo;Ljavax/ws/rs/core/MultivaluedMap;Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;");
                mv.visitVarInsn(ASTORE, 2);
                mv.visitVarInsn(ALOAD, 2);
                mv.visitInsn(ARETURN);
                mv.visitMaxs(6, 3);
                mv.visitEnd();
                continue;
            }
        }
        {
            if (serviceHandler.getHttpMethod().name().equalsIgnoreCase("head")) {

                {
                    String methodName = serviceHandler.getHttpMethod().name().toLowerCase();
                    if (duplicateCounter++ >= 0) {
                        methodName = methodName + "_" + duplicateCounter;
                    }
                    mv = cw.visitMethod(ACC_PUBLIC, methodName,
                            "(Ljavax/ws/rs/core/UriInfo;)Ljavax/ws/rs/core/Response;", null, null);
                    {
                        String p = convert(serviceHandler.path());
                        if (!p.equals("/") && !p.isEmpty()) {
                            av0 = mv.visitAnnotation("Ljavax/ws/rs/Path;", true);
                            av0.visit("value", p);
                            av0.visitEnd();
                        }
                    }
                    {
                        av0 = mv.visitAnnotation("Ljavax/ws/rs/HEAD;", true);
                        av0.visitEnd();
                    }
                    if (serviceHandler.consumeMediaType() != null) {
                        {
                            av0 = mv.visitAnnotation("Ljavax/ws/rs/Consumes;", true);
                            {
                                AnnotationVisitor av1 = av0.visitArray("value");
                                av1.visit(null, serviceHandler.consumeMediaType().toMediaType());
                                av1.visitEnd();
                            }
                            av0.visitEnd();
                        }
                    }
                    if (serviceHandler.mediaToProduce().size() > 0) {
                        {
                            av0 = mv.visitAnnotation("Ljavax/ws/rs/Produces;", true);
                            {
                                AnnotationVisitor av1 = av0.visitArray("value");
                                for (MediaType m : serviceHandler.mediaToProduce()) {
                                    av1.visit(null, m.toMediaType());
                                }
                                av1.visitEnd();
                            }
                            av0.visitEnd();
                        }
                    }
                    {
                        av0 = mv.visitParameterAnnotation(0, "Ljavax/ws/rs/core/Context;", true);
                        av0.visitEnd();
                    }
                    mv.visitCode();
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitLdcInsn("head");
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitInsn(ACONST_NULL);
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKESPECIAL, className, "mapMatrixParam",
                            "(Ljavax/ws/rs/core/UriInfo;)Ljava/util/Map;");
                    mv.visitInsn(ACONST_NULL);
                    mv.visitMethodInsn(INVOKESPECIAL, className, "invokeAction",
                            "(Ljava/lang/String;Ljavax/ws/rs/core/UriInfo;Ljavax/ws/rs/core/MultivaluedMap;Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;");
                    mv.visitVarInsn(ASTORE, 2);
                    mv.visitMethodInsn(INVOKESTATIC, "javax/ws/rs/core/Response", "ok",
                            "()Ljavax/ws/rs/core/Response$ResponseBuilder;");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "javax/ws/rs/core/Response$ResponseBuilder", "build",
                            "()Ljavax/ws/rs/core/Response;");
                    mv.visitInsn(ARETURN);
                    mv.visitMaxs(6, 3);
                    mv.visitEnd();
                    continue;
                }
            }
        }
        {
            if (serviceHandler.getHttpMethod().name().equalsIgnoreCase("put")) {

                {
                    String methodName = serviceHandler.getHttpMethod().name().toLowerCase();
                    if (duplicateCounter++ >= 0) {
                        methodName = methodName + "_" + duplicateCounter;
                    }

                    String methodType = serviceHandler.consumeClass() != null
                            ? serviceHandler.consumeClass().getName().replace(".", "/")
                            : "java/lang/String";
                    mv = cw.visitMethod(ACC_PUBLIC, methodName,
                            "(Ljavax/ws/rs/core/UriInfo;L" + methodType + ";)Ljavax/ws/rs/core/Response;", null,
                            null);
                    {
                        String p = convert(serviceHandler.path());
                        if (!p.equals("/") && !p.isEmpty()) {
                            av0 = mv.visitAnnotation("Ljavax/ws/rs/Path;", true);
                            av0.visit("value", p);
                            av0.visitEnd();
                        }
                    }
                    {
                        av0 = mv.visitAnnotation("Ljavax/ws/rs/PUT;", true);
                        av0.visitEnd();
                    }
                    if (serviceHandler.consumeMediaType() != null) {
                        {
                            av0 = mv.visitAnnotation("Ljavax/ws/rs/Consumes;", true);
                            {
                                AnnotationVisitor av1 = av0.visitArray("value");
                                av1.visit(null, serviceHandler.consumeMediaType().toMediaType());
                                av1.visitEnd();
                            }
                            av0.visitEnd();
                        }
                    }
                    if (serviceHandler.mediaToProduce().size() > 0) {
                        {
                            av0 = mv.visitAnnotation("Ljavax/ws/rs/Produces;", true);
                            {
                                AnnotationVisitor av1 = av0.visitArray("value");
                                for (MediaType m : serviceHandler.mediaToProduce()) {
                                    av1.visit(null, m.toMediaType());
                                }
                                av1.visitEnd();
                            }
                            av0.visitEnd();
                        }
                    }
                    {
                        av0 = mv.visitParameterAnnotation(0, "Ljavax/ws/rs/core/Context;", true);
                        av0.visitEnd();
                    }
                    mv.visitCode();
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
                    mv.visitMethodInsn(INVOKESTATIC, "javax/ws/rs/core/UriBuilder", "fromResource",
                            "(Ljava/lang/Class;)Ljavax/ws/rs/core/UriBuilder;");
                    mv.visitInsn(ICONST_3);
                    mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
                    mv.visitInsn(DUP);
                    mv.visitInsn(ICONST_0);
                    mv.visitLdcInsn("");
                    mv.visitInsn(AASTORE);
                    mv.visitInsn(DUP);
                    mv.visitInsn(ICONST_1);
                    mv.visitLdcInsn("");
                    mv.visitInsn(AASTORE);
                    mv.visitInsn(DUP);
                    mv.visitInsn(ICONST_2);
                    mv.visitLdcInsn("");
                    mv.visitInsn(AASTORE);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "javax/ws/rs/core/UriBuilder", "build",
                            "([Ljava/lang/Object;)Ljava/net/URI;");
                    mv.visitVarInsn(ASTORE, 3);
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitLdcInsn("put");
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKEINTERFACE, "javax/ws/rs/core/UriInfo", "getQueryParameters",
                            "()Ljavax/ws/rs/core/MultivaluedMap;");
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitMethodInsn(INVOKESPECIAL, className, "mapMatrixParam",
                            "(Ljavax/ws/rs/core/UriInfo;)Ljava/util/Map;");
                    mv.visitVarInsn(ALOAD, 2);
                    mv.visitMethodInsn(INVOKESPECIAL, className, "invokeAction",
                            "(Ljava/lang/String;Ljavax/ws/rs/core/UriInfo;Ljavax/ws/rs/core/MultivaluedMap;Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;");
                    mv.visitVarInsn(ASTORE, 4);
                    mv.visitVarInsn(ALOAD, 3);
                    mv.visitMethodInsn(INVOKESTATIC, "javax/ws/rs/core/Response", "created",
                            "(Ljava/net/URI;)Ljavax/ws/rs/core/Response$ResponseBuilder;");
                    mv.visitVarInsn(ALOAD, 4);
                    mv.visitMethodInsn(INVOKEVIRTUAL, "javax/ws/rs/core/Response$ResponseBuilder", "entity",
                            "(Ljava/lang/Object;)Ljavax/ws/rs/core/Response$ResponseBuilder;");
                    mv.visitMethodInsn(INVOKEVIRTUAL, "javax/ws/rs/core/Response$ResponseBuilder", "build",
                            "()Ljavax/ws/rs/core/Response;");
                    mv.visitInsn(ARETURN);
                    mv.visitMaxs(6, 5);
                    mv.visitEnd();
                    continue;
                }
            }
            {
                if (serviceHandler.getHttpMethod().name().equalsIgnoreCase("post")) {

                    String methodName = serviceHandler.getHttpMethod().name().toLowerCase();
                    if (duplicateCounter++ >= 0) {
                        methodName = methodName + "_" + duplicateCounter;
                    }

                    List<String> formsParam = PostServiceHandler.class.cast(serviceHandler).formParams();
                    if (formsParam.size() > 0) {
                        {
                            mv = cw.visitMethod(ACC_PUBLIC, methodName,
                                    "(Ljavax/ws/rs/core/UriInfo;Ljavax/ws/rs/core/MultivaluedMap;)Ljavax/ws/rs/core/Response;",
                                    "(Ljavax/ws/rs/core/UriInfo;Ljavax/ws/rs/core/MultivaluedMap<Ljava/lang/String;Ljava/lang/String;>;)Ljavax/ws/rs/core/Response;",
                                    null);
                            {
                                String p = convert(serviceHandler.path());
                                if (!p.equals("/") && !p.isEmpty()) {
                                    av0 = mv.visitAnnotation("Ljavax/ws/rs/Path;", true);
                                    av0.visit("value", p);
                                    av0.visitEnd();
                                }
                            }
                            {
                                av0 = mv.visitAnnotation("Ljavax/ws/rs/POST;", true);
                                av0.visitEnd();
                            }
                            {
                                av0 = mv.visitAnnotation("Ljavax/ws/rs/Consumes;", true);
                                {
                                    AnnotationVisitor av1 = av0.visitArray("value");
                                    av1.visit(null, "application/x-www-form-urlencoded");
                                    av1.visitEnd();
                                }
                                av0.visitEnd();
                            }
                            if (serviceHandler.mediaToProduce().size() > 0) {
                                {
                                    av0 = mv.visitAnnotation("Ljavax/ws/rs/Produces;", true);
                                    {
                                        AnnotationVisitor av1 = av0.visitArray("value");
                                        for (MediaType m : serviceHandler.mediaToProduce()) {
                                            av1.visit(null, m.toMediaType());
                                        }
                                        av1.visitEnd();
                                    }
                                    av0.visitEnd();
                                }
                            }
                            {
                                av0 = mv.visitParameterAnnotation(0, "Ljavax/ws/rs/core/Context;", true);
                                av0.visitEnd();
                            }
                            mv.visitCode();
                            mv.visitVarInsn(ALOAD, 0);
                            mv.visitLdcInsn("post");
                            mv.visitVarInsn(ALOAD, 1);
                            mv.visitVarInsn(ALOAD, 2);
                            mv.visitVarInsn(ALOAD, 0);
                            mv.visitVarInsn(ALOAD, 1);
                            mv.visitMethodInsn(INVOKESPECIAL, className, "mapMatrixParam",
                                    "(Ljavax/ws/rs/core/UriInfo;)Ljava/util/Map;");
                            mv.visitInsn(ACONST_NULL);
                            mv.visitMethodInsn(INVOKESPECIAL, className, "invokeAction",
                                    "(Ljava/lang/String;Ljavax/ws/rs/core/UriInfo;Ljavax/ws/rs/core/MultivaluedMap;Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;");
                            mv.visitVarInsn(ASTORE, 3);
                            mv.visitVarInsn(ALOAD, 3);
                            Label l0 = new Label();
                            mv.visitJumpInsn(IFNONNULL, l0);
                            mv.visitFieldInsn(GETSTATIC, "javax/ws/rs/core/Response$Status", "NO_CONTENT",
                                    "Ljavax/ws/rs/core/Response$Status;");
                            mv.visitMethodInsn(INVOKESTATIC, "javax/ws/rs/core/Response", "status",
                                    "(Ljavax/ws/rs/core/Response$Status;)Ljavax/ws/rs/core/Response$ResponseBuilder;");
                            mv.visitMethodInsn(INVOKEVIRTUAL, "javax/ws/rs/core/Response$ResponseBuilder",
                                    "build", "()Ljavax/ws/rs/core/Response;");
                            mv.visitInsn(ARETURN);
                            mv.visitLabel(l0);
                            mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { "java/lang/Object" }, 0, null);
                            mv.visitVarInsn(ALOAD, 3);
                            mv.visitMethodInsn(INVOKESTATIC, "javax/ws/rs/core/Response", "ok",
                                    "(Ljava/lang/Object;)Ljavax/ws/rs/core/Response$ResponseBuilder;");
                            mv.visitMethodInsn(INVOKEVIRTUAL, "javax/ws/rs/core/Response$ResponseBuilder",
                                    "build", "()Ljavax/ws/rs/core/Response;");
                            mv.visitInsn(ARETURN);
                            mv.visitMaxs(6, 4);
                            mv.visitEnd();
                            continue;
                        }
                    } else {
                        String methodType = serviceHandler.consumeClass() != null
                                ? serviceHandler.consumeClass().getName().replace(".", "/")
                                : "java/lang/String";
                        mv = cw.visitMethod(ACC_PUBLIC, methodName,
                                "(Ljavax/ws/rs/core/UriInfo;L" + methodType + ";)Ljavax/ws/rs/core/Response;",
                                null, null);
                        {
                            String p = convert(serviceHandler.path());
                            if (!p.equals("/") && !p.isEmpty()) {
                                av0 = mv.visitAnnotation("Ljavax/ws/rs/Path;", true);
                                av0.visit("value", p);
                                av0.visitEnd();
                            }
                        }
                        {
                            av0 = mv.visitAnnotation("Ljavax/ws/rs/POST;", true);
                            av0.visitEnd();
                        }
                        if (serviceHandler.mediaToProduce().size() > 0) {
                            {
                                av0 = mv.visitAnnotation("Ljavax/ws/rs/Produces;", true);
                                {
                                    AnnotationVisitor av1 = av0.visitArray("value");
                                    for (MediaType m : serviceHandler.mediaToProduce()) {
                                        av1.visit(null, m.toMediaType());
                                    }
                                    av1.visitEnd();
                                }
                                av0.visitEnd();
                            }
                        }
                        if (serviceHandler.consumeMediaType() != null) {
                            {
                                av0 = mv.visitAnnotation("Ljavax/ws/rs/Consumes;", true);
                                {
                                    AnnotationVisitor av1 = av0.visitArray("value");
                                    av1.visit(null, serviceHandler.consumeMediaType().toMediaType());
                                    av1.visitEnd();
                                }
                                av0.visitEnd();
                            }
                        }
                        {
                            av0 = mv.visitParameterAnnotation(0, "Ljavax/ws/rs/core/Context;", true);
                            av0.visitEnd();
                        }
                        mv.visitCode();
                        mv.visitVarInsn(ALOAD, 0);
                        mv.visitLdcInsn("post");
                        mv.visitVarInsn(ALOAD, 1);
                        mv.visitVarInsn(ALOAD, 1);
                        mv.visitMethodInsn(INVOKEINTERFACE, "javax/ws/rs/core/UriInfo", "getQueryParameters",
                                "()Ljavax/ws/rs/core/MultivaluedMap;");
                        mv.visitVarInsn(ALOAD, 0);
                        mv.visitVarInsn(ALOAD, 1);
                        mv.visitMethodInsn(INVOKESPECIAL, className, "mapMatrixParam",
                                "(Ljavax/ws/rs/core/UriInfo;)Ljava/util/Map;");
                        mv.visitVarInsn(ALOAD, 2);
                        mv.visitMethodInsn(INVOKESPECIAL, className, "invokeAction",
                                "(Ljava/lang/String;Ljavax/ws/rs/core/UriInfo;Ljavax/ws/rs/core/MultivaluedMap;Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;");
                        mv.visitVarInsn(ASTORE, 3);
                        mv.visitVarInsn(ALOAD, 3);
                        Label l0 = new Label();
                        mv.visitJumpInsn(IFNONNULL, l0);
                        mv.visitFieldInsn(GETSTATIC, "javax/ws/rs/core/Response$Status", "NO_CONTENT",
                                "Ljavax/ws/rs/core/Response$Status;");
                        mv.visitMethodInsn(INVOKESTATIC, "javax/ws/rs/core/Response", "status",
                                "(Ljavax/ws/rs/core/Response$Status;)Ljavax/ws/rs/core/Response$ResponseBuilder;");
                        mv.visitMethodInsn(INVOKEVIRTUAL, "javax/ws/rs/core/Response$ResponseBuilder", "build",
                                "()Ljavax/ws/rs/core/Response;");
                        mv.visitInsn(ARETURN);
                        mv.visitLabel(l0);
                        mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { "java/lang/Object" }, 0, null);
                        mv.visitVarInsn(ALOAD, 3);
                        mv.visitMethodInsn(INVOKESTATIC, "javax/ws/rs/core/Response", "ok",
                                "(Ljava/lang/Object;)Ljavax/ws/rs/core/Response$ResponseBuilder;");
                        mv.visitMethodInsn(INVOKEVIRTUAL, "javax/ws/rs/core/Response$ResponseBuilder", "build",
                                "()Ljavax/ws/rs/core/Response;");
                        mv.visitInsn(ARETURN);
                        mv.visitMaxs(6, 4);
                        mv.visitEnd();
                        continue;
                    }
                }
            }
            {
                if (serviceHandler.getHttpMethod().name().equalsIgnoreCase("delete")) {
                    {
                        String methodName = serviceHandler.getHttpMethod().name().toLowerCase();
                        if (duplicateCounter++ >= 0) {
                            methodName = methodName + "_" + duplicateCounter;
                        }
                        String methodType = serviceHandler.consumeClass() != null
                                ? serviceHandler.consumeClass().getName().replace(".", "/")
                                : "java/lang/String";
                        mv = cw.visitMethod(ACC_PUBLIC, methodName,
                                "(Ljavax/ws/rs/core/UriInfo;L" + methodType + ";)Ljavax/ws/rs/core/Response;",
                                null, null);

                        {
                            String p = convert(serviceHandler.path());
                            if (!p.equals("/") && !p.isEmpty()) {
                                av0 = mv.visitAnnotation("Ljavax/ws/rs/Path;", true);
                                av0.visit("value", p);
                                av0.visitEnd();
                            }
                        }
                        {
                            av0 = mv.visitAnnotation("Ljavax/ws/rs/DELETE;", true);
                            av0.visitEnd();
                        }
                        if (serviceHandler.mediaToProduce().size() > 0) {
                            {
                                av0 = mv.visitAnnotation("Ljavax/ws/rs/Produces;", true);
                                {
                                    AnnotationVisitor av1 = av0.visitArray("value");
                                    for (MediaType m : serviceHandler.mediaToProduce()) {
                                        av1.visit(null, m.toMediaType());
                                    }
                                    av1.visitEnd();
                                }
                                av0.visitEnd();
                            }
                        }
                        if (serviceHandler.consumeMediaType() != null) {
                            {
                                av0 = mv.visitAnnotation("Ljavax/ws/rs/Consumes;", true);
                                {
                                    AnnotationVisitor av1 = av0.visitArray("value");
                                    av1.visit(null, serviceHandler.consumeMediaType().toMediaType());
                                    av1.visitEnd();
                                }
                                av0.visitEnd();
                            }
                        }
                        {
                            av0 = mv.visitParameterAnnotation(0, "Ljavax/ws/rs/core/Context;", true);
                            av0.visitEnd();
                        }
                        mv.visitCode();
                        mv.visitVarInsn(ALOAD, 0);
                        mv.visitLdcInsn("delete");
                        mv.visitVarInsn(ALOAD, 1);
                        mv.visitInsn(ACONST_NULL);
                        mv.visitVarInsn(ALOAD, 0);
                        mv.visitVarInsn(ALOAD, 1);
                        mv.visitMethodInsn(INVOKESPECIAL, className, "mapMatrixParam",
                                "(Ljavax/ws/rs/core/UriInfo;)Ljava/util/Map;");
                        mv.visitVarInsn(ALOAD, 2);
                        mv.visitMethodInsn(INVOKESPECIAL, className, "invokeAction",
                                "(Ljava/lang/String;Ljavax/ws/rs/core/UriInfo;Ljavax/ws/rs/core/MultivaluedMap;Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;");
                        mv.visitVarInsn(ASTORE, 3);
                        mv.visitVarInsn(ALOAD, 3);
                        mv.visitMethodInsn(INVOKESTATIC, "javax/ws/rs/core/Response", "ok",
                                "(Ljava/lang/Object;)Ljavax/ws/rs/core/Response$ResponseBuilder;");
                        mv.visitMethodInsn(INVOKEVIRTUAL, "javax/ws/rs/core/Response$ResponseBuilder", "build",
                                "()Ljavax/ws/rs/core/Response;");
                        mv.visitInsn(ARETURN);
                        mv.visitMaxs(6, 4);
                        mv.visitEnd();
                        continue;
                    }
                }
            }
        }
    }
    {
        mv = cw.visitMethod(ACC_PRIVATE, "invokeAction",
                "(Ljava/lang/String;Ljavax/ws/rs/core/UriInfo;Ljavax/ws/rs/core/MultivaluedMap;Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;",
                "<T:Ljava/lang/Object;>(Ljava/lang/String;Ljavax/ws/rs/core/UriInfo;Ljavax/ws/rs/core/MultivaluedMap<Ljava/lang/String;Ljava/lang/String;>;Ljava/util/Map<Ljava/lang/String;Ljava/util/Collection<Ljava/lang/String;>;>;TT;)Ljava/lang/Object;",
                null);
        mv.visitCode();
        Label l0 = new Label();
        Label l1 = new Label();
        Label l2 = new Label();
        mv.visitTryCatchBlock(l0, l1, l2, "org/sonatype/restsimple/api/ActionException");
        Label l3 = new Label();
        mv.visitTryCatchBlock(l0, l1, l3, "java/lang/Throwable");
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, className, "mapper", "Lorg/sonatype/restsimple/spi/ServiceHandlerMapper;");
        mv.visitVarInsn(ALOAD, 1);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/ws/rs/core/UriInfo", "getPath", "()Ljava/lang/String;");
        mv.visitMethodInsn(INVOKEVIRTUAL, "org/sonatype/restsimple/spi/ServiceHandlerMapper", "map",
                "(Ljava/lang/String;Ljava/lang/String;)Lorg/sonatype/restsimple/api/ServiceHandler;");
        mv.visitVarInsn(ASTORE, 6);
        mv.visitVarInsn(ALOAD, 6);
        Label l4 = new Label();
        mv.visitJumpInsn(IFNONNULL, l4);
        mv.visitTypeInsn(NEW, "javax/ws/rs/WebApplicationException");
        mv.visitInsn(DUP);
        mv.visitIntInsn(SIPUSH, 405);
        mv.visitMethodInsn(INVOKESTATIC, "javax/ws/rs/core/Response", "status",
                "(I)Ljavax/ws/rs/core/Response$ResponseBuilder;");
        mv.visitLdcInsn("Method not allowed");
        mv.visitMethodInsn(INVOKEVIRTUAL, "javax/ws/rs/core/Response$ResponseBuilder", "entity",
                "(Ljava/lang/Object;)Ljavax/ws/rs/core/Response$ResponseBuilder;");
        mv.visitMethodInsn(INVOKEVIRTUAL, "javax/ws/rs/core/Response$ResponseBuilder", "build",
                "()Ljavax/ws/rs/core/Response;");
        mv.visitMethodInsn(INVOKESPECIAL, "javax/ws/rs/WebApplicationException", "<init>",
                "(Ljavax/ws/rs/core/Response;)V");
        mv.visitInsn(ATHROW);
        mv.visitLabel(l4);
        mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { "org/sonatype/restsimple/api/ServiceHandler" }, 0,
                null);
        mv.visitVarInsn(ALOAD, 6);
        mv.visitMethodInsn(INVOKEVIRTUAL, "org/sonatype/restsimple/api/ServiceHandler", "getHttpMethod",
                "()Lorg/sonatype/restsimple/api/ServiceDefinition$METHOD;");
        mv.visitMethodInsn(INVOKEVIRTUAL, "org/sonatype/restsimple/api/ServiceDefinition$METHOD", "name",
                "()Ljava/lang/String;");
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equalsIgnoreCase", "(Ljava/lang/String;)Z");
        Label l5 = new Label();
        mv.visitJumpInsn(IFNE, l5);
        mv.visitTypeInsn(NEW, "javax/ws/rs/WebApplicationException");
        mv.visitInsn(DUP);
        mv.visitIntInsn(SIPUSH, 405);
        mv.visitMethodInsn(INVOKESTATIC, "javax/ws/rs/core/Response", "status",
                "(I)Ljavax/ws/rs/core/Response$ResponseBuilder;");
        mv.visitLdcInsn("Method not allowed");
        mv.visitMethodInsn(INVOKEVIRTUAL, "javax/ws/rs/core/Response$ResponseBuilder", "entity",
                "(Ljava/lang/Object;)Ljavax/ws/rs/core/Response$ResponseBuilder;");
        mv.visitMethodInsn(INVOKEVIRTUAL, "javax/ws/rs/core/Response$ResponseBuilder", "build",
                "()Ljavax/ws/rs/core/Response;");
        mv.visitMethodInsn(INVOKESPECIAL, "javax/ws/rs/WebApplicationException", "<init>",
                "(Ljavax/ws/rs/core/Response;)V");
        mv.visitInsn(ATHROW);
        mv.visitLabel(l5);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitInsn(ACONST_NULL);
        mv.visitVarInsn(ASTORE, 7);
        mv.visitVarInsn(ALOAD, 6);
        mv.visitMethodInsn(INVOKEVIRTUAL, "org/sonatype/restsimple/api/ServiceHandler", "getAction",
                "()Lorg/sonatype/restsimple/api/Action;");
        mv.visitVarInsn(ASTORE, 8);
        mv.visitTypeInsn(NEW, "java/util/HashMap");
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashMap", "<init>", "()V");
        mv.visitVarInsn(ASTORE, 9);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/ws/rs/core/UriInfo", "getPathParameters",
                "()Ljavax/ws/rs/core/MultivaluedMap;");
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/ws/rs/core/MultivaluedMap", "entrySet", "()Ljava/util/Set;");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Set", "iterator", "()Ljava/util/Iterator;");
        mv.visitVarInsn(ASTORE, 10);
        Label l6 = new Label();
        mv.visitLabel(l6);
        mv.visitFrame(Opcodes.F_FULL, 11,
                new Object[] { className, "java/lang/String", "javax/ws/rs/core/UriInfo",
                        "javax/ws/rs/core/MultivaluedMap", "java/util/Map", "java/lang/Object",
                        "org/sonatype/restsimple/api/ServiceHandler", "java/lang/Object",
                        "org/sonatype/restsimple/api/Action", "java/util/Map", "java/util/Iterator" },
                0, new Object[] {});
        mv.visitVarInsn(ALOAD, 10);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z");
        mv.visitJumpInsn(IFEQ, l0);
        mv.visitVarInsn(ALOAD, 10);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;");
        mv.visitTypeInsn(CHECKCAST, "java/util/Map$Entry");
        mv.visitVarInsn(ASTORE, 11);
        mv.visitVarInsn(ALOAD, 9);
        mv.visitVarInsn(ALOAD, 11);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map$Entry", "getKey", "()Ljava/lang/Object;");
        mv.visitVarInsn(ALOAD, 11);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map$Entry", "getValue", "()Ljava/lang/Object;");
        mv.visitTypeInsn(CHECKCAST, "java/util/List");
        mv.visitInsn(ICONST_0);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put",
                "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitInsn(POP);
        mv.visitJumpInsn(GOTO, l6);
        mv.visitLabel(l0);
        mv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);
        mv.visitTypeInsn(NEW, "org/sonatype/restsimple/api/ActionContext");
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, className, "request", "Ljavax/servlet/http/HttpServletRequest;");
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/servlet/http/HttpServletRequest", "getMethod",
                "()Ljava/lang/String;");
        mv.visitMethodInsn(INVOKESPECIAL, className, "mapMethod",
                "(Ljava/lang/String;)Lorg/sonatype/restsimple/api/ServiceDefinition$METHOD;");
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, className, "mapHeaders", "()Ljava/util/Map;");
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKESPECIAL, className, "mapFormParams",
                "(Ljavax/ws/rs/core/MultivaluedMap;)Ljava/util/Map;");
        mv.visitVarInsn(ALOAD, 4);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, className, "request", "Ljavax/servlet/http/HttpServletRequest;");
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/servlet/http/HttpServletRequest", "getInputStream",
                "()Ljavax/servlet/ServletInputStream;");
        mv.visitVarInsn(ALOAD, 9);
        mv.visitVarInsn(ALOAD, 5);
        mv.visitMethodInsn(INVOKESPECIAL, "org/sonatype/restsimple/api/ActionContext", "<init>",
                "(Lorg/sonatype/restsimple/api/ServiceDefinition$METHOD;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/io/InputStream;Ljava/util/Map;Ljava/lang/Object;)V");
        mv.visitVarInsn(ASTORE, 10);
        mv.visitVarInsn(ALOAD, 8);
        mv.visitVarInsn(ALOAD, 10);
        mv.visitMethodInsn(INVOKEINTERFACE, "org/sonatype/restsimple/api/Action", "action",
                "(Lorg/sonatype/restsimple/api/ActionContext;)Ljava/lang/Object;");
        mv.visitVarInsn(ASTORE, 7);
        mv.visitLabel(l1);
        Label l7 = new Label();
        mv.visitJumpInsn(GOTO, l7);
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1,
                new Object[] { "org/sonatype/restsimple/api/ActionException" });
        mv.visitVarInsn(ASTORE, 10);
        mv.visitTypeInsn(NEW, "javax/ws/rs/WebApplicationException");
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 10);
        mv.visitVarInsn(ALOAD, 10);
        mv.visitMethodInsn(INVOKEVIRTUAL, "org/sonatype/restsimple/api/ActionException", "getStatusCode",
                "()I");
        mv.visitMethodInsn(INVOKESPECIAL, "javax/ws/rs/WebApplicationException", "<init>",
                "(Ljava/lang/Throwable;I)V");
        mv.visitInsn(ATHROW);
        mv.visitLabel(l3);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Throwable" });
        mv.visitVarInsn(ASTORE, 10);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, className, "logger", "Lorg/slf4j/Logger;");
        mv.visitLdcInsn("invokeAction");
        mv.visitVarInsn(ALOAD, 10);
        mv.visitMethodInsn(INVOKEINTERFACE, "org/slf4j/Logger", "error",
                "(Ljava/lang/String;Ljava/lang/Throwable;)V");
        mv.visitTypeInsn(NEW, "javax/ws/rs/WebApplicationException");
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 10);
        mv.visitMethodInsn(INVOKESPECIAL, "javax/ws/rs/WebApplicationException", "<init>",
                "(Ljava/lang/Throwable;)V");
        mv.visitInsn(ATHROW);
        mv.visitLabel(l7);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitVarInsn(ALOAD, 7);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(9, 12);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PRIVATE, "mapFormParams", "(Ljavax/ws/rs/core/MultivaluedMap;)Ljava/util/Map;",
                "(Ljavax/ws/rs/core/MultivaluedMap<Ljava/lang/String;Ljava/lang/String;>;)Ljava/util/Map<Ljava/lang/String;Ljava/util/Collection<Ljava/lang/String;>;>;",
                null);
        mv.visitCode();
        mv.visitTypeInsn(NEW, "java/util/HashMap");
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashMap", "<init>", "()V");
        mv.visitVarInsn(ASTORE, 2);
        mv.visitVarInsn(ALOAD, 1);
        Label l0 = new Label();
        mv.visitJumpInsn(IFNULL, l0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/ws/rs/core/MultivaluedMap", "keySet", "()Ljava/util/Set;");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Set", "iterator", "()Ljava/util/Iterator;");
        mv.visitVarInsn(ASTORE, 3);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitFrame(Opcodes.F_APPEND, 2, new Object[] { "java/util/Map", "java/util/Iterator" }, 0, null);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z");
        mv.visitJumpInsn(IFEQ, l0);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;");
        mv.visitTypeInsn(CHECKCAST, "java/lang/String");
        mv.visitVarInsn(ASTORE, 4);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitVarInsn(ALOAD, 4);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
        Label l2 = new Label();
        mv.visitJumpInsn(IFNULL, l2);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitVarInsn(ALOAD, 4);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitTypeInsn(CHECKCAST, "java/util/Collection");
        mv.visitVarInsn(ALOAD, 1);
        mv.visitVarInsn(ALOAD, 4);
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/ws/rs/core/MultivaluedMap", "get",
                "(Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitTypeInsn(CHECKCAST, "java/util/Collection");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Collection", "addAll", "(Ljava/util/Collection;)Z");
        mv.visitInsn(POP);
        Label l3 = new Label();
        mv.visitJumpInsn(GOTO, l3);
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { "java/lang/String" }, 0, null);
        mv.visitTypeInsn(NEW, "java/util/ArrayList");
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V");
        mv.visitVarInsn(ASTORE, 5);
        mv.visitVarInsn(ALOAD, 5);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitVarInsn(ALOAD, 4);
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/ws/rs/core/MultivaluedMap", "get",
                "(Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitTypeInsn(CHECKCAST, "java/util/Collection");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "addAll", "(Ljava/util/Collection;)Z");
        mv.visitInsn(POP);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitVarInsn(ALOAD, 4);
        mv.visitVarInsn(ALOAD, 5);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put",
                "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitInsn(POP);
        mv.visitLabel(l3);
        mv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);
        mv.visitJumpInsn(GOTO, l1);
        mv.visitLabel(l0);
        mv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(3, 6);
        mv.visitEnd();
    }

    {
        mv = cw.visitMethod(ACC_PRIVATE, "mapMethod",
                "(Ljava/lang/String;)Lorg/sonatype/restsimple/api/ServiceDefinition$METHOD;", null, null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 1);
        mv.visitLdcInsn("GET");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equalsIgnoreCase", "(Ljava/lang/String;)Z");
        Label l0 = new Label();
        mv.visitJumpInsn(IFEQ, l0);
        mv.visitFieldInsn(GETSTATIC, "org/sonatype/restsimple/api/ServiceDefinition$METHOD", "GET",
                "Lorg/sonatype/restsimple/api/ServiceDefinition$METHOD;");
        mv.visitInsn(ARETURN);
        mv.visitLabel(l0);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitLdcInsn("PUT");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equalsIgnoreCase", "(Ljava/lang/String;)Z");
        Label l1 = new Label();
        mv.visitJumpInsn(IFEQ, l1);
        mv.visitFieldInsn(GETSTATIC, "org/sonatype/restsimple/api/ServiceDefinition$METHOD", "PUT",
                "Lorg/sonatype/restsimple/api/ServiceDefinition$METHOD;");
        mv.visitInsn(ARETURN);
        mv.visitLabel(l1);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitLdcInsn("POST");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equalsIgnoreCase", "(Ljava/lang/String;)Z");
        Label l2 = new Label();
        mv.visitJumpInsn(IFEQ, l2);
        mv.visitFieldInsn(GETSTATIC, "org/sonatype/restsimple/api/ServiceDefinition$METHOD", "POST",
                "Lorg/sonatype/restsimple/api/ServiceDefinition$METHOD;");
        mv.visitInsn(ARETURN);
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitLdcInsn("DELETE");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equalsIgnoreCase", "(Ljava/lang/String;)Z");
        Label l3 = new Label();
        mv.visitJumpInsn(IFEQ, l3);
        mv.visitFieldInsn(GETSTATIC, "org/sonatype/restsimple/api/ServiceDefinition$METHOD", "DELETE",
                "Lorg/sonatype/restsimple/api/ServiceDefinition$METHOD;");
        mv.visitInsn(ARETURN);
        mv.visitLabel(l3);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitLdcInsn("HEAD");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equalsIgnoreCase", "(Ljava/lang/String;)Z");
        Label l4 = new Label();
        mv.visitJumpInsn(IFEQ, l4);
        mv.visitFieldInsn(GETSTATIC, "org/sonatype/restsimple/api/ServiceDefinition$METHOD", "HEAD",
                "Lorg/sonatype/restsimple/api/ServiceDefinition$METHOD;");
        mv.visitInsn(ARETURN);
        mv.visitLabel(l4);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
        mv.visitInsn(DUP);
        mv.visitLdcInsn("Invalid Method");
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>", "(Ljava/lang/String;)V");
        mv.visitInsn(ATHROW);
        mv.visitMaxs(3, 2);
        mv.visitEnd();
    }

    {
        mv = cw.visitMethod(ACC_PRIVATE, "mapHeaders", "()Ljava/util/Map;",
                "()Ljava/util/Map<Ljava/lang/String;Ljava/util/Collection<Ljava/lang/String;>;>;", null);
        mv.visitCode();
        mv.visitTypeInsn(NEW, "java/util/HashMap");
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashMap", "<init>", "()V");
        mv.visitVarInsn(ASTORE, 1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, className, "request", "Ljavax/servlet/http/HttpServletRequest;");
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/servlet/http/HttpServletRequest", "getHeaderNames",
                "()Ljava/util/Enumeration;");
        mv.visitVarInsn(ASTORE, 2);
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitFrame(Opcodes.F_APPEND, 2, new Object[] { "java/util/Map", "java/util/Enumeration" }, 0, null);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Enumeration", "hasMoreElements", "()Z");
        Label l1 = new Label();
        mv.visitJumpInsn(IFEQ, l1);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Enumeration", "nextElement", "()Ljava/lang/Object;");
        mv.visitTypeInsn(CHECKCAST, "java/lang/String");
        mv.visitVarInsn(ASTORE, 3);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
        Label l2 = new Label();
        mv.visitJumpInsn(IFNULL, l2);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitTypeInsn(CHECKCAST, "java/util/Collection");
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, className, "request", "Ljavax/servlet/http/HttpServletRequest;");
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/servlet/http/HttpServletRequest", "getHeader",
                "(Ljava/lang/String;)Ljava/lang/String;");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Collection", "add", "(Ljava/lang/Object;)Z");
        mv.visitInsn(POP);
        mv.visitJumpInsn(GOTO, l0);
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { "java/lang/String" }, 0, null);
        mv.visitTypeInsn(NEW, "java/util/ArrayList");
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V");
        mv.visitVarInsn(ASTORE, 4);
        mv.visitVarInsn(ALOAD, 4);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, className, "request", "Ljavax/servlet/http/HttpServletRequest;");
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/servlet/http/HttpServletRequest", "getHeader",
                "(Ljava/lang/String;)Ljava/lang/String;");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z");
        mv.visitInsn(POP);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitVarInsn(ALOAD, 4);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put",
                "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitInsn(POP);
        mv.visitJumpInsn(GOTO, l0);
        mv.visitLabel(l1);
        mv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKESTATIC, "java/util/Collections", "unmodifiableMap",
                "(Ljava/util/Map;)Ljava/util/Map;");
        mv.visitInsn(ARETURN);
        mv.visitMaxs(3, 5);
        mv.visitEnd();
    }

    {
        mv = cw.visitMethod(ACC_PRIVATE, "mapMatrixParam", "(Ljavax/ws/rs/core/UriInfo;)Ljava/util/Map;",
                "(Ljavax/ws/rs/core/UriInfo;)Ljava/util/Map<Ljava/lang/String;Ljava/util/Collection<Ljava/lang/String;>;>;",
                null);
        mv.visitCode();
        mv.visitTypeInsn(NEW, "java/util/HashMap");
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashMap", "<init>", "()V");
        mv.visitVarInsn(ASTORE, 2);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/ws/rs/core/UriInfo", "getPathSegments",
                "()Ljava/util/List;");
        mv.visitVarInsn(ASTORE, 3);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "iterator", "()Ljava/util/Iterator;");
        mv.visitVarInsn(ASTORE, 4);
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitFrame(Opcodes.F_APPEND, 3,
                new Object[] { "java/util/Map", "java/util/List", "java/util/Iterator" }, 0, null);
        mv.visitVarInsn(ALOAD, 4);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z");
        Label l1 = new Label();
        mv.visitJumpInsn(IFEQ, l1);
        mv.visitVarInsn(ALOAD, 4);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;");
        mv.visitTypeInsn(CHECKCAST, "javax/ws/rs/core/PathSegment");
        mv.visitVarInsn(ASTORE, 5);
        mv.visitVarInsn(ALOAD, 5);
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/ws/rs/core/PathSegment", "getMatrixParameters",
                "()Ljavax/ws/rs/core/MultivaluedMap;");
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/ws/rs/core/MultivaluedMap", "keySet", "()Ljava/util/Set;");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Set", "iterator", "()Ljava/util/Iterator;");
        mv.visitVarInsn(ASTORE, 6);
        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_APPEND, 2,
                new Object[] { "javax/ws/rs/core/PathSegment", "java/util/Iterator" }, 0, null);
        mv.visitVarInsn(ALOAD, 6);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z");
        Label l3 = new Label();
        mv.visitJumpInsn(IFEQ, l3);
        mv.visitVarInsn(ALOAD, 6);
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;");
        mv.visitTypeInsn(CHECKCAST, "java/lang/String");
        mv.visitVarInsn(ASTORE, 7);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitVarInsn(ALOAD, 7);
        mv.visitVarInsn(ALOAD, 5);
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/ws/rs/core/PathSegment", "getMatrixParameters",
                "()Ljavax/ws/rs/core/MultivaluedMap;");
        mv.visitVarInsn(ALOAD, 7);
        mv.visitMethodInsn(INVOKEINTERFACE, "javax/ws/rs/core/MultivaluedMap", "get",
                "(Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put",
                "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitInsn(POP);
        mv.visitJumpInsn(GOTO, l2);
        mv.visitLabel(l3);
        mv.visitFrame(Opcodes.F_CHOP, 2, null, 0, null);
        mv.visitJumpInsn(GOTO, l0);
        mv.visitLabel(l1);
        mv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKESTATIC, "java/util/Collections", "unmodifiableMap",
                "(Ljava/util/Map;)Ljava/util/Map;");
        mv.visitInsn(ARETURN);
        mv.visitMaxs(4, 8);
        mv.visitEnd();
    }
    cw.visitEnd();

    byte[] bytes = cw.toByteArray();

    try {
        String classToLoad = className.replace("/", ".");
        ClassLoader cl = new ByteClassloader(bytes, this.getClass().getClassLoader(), classToLoad);
        Class<?> clazz = cl.loadClass(classToLoad);

        moduleConfig.bind(clazz);
        moduleConfig.bind(GenericMessageBodyWriter.class);
        bindExtension(serviceDefinition);
    } catch (Throwable e) {
        logger.error("generate", e);
    }
}