Example usage for org.objectweb.asm MethodVisitor visitEnd

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

Introduction

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

Prototype

public void visitEnd() 

Source Link

Document

Visits the end of the method.

Usage

From source file:br.usp.each.saeg.badua.test.validation.MaxTest.java

License:Open Source License

@Override
@Before//from   w w  w .  ja  v a 2  s.co m
public void setUp() throws Exception {
    super.setUp();

    final int classVersion = Opcodes.V1_6;
    final int classAccessor = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER;
    final String className = "Max";
    final String superName = "java/lang/Object";

    final int methodAccessor = Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC;
    final String methodName = "max";
    final String methodDesc = "([II)I";

    final ClassWriter cw = new ClassWriter(0);
    final MethodVisitor mw;

    cw.visit(classVersion, classAccessor, className, null, superName, null);
    mw = cw.visitMethod(methodAccessor, methodName, methodDesc, null, null);
    mw.visitCode();
    // block 0 (definitions {0, 1, 2, 3})
    mw.visitInsn(Opcodes.ICONST_0);
    mw.visitVarInsn(Opcodes.ISTORE, 2);
    mw.visitVarInsn(Opcodes.ALOAD, 0);
    mw.visitVarInsn(Opcodes.ILOAD, 2);
    mw.visitIincInsn(2, 1);
    mw.visitInsn(Opcodes.IALOAD);
    mw.visitVarInsn(Opcodes.ISTORE, 3);
    // block 1 (p-uses {1, 2})
    final Label backLoop = new Label();
    mw.visitLabel(backLoop);
    mw.visitVarInsn(Opcodes.ILOAD, 2);
    mw.visitVarInsn(Opcodes.ILOAD, 1);
    final Label breakLoop = new Label();
    mw.visitJumpInsn(Opcodes.IF_ICMPGE, breakLoop);
    // block 3 (p-uses {0, 2, 3})
    mw.visitVarInsn(Opcodes.ALOAD, 0);
    mw.visitVarInsn(Opcodes.ILOAD, 2);
    mw.visitInsn(Opcodes.IALOAD);
    mw.visitVarInsn(Opcodes.ILOAD, 3);
    final Label jump = new Label();
    mw.visitJumpInsn(Opcodes.IF_ICMPLE, jump);
    // block 5 (definitions {3}, uses {0, 2})
    mw.visitVarInsn(Opcodes.ALOAD, 0);
    mw.visitVarInsn(Opcodes.ILOAD, 2);
    mw.visitInsn(Opcodes.IALOAD);
    mw.visitVarInsn(Opcodes.ISTORE, 3);
    // block 4 (definitions {2}, uses {2})
    mw.visitLabel(jump);
    mw.visitIincInsn(2, 1);
    mw.visitJumpInsn(Opcodes.GOTO, backLoop);
    // block 2 ( uses {3})
    mw.visitLabel(breakLoop);
    mw.visitVarInsn(Opcodes.ILOAD, 3);
    mw.visitInsn(Opcodes.IRETURN);
    mw.visitMaxs(2, 4);
    mw.visitEnd();
    cw.visitEnd();

    final byte[] bytes = cw.toByteArray();
    klass = addClass(className, bytes);
    method = klass.getMethod(methodName, int[].class, int.class);
    classId = CRC64.checksum(bytes);

    RT.init(new RuntimeData());
}

From source file:bytecode.ClassExporter.java

License:Apache License

/**
 * Exports the given class node to a file. The location of this file is
 * determined by the output classpath. This will cause a
 * <code>RuntimeException</code> if the class is not deeply loaded.
 *
 * @param  c     Class node to be exported.
 *//*from   www .j  a  v a2 s. co m*/
public static void export(ClassNode c) {
    // Form array of interface names.
    String[] interfaces = new String[c.getInterfaces().size()];
    int index = 0;

    for (ClassNode iface : c.getInterfaces()) {
        interfaces[index++] = iface.getName();
    }

    // Export Class Header
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

    cw.visit(Opcodes.V1_6, Modifier.getBitField(c.getModifiers()), c.getName(), null, // NOTE: Generic signature (for debugging/reflection).
            (c.getSuperClass() == null) ? null : c.getSuperClass().getName(), interfaces);

    // TODO: Inner / Outer Classes

    // Debug Information
    if (c.getSourceFile() != null) {
        cw.visitSource(c.getSourceFile(), null);
    }

    // Export Fields
    for (Field f : c.getFields()) {
        cw.visitField(Modifier.getBitField(f.getModifiers()), f.getName(), f.getType().getDescriptor(), null,
                f.getDefaultValue());
    }

    // Export Methods
    MethodVisitor mv;

    for (Method m : c.getMethods()) {
        if (!m.getModifiers().contains(Modifier.INHERITED)) {
            mv = cw.visitMethod(Modifier.getBitField(m.getModifiers()), m.getName(), m.getDescriptor(), null, // NOTE: Generic signature (for debugging/reflection).
                    null // TODO: Exceptions
            );

            // Export code unless NATIVE or ABSTRACT.
            if (!m.getModifiers().contains(Modifier.NATIVE) && !m.getModifiers().contains(Modifier.ABSTRACT)) {
                mv.visitCode();
                m.getImplementation().accept(new BlockExporter(mv));

                // Arguments are just dummys, the ClassWriter recalculates.
                mv.visitMaxs(0, 0);
            }

            mv.visitEnd();
        }
    }

    cw.visitEnd();

    File f = new File(outputDirectory, c.getName() + ".class");
    try {
        f.getParentFile().mkdirs();
        FileOutputStream fos = new FileOutputStream(f);
        fos.write(cw.toByteArray());
    } catch (IOException e) {
        throw new RuntimeException("Could not create class file: " + f);
    }
}

From source file:cc.adf.metrics.agent.visitor.ApplicationModuleImplModifier.java

public static void addDetailNameMethod(ClassWriter cw) {
    MethodVisitor mv = cw.visitMethod(ACC_PRIVATE, "getDetailName", "()Ljava/lang/String;", null, null);
    mv.visitCode();//w  w  w  .j  a  v a  2 s.  c  om
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKEVIRTUAL, "oracle/jbo/server/ApplicationModuleImpl", "isRoot", "()Z", false);
    Label l0 = new Label();
    mv.visitJumpInsn(IFEQ, l0);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, "oracle/jbo/server/ApplicationModuleImpl", "getName",
            "()Ljava/lang/String;", false);
    mv.visitInsn(ARETURN);
    mv.visitLabel(l0);
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V", false);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, "oracle/jbo/server/ApplicationModuleImpl", "getRootApplicationModule",
            "()Loracle/jbo/server/ApplicationModuleImpl;", false);
    mv.visitMethodInsn(INVOKEVIRTUAL, "oracle/jbo/server/ApplicationModuleImpl", "getName",
            "()Ljava/lang/String;", false);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
            "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
    mv.visitLdcInsn("::");
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
            "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, "oracle/jbo/server/ApplicationModuleImpl", "getName",
            "()Ljava/lang/String;", false);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
            "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
    mv.visitInsn(ARETURN);
    mv.visitMaxs(2, 1);
    mv.visitEnd();
}

From source file:ch.raffael.contracts.processor.pmap.ParameterMapAnnotationProcessor.java

License:Apache License

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Building parameter maps");
    for (Element elem : roundEnv.getRootElements()) {
        if (elem.getKind() == ElementKind.CLASS || elem.getKind() == ElementKind.INTERFACE) {
            // FIXME: enums & enum constants
            try {
                TypeElement typeElem = (TypeElement) elem;
                processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,
                        "Processing: " + ((TypeElement) elem).getQualifiedName());
                String className = typeElem.getQualifiedName().toString();
                if (className.endsWith(CONTRACTS_CLASS_SUFFIX)) {
                    continue;
                }/*from  w  ww .j a v a 2s .co  m*/
                String ctrClassName = className + CONTRACTS_CLASS_SUFFIX;
                JavaFileObject contractsFile = processingEnv.getFiler().createClassFile(ctrClassName, elem);
                ClassWriter classWriter = new ClassWriter(0);
                classWriter.visit(V1_7, ACC_PUBLIC + ACC_SUPER, toInternalName(ctrClassName), null, null, null);
                MethodVisitor ctor = classWriter.visitMethod(ACC_PRIVATE, "<init>", "()V", null, null);
                ctor.visitCode();
                ctor.visitLabel(new Label());
                ctor.visitEnd();
                //classWriter.visitOuterClass(toInternalName(className), null, null);
                AnnotationVisitor parameterMap = classWriter
                        .visitAnnotation(Type.getDescriptor(ParameterMap.class), false);
                writeType(parameterMap, typeElem, null);
                parameterMap.visitEnd();
                classWriter.visitEnd();
                try (OutputStream output = contractsFile.openOutputStream()) {
                    output.write(classWriter.toByteArray());
                }
            } catch (IOException e) {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getLocalizedMessage());
            }
        }
    }
    return false;
}

From source file:cn.annoreg.asm.DelegateGenerator.java

License:Open Source License

public static MethodVisitor generateStaticMethod(ClassVisitor parentClass, MethodVisitor parent,
        String className, String methodName, String desc, final Side side) {

    //This method is a little bit complicated.
    //We need to generate a delegate class implementing NetworkCallDelegate and a redirect
    //the code that originally generated here in parent, into the delegate class,
    //by returning a MethodVisitor under the ClassVisitor of the delegate class.
    //Besides, we should generate a call to NetworkCallManager into parent.

    //Above is the original method. Now it has a little bit change. To allow private call in
    //here, we need to generate the delegate method in this class instead of in a delegate class.
    //We make the delegate method public so that the delegate class can call it.

    //delegateName is a string used by both sides to identify a network-call delegate.
    final String delegateName = className + ":" + methodName + ":" + desc;
    final Type[] args = Type.getArgumentTypes(desc);
    final Type ret = Type.getReturnType(desc);

    //Check types
    for (Type t : args) {
        //TODO support these types
        if (!t.getDescriptor().startsWith("L") && !t.getDescriptor().startsWith("[")) {
            throw new RuntimeException("Unsupported argument type in network call. in method " + methodName
                    + ", " + t.getDescriptor());
        }//from  w  ww .  j av a  2s . co m
    }
    if (!ret.equals(Type.VOID_TYPE)) {
        throw new RuntimeException(
                "Unsupported return value type in network call. " + "Only void is supported.");
    }

    //Generate call to NetworkCallManager in parent.
    parent.visitCode();
    //First parameter
    parent.visitLdcInsn(delegateName);
    //Second parameter: object array
    pushIntegerConst(parent, args.length); //array size
    parent.visitTypeInsn(Opcodes.ANEWARRAY, Type.getInternalName(Object.class));
    for (int i = 0; i < args.length; ++i) {
        parent.visitInsn(Opcodes.DUP);
        pushIntegerConst(parent, i);
        parent.visitVarInsn(Opcodes.ALOAD, i);
        parent.visitInsn(Opcodes.AASTORE);
    }
    //Call cn.annoreg.mc.network.NetworkCallManager.onNetworkCall
    parent.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(NetworkCallManager.class),
            "onNetworkCall",
            Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class), Type.getType(Object[].class)));
    parent.visitInsn(Opcodes.RETURN);
    parent.visitMaxs(5, args.length);
    parent.visitEnd();

    //Create delegate object.
    final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
    final String delegateId = Integer.toString(delegateNextID++);
    final Type delegateClassType = Type.getType("cn/annoreg/asm/NetworkCallDelegate_" + delegateId);
    cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, delegateClassType.getInternalName(), null,
            Type.getInternalName(Object.class),
            new String[] { Type.getInternalName(NetworkCallDelegate.class) });
    //package cn.annoreg.asm;
    //class NetworkCallDelegate_? implements NetworkCallDelegate {
    {
        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V");
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    //public NetworkCallDelegate_?() {}

    final String delegateFunctionName = methodName + "_delegate_" + delegateId;
    {
        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "invoke",
                Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object[].class)), null, null);
        mv.visitCode();
        for (int i = 0; i < args.length; ++i) {
            mv.visitVarInsn(Opcodes.ALOAD, 1); //0 is this
            pushIntegerConst(mv, i);
            mv.visitInsn(Opcodes.AALOAD);
            mv.visitTypeInsn(Opcodes.CHECKCAST, args[i].getInternalName());
        }
        mv.visitMethodInsn(Opcodes.INVOKESTATIC,
                //delegateClassType.getInternalName(), //changed to original class
                className.replace('.', '/'), delegateFunctionName, desc);
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(args.length + 2, 2);
        mv.visitEnd();
    }
    //@Override public void invoke(Object[] args) {
    //    xxxx.xxxx_delegated_xxx((Type0) args[0], (Type1) args[1], ...);
    //}

    //The returned MethodVisitor will visit the original version of the method,
    //including its annotation, where we can get StorageOptions.
    return new MethodVisitor(Opcodes.ASM4, parentClass.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC,
            delegateFunctionName, desc, null, null)) {

        //Remember storage options for each argument
        StorageOption.Option[] options = new StorageOption.Option[args.length];
        int targetIndex = -1;
        StorageOption.Target.RangeOption range = StorageOption.Target.RangeOption.SINGLE;
        double sendRange = -1;

        {
            for (int i = 0; i < options.length; ++i) {
                options[i] = StorageOption.Option.NULL; //set default value
            }
        }

        @Override
        public AnnotationVisitor visitParameterAnnotation(final int parameter, String desc, boolean visible) {
            Type type = Type.getType(desc);
            if (type.equals(Type.getType(StorageOption.Data.class))) {
                options[parameter] = StorageOption.Option.DATA;
            } else if (type.equals(Type.getType(StorageOption.Instance.class))) {
                //INSTANCE as defualt
                options[parameter] = StorageOption.Option.INSTANCE;

                //Change to NULLABLE_INSTANCE if nullable set to true
                return new AnnotationVisitor(this.api,
                        super.visitParameterAnnotation(parameter, desc, visible)) {
                    @Override
                    public void visit(String name, Object value) {
                        if (name.equals("nullable")) {
                            if ((Boolean) value == true) {
                                options[parameter] = StorageOption.Option.NULLABLE_INSTANCE;
                            }
                        }
                        super.visit(name, value);
                    }
                };
            } else if (type.equals(Type.getType(StorageOption.Update.class))) {
                options[parameter] = StorageOption.Option.UPDATE;
            } else if (type.equals(Type.getType(StorageOption.Null.class))) {
                options[parameter] = StorageOption.Option.NULL;
            } else if (type.equals(Type.getType(StorageOption.Target.class))) {
                if (!args[parameter].equals(Type.getType(EntityPlayer.class))) {
                    throw new RuntimeException("Target annotation can only be used on EntityPlayer.");
                }
                if (targetIndex != -1) {
                    throw new RuntimeException("You can not specify multiple targets.");
                }
                options[parameter] = StorageOption.Option.INSTANCE;
                targetIndex = parameter;
                return new AnnotationVisitor(this.api,
                        super.visitParameterAnnotation(parameter, desc, visible)) {
                    @Override
                    public void visitEnum(String name, String desc, String value) {
                        super.visitEnum(name, desc, value);
                        range = StorageOption.Target.RangeOption.valueOf(value);
                    }
                };
            } else if (type.equals(Type.getType(StorageOption.RangedTarget.class))) {
                if (targetIndex != -1) {
                    throw new RuntimeException("You can not specify multiple targets.");
                }
                range = null;
                targetIndex = parameter;
                return new AnnotationVisitor(this.api,
                        super.visitParameterAnnotation(parameter, desc, visible)) {
                    @Override
                    public void visit(String name, Object value) {
                        super.visit(name, value);
                        sendRange = (double) value;
                    }
                };
            }
            return super.visitParameterAnnotation(parameter, desc, visible);
        }

        @Override
        public void visitEnd() {
            super.visitEnd();
            //This is the last method in the delegate class.
            //Finish the class and do the registration.
            cw.visitEnd();
            try {
                Class<?> clazz = classLoader.defineClass(delegateClassType.getClassName(), cw.toByteArray());
                NetworkCallDelegate delegateObj = (NetworkCallDelegate) clazz.newInstance();
                if (side == Side.CLIENT) {
                    NetworkCallManager.registerClientDelegateClass(delegateName, delegateObj, options,
                            targetIndex, range, sendRange);
                } else {
                    NetworkCallManager.registerServerDelegateClass(delegateName, delegateObj, options);
                }
            } catch (Throwable e) {
                throw new RuntimeException("Can not create delegate for network call.", e);
            }
        }
    };
    //public static void delegated(Type0 arg0, Type1, arg1, ...) {
    //    //Code generated by caller.
    //}
    //}
}

From source file:cn.annoreg.asm.DelegateGenerator.java

License:Open Source License

public static MethodVisitor generateNonStaticMethod(ClassVisitor parentClass, MethodVisitor parent,
        String className, String methodName, String desc, final Side side) {

    //convert desc to a non-static method form
    String nonstaticDesc;/*from www .j av  a2s . co m*/
    {
        Type staticType = Type.getMethodType(desc);
        Type retType = staticType.getReturnType();
        Type[] argsType = staticType.getArgumentTypes();
        Type[] argsTypeWithThis = new Type[argsType.length + 1];
        argsTypeWithThis[0] = Type.getType('L' + className.replace('.', '/') + ';');
        System.arraycopy(argsType, 0, argsTypeWithThis, 1, argsType.length);
        nonstaticDesc = Type.getMethodDescriptor(retType, argsTypeWithThis);
    }

    //delegateName is a string used by both sides to identify a network-call delegate.
    final String delegateName = className + ":" + methodName + ":" + desc;
    final Type[] args = Type.getArgumentTypes(nonstaticDesc);
    final Type ret = Type.getReturnType(nonstaticDesc);

    //Check types
    for (Type t : args) {
        //TODO support these types
        if (!t.getDescriptor().startsWith("L") && !t.getDescriptor().startsWith("[")) {
            throw new RuntimeException("Unsupported argument type in network call. ");
        }
    }
    if (!ret.equals(Type.VOID_TYPE)) {
        throw new RuntimeException(
                "Unsupported return value type in network call. " + "Only void is supported.");
    }

    //Generate call to NetworkCallManager in parent.
    parent.visitCode();
    //First parameter
    parent.visitLdcInsn(delegateName);
    //Second parameter: object array
    pushIntegerConst(parent, args.length); //this (0) has been included
    parent.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
    for (int i = 0; i < args.length; ++i) {
        parent.visitInsn(Opcodes.DUP);
        pushIntegerConst(parent, i);
        parent.visitVarInsn(Opcodes.ALOAD, i);
        parent.visitInsn(Opcodes.AASTORE);
    }
    //Call cn.annoreg.mc.network.NetworkCallManager.onNetworkCall
    parent.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(NetworkCallManager.class),
            "onNetworkCall", "(Ljava/lang/String;[Ljava/lang/Object;)V");
    parent.visitInsn(Opcodes.RETURN);
    parent.visitMaxs(5, args.length);
    parent.visitEnd();

    //Create delegate object.
    final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
    final String delegateId = Integer.toString(delegateNextID++);
    final Type delegateClassType = Type.getType("cn/annoreg/asm/NetworkCallDelegate_" + delegateId);
    cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, delegateClassType.getInternalName(), null,
            Type.getInternalName(Object.class),
            new String[] { Type.getInternalName(NetworkCallDelegate.class) });
    //package cn.annoreg.asm;
    //class NetworkCallDelegate_? implements NetworkCallDelegate {
    {
        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V");
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    //public NetworkCallDelegate_?() {}

    final String delegateMethodName = methodName + "_delegate_" + delegateId;
    {
        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "invoke",
                Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object[].class)), null, null);
        mv.visitCode();

        //check if this is null
        mv.visitVarInsn(Opcodes.ALOAD, 1); //0 is this
        pushIntegerConst(mv, 0);
        mv.visitInsn(Opcodes.AALOAD);
        Label lblEnd = new Label();
        mv.visitJumpInsn(Opcodes.IFNULL, lblEnd);

        for (int i = 0; i < args.length; ++i) {
            mv.visitVarInsn(Opcodes.ALOAD, 1); //0 is this
            pushIntegerConst(mv, i);
            mv.visitInsn(Opcodes.AALOAD);
            mv.visitTypeInsn(Opcodes.CHECKCAST, args[i].getInternalName());
        }
        mv.visitMethodInsn(Opcodes.INVOKESTATIC,
                //delegateClassType.getInternalName(), 
                className.replace('.', '/'), delegateMethodName, nonstaticDesc);

        mv.visitLabel(lblEnd);

        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(args.length + 2, 2);
        mv.visitEnd();
    }
    //@Override public void invoke(Object[] args) {
    //    delegated((Type0) args[0], (Type1) args[1], ...);
    //}

    //The returned MethodVisitor will visit the original version of the method,
    //including its annotation, where we can get StorageOptions.
    return new MethodVisitor(Opcodes.ASM4, parentClass.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC,
            delegateMethodName, nonstaticDesc, null, null)) {

        //Remember storage options for each argument
        StorageOption.Option[] options = new StorageOption.Option[args.length];
        int targetIndex = -1;
        double sendRange = -1;
        StorageOption.Target.RangeOption range = StorageOption.Target.RangeOption.SINGLE;

        {
            for (int i = 0; i < options.length; ++i) {
                options[i] = StorageOption.Option.NULL; //set default value
            }
            options[0] = StorageOption.Option.INSTANCE;
        }

        @Override
        public AnnotationVisitor visitParameterAnnotation(int parameter_in_func, String desc, boolean visible) {
            final int parameter = parameter_in_func + 1; //skip this
            Type type = Type.getType(desc);
            if (type.equals(Type.getType(StorageOption.Data.class))) {
                options[parameter] = StorageOption.Option.DATA;
            } else if (type.equals(Type.getType(StorageOption.Instance.class))) {
                //INSTANCE as defualt
                options[parameter] = StorageOption.Option.INSTANCE;

                //Change to NULLABLE_INSTANCE if nullable set to true
                return new AnnotationVisitor(this.api,
                        super.visitParameterAnnotation(parameter, desc, visible)) {
                    @Override
                    public void visit(String name, Object value) {
                        if (name.equals("nullable")) {
                            if ((Boolean) value == true) {
                                options[parameter] = StorageOption.Option.NULLABLE_INSTANCE;
                            }
                        }
                        super.visit(name, value);
                    }
                };
            } else if (type.equals(Type.getType(StorageOption.Update.class))) {
                options[parameter] = StorageOption.Option.UPDATE;
            } else if (type.equals(Type.getType(StorageOption.Null.class))) {
                options[parameter] = StorageOption.Option.NULL;
            } else if (type.equals(Type.getType(StorageOption.Target.class))) {
                if (!args[parameter].equals(Type.getType(EntityPlayer.class))) {
                    throw new RuntimeException("Target annotation can only be used on EntityPlayer.");
                }
                if (targetIndex != -1) {
                    throw new RuntimeException("You can not specify multiple targets.");
                }
                options[parameter] = StorageOption.Option.INSTANCE;
                targetIndex = parameter;
                return new AnnotationVisitor(this.api,
                        super.visitParameterAnnotation(parameter, desc, visible)) {
                    @Override
                    public void visitEnum(String name, String desc, String value) {
                        super.visitEnum(name, desc, value);
                        range = StorageOption.Target.RangeOption.valueOf(value);
                    }
                };
            } else if (type.equals(Type.getType(StorageOption.RangedTarget.class))) {
                if (targetIndex != -1) {
                    throw new RuntimeException("You can not specify multiple targets.");
                }
                targetIndex = parameter;
                range = null;
                return new AnnotationVisitor(this.api,
                        super.visitParameterAnnotation(parameter, desc, visible)) {
                    @Override
                    public void visit(String name, Object value) {
                        super.visit(name, value);
                        sendRange = (double) value;
                    }
                };
            }
            return super.visitParameterAnnotation(parameter, desc, visible);
        }

        //TODO this option (from annotation)

        @Override
        public void visitEnd() {
            super.visitEnd();
            //This is the last method in the delegate class.
            //Finish the class and do the registration.
            cw.visitEnd();
            try {
                Class<?> clazz = classLoader.defineClass(delegateClassType.getClassName(), cw.toByteArray());
                NetworkCallDelegate delegateObj = (NetworkCallDelegate) clazz.newInstance();
                if (side == Side.CLIENT) {
                    NetworkCallManager.registerClientDelegateClass(delegateName, delegateObj, options,
                            targetIndex, range, sendRange);
                } else {
                    NetworkCallManager.registerServerDelegateClass(delegateName, delegateObj, options);
                }
            } catch (Throwable e) {
                throw new RuntimeException("Can not create delegate for network call.", e);
            }
        }
    };
    //public static void delegated(Type0 arg0, Type1, arg1, ...) {
    //    //Code generated by caller.
    //}
    //}
}

From source file:co.paralleluniverse.data.record.DynamicGeneratedRecord.java

License:Open Source License

private static ClassWriter generateClass(Class<?> type, Field field, String accName) {
    final String superName = DYNAMIC_GENERATED_RECORD_TYPE + "$" + accName;
    final String className = accessorClassName(type, field).replace('.', '/');

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);

    cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, className, null, superName, null);

    cw.visitInnerClass(superName, DYNAMIC_GENERATED_RECORD_TYPE, accName, ACC_STATIC + ACC_ABSTRACT);

    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
    mv.visitCode();/*from www . ja v a 2s.co m*/
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, superName, "<init>", "()V");
    mv.visitInsn(RETURN);
    mv.visitMaxs(1, 1);
    mv.visitEnd();

    return cw;
}

From source file:co.paralleluniverse.data.record.DynamicGeneratedRecord.java

License:Open Source License

private static byte[] generateSimpleFieldAccessor(Class<?> type, Field<?, ?> field, java.lang.reflect.Field f) {
    final String typeName = Type.getInternalName(type);
    final String fieldTypeName = Type.getInternalName(field.typeClass());
    final String fieldTypeDesc = Type.getDescriptor(field.typeClass());
    final String accName = accessorName(field) + "Accessor";

    ClassWriter cw = generateClass(type, field, accName);
    MethodVisitor mv;

    mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;)" + methodSigTypeDesc(field), null, null);
    mv.visitCode();/*from   w w  w.  j a  v a  2 s .c  o m*/
    mv.visitVarInsn(ALOAD, 1);
    mv.visitTypeInsn(CHECKCAST, typeName);
    mv.visitFieldInsn(GETFIELD, typeName, field.name(), fieldTypeDesc);
    mv.visitInsn(returnOpcode(field));
    mv.visitEnd();

    mv = cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;" + methodSigTypeDesc(field) + ")V", null, null);
    mv.visitCode();
    if (Modifier.isFinal(f.getModifiers())) {
        mv.visitTypeInsn(NEW, "co/paralleluniverse/data/record/ReadOnlyFieldException");
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, "co/paralleluniverse/data/record/ReadOnlyFieldException", "<init>",
                "()V");
        mv.visitInsn(ATHROW);
    } else {
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST, typeName);
        mv.visitVarInsn(loadOpcode(field), 2);
        if (field instanceof Field.ObjectField)
            mv.visitTypeInsn(CHECKCAST, fieldTypeName);
        mv.visitFieldInsn(PUTFIELD, typeName, field.name(), fieldTypeDesc);
        mv.visitInsn(RETURN);
    }
    mv.visitEnd();

    cw.visitEnd();

    return cw.toByteArray();
}

From source file:co.paralleluniverse.data.record.DynamicGeneratedRecord.java

License:Open Source License

private static byte[] generateMethodAccessor(Class<?> type, Field<?, ?> field, Method getter, Method setter) {
    final String typeName = Type.getInternalName(type);
    final String fieldTypeName = Type.getInternalName(field.typeClass());
    final String fieldTypeDesc = Type.getDescriptor(field.typeClass());
    final String accName = accessorName(field) + "Accessor";

    ClassWriter cw = generateClass(type, field, accName);
    MethodVisitor mv;

    mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;)" + methodSigTypeDesc(field), null, null);
    mv.visitCode();/*from   w w  w .jav a 2 s.  co m*/
    mv.visitVarInsn(ALOAD, 1);
    mv.visitTypeInsn(CHECKCAST, typeName);
    mv.visitMethodInsn(INVOKEVIRTUAL, typeName, getter.getName(), Type.getMethodDescriptor(getter));
    mv.visitInsn(returnOpcode(field));
    mv.visitEnd();

    mv = cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;" + methodSigTypeDesc(field) + ")V", null, null);
    mv.visitCode();

    if (setter != null) {
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST, typeName);
        mv.visitVarInsn(loadOpcode(field), 2);
        if (field instanceof Field.ObjectField)
            mv.visitTypeInsn(CHECKCAST, fieldTypeName);
        mv.visitMethodInsn(INVOKEVIRTUAL, typeName, setter.getName(), Type.getMethodDescriptor(setter));
        mv.visitInsn(RETURN);
    } else {
        mv.visitTypeInsn(NEW, Type.getInternalName(ReadOnlyFieldException.class));
        mv.visitInsn(DUP);
        mv.visitLdcInsn(field.name);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(ReadOnlyFieldException.class), "<init>",
                "(Ljava/lang/String;Ljava/lang/Object;)V");
        mv.visitInsn(ATHROW);
    }
    mv.visitEnd();

    cw.visitEnd();

    return cw.toByteArray();
}

From source file:co.paralleluniverse.data.record.DynamicGeneratedRecord.java

License:Open Source License

private static byte[] generateArrayFieldAccessor(Class<?> type, Field<?, ?> field, java.lang.reflect.Field f) {
    final String typeName = Type.getInternalName(type);
    final String typeDesc = Type.getDescriptor(field.typeClass());
    final String accName = accessorName(field) + "ArrayAccessor";

    ClassWriter cw = generateClass(type, field, accName);
    MethodVisitor mv;

    mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;)" + methodSigTypeDesc(field), null, null);
    mv.visitCode();//from ww w. j  a  v  a2 s.  co  m
    mv.visitVarInsn(ALOAD, 1);
    mv.visitTypeInsn(CHECKCAST, typeName);
    mv.visitFieldInsn(GETFIELD, typeName, field.name(), typeDesc);
    mv.visitInsn(ARETURN);
    mv.visitEnd();

    cw.visitEnd();

    return cw.toByteArray();
}