Example usage for org.objectweb.asm ClassVisitor visitMethod

List of usage examples for org.objectweb.asm ClassVisitor visitMethod

Introduction

In this page you can find the example usage for org.objectweb.asm ClassVisitor visitMethod.

Prototype

public MethodVisitor visitMethod(final int access, final String name, final String descriptor,
        final String signature, final String[] exceptions) 

Source Link

Document

Visits a method of the class.

Usage

From source file:Java6to2.java

License:Open Source License

private static byte[] transform(InputStream classfile) throws IOException {
    ClassReader cr = new ClassReader(classfile);
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    ClassVisitor cv = new ClassVisitor(ASM7, cw) {
        String internalName;/*from  w w  w.  j ava  2s  .  c  o m*/
        boolean classLookupMethodGenerated;
        Set fieldsGenerated = new HashSet();

        public void visit(int version, int access, String name, String signature, String superName,
                String[] interfaces) {
            /* Change class file version to 1.2 */
            cv.visit(V1_2, access, name, signature, superName, interfaces);
            this.internalName = name;
        }

        /**
         * Generates the synthetic "class$" method, used to lookup classes via Class.forName(). This uses the exact same code as does JDK8 javac for target 1.2.
         */
        void generateSyntheticClassLookupMethod() {
            MethodVisitor mv = cv.visitMethod(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, "class$",
                    "(Ljava/lang/String;)Ljava/lang/Class;", null, null);
            {
                Label start = new Label();
                Label end = new Label();
                Label handler = new Label();
                mv.visitTryCatchBlock(start, end, handler, "java/lang/ClassNotFoundException");
                mv.visitLabel(start);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Class", "forName",
                        "(Ljava/lang/String;)Ljava/lang/Class;", false);
                mv.visitLabel(end);
                mv.visitInsn(ARETURN);
                mv.visitLabel(handler);
                mv.visitVarInsn(ASTORE, 1);
                mv.visitTypeInsn(NEW, "java/lang/NoClassDefFoundError");
                mv.visitInsn(DUP);
                mv.visitMethodInsn(INVOKESPECIAL, "java/lang/NoClassDefFoundError", "<init>", "()V", false);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/NoClassDefFoundError", "initCause",
                        "(Ljava/lang/Throwable;)Ljava/lang/Throwable;", false);
                mv.visitInsn(ATHROW);
            }
            mv.visitMaxs(2, 2);
            mv.visitEnd();
        }

        public MethodVisitor visitMethod(int access, String name, String desc, String signature,
                String[] exceptions) {
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
            final ClassVisitor cv = this.cv;
            return new MethodVisitor(ASM7, mv) {
                /**
                 * Intercepts class instantiations to see whether they instantiate a StringBuilder. Those instructions were generated by javac for string concatenations. But
                 * StringBuilder is not available on JRE1.2, so we just replace it with StringBuffer.
                 */
                public void visitTypeInsn(int opcode, String type) {
                    if (opcode == NEW && "java/lang/StringBuilder".equals(type)) {
                        mv.visitTypeInsn(opcode, "java/lang/StringBuffer");
                    } else {
                        mv.visitTypeInsn(opcode, type);
                    }
                }

                /**
                 * Intercepts method invocations to see whether they do something with StringBuilder. Those instructions were generated by javac for string concatenations. But
                 * StringBuilder is not available on JRE1.2, so we just replace it with StringBuffer.
                 */
                public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
                    if ("java/lang/StringBuilder".equals(owner)) {
                        mv.visitMethodInsn(opcode, "java/lang/StringBuffer", name,
                                desc.replace("java/lang/StringBuilder", "java/lang/StringBuffer"), itf);
                    } else {
                        mv.visitMethodInsn(opcode, owner, name, desc, itf);
                    }
                }

                /**
                 * Intercepts LDC instructions and check whether they are used to load a class. This is not supported on Java 1.2, so we convert it to the same code used by the
                 * JDK8 javac:
                 * <ul>
                 * <li>create synthetic fields holding the resolved class objects
                 * <li>create a synthetic method called "class$" which does Class.forName
                 * </ul>
                 */
                public void visitLdcInsn(Object cst) {
                    if (cst instanceof Type) {
                        Type t = (Type) cst;
                        String syntheticField = "class$"
                                + t.getInternalName().replace('/', '$').replace("[", "");
                        if (!classLookupMethodGenerated) {
                            /* Emit the synthetic "class$" method, used to lookup classes via Class.forName() */
                            generateSyntheticClassLookupMethod();
                            classLookupMethodGenerated = true;
                        }
                        if (!fieldsGenerated.contains(syntheticField)) {
                            /* Generate a synthetic field holding the resolved Class object */
                            cv.visitField(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, syntheticField,
                                    "Ljava/lang/Class;", null, null);
                            fieldsGenerated.add(syntheticField);
                        }
                        mv.visitFieldInsn(GETSTATIC, internalName, syntheticField, "Ljava/lang/Class;");
                        Label nonNull = new Label();
                        mv.visitJumpInsn(IFNONNULL, nonNull);
                        mv.visitLdcInsn(t.getInternalName().replace('/', '.'));
                        mv.visitMethodInsn(INVOKESTATIC, internalName, "class$",
                                "(Ljava/lang/String;)Ljava/lang/Class;", false);
                        mv.visitInsn(DUP);
                        mv.visitFieldInsn(PUTSTATIC, internalName, syntheticField, "Ljava/lang/Class;");
                        Label cnt = new Label();
                        mv.visitJumpInsn(GOTO, cnt);
                        mv.visitLabel(nonNull);
                        mv.visitFieldInsn(GETSTATIC, internalName, syntheticField, "Ljava/lang/Class;");
                        mv.visitLabel(cnt);
                    } else {
                        mv.visitLdcInsn(cst);
                    }
                }
            };
        }
    };
    cr.accept(cv, ClassReader.SKIP_FRAMES); // <- Frames are not used in Java 1.2, so skip them
    return cw.toByteArray();
}

From source file:asmlib.extra.FixDeadTryCatchBlockMethodVisitor.java

License:Open Source License

public FixDeadTryCatchBlockMethodVisitor(int access, String name, String desc, String signature,
        String[] exceptions, ClassVisitor cv) {
    super(Opcodes.ASM4, cv.visitMethod(access, name, desc, signature, exceptions));
}

From source file:asmlib.extra.RemoveUnusedTryCatchBlockMethodVisitor.java

License:Open Source License

public RemoveUnusedTryCatchBlockMethodVisitor(int access, String name, String desc, String signature,
        String[] exceptions, ClassVisitor cv) {
    super(Opcodes.ASM4, cv.visitMethod(access, name, desc, signature, exceptions));
}

From source file:asmlib.UninitializedCallChecker.java

License:Open Source License

public UninitializedCallChecker(int access, String name, String desc, String signature, String[] exceptions,
        ClassVisitor cv, String className, PrintWriter pw) {
    super(Opcodes.ASM4, new AnalyzerAdapter(className, access, name, desc,
            cv.visitMethod(access, name, desc, signature, exceptions)));
    _analyzerAdapter = (AnalyzerAdapter) mv;
    _pw = pw;/* www  . jav a2  s  . c  o m*/
    _name = name;
    _desc = desc;
}

From source file:ch.eiafr.cojac.Agent.java

License:Apache License

/**
* This method works only with the FloatReplacerClasses class
* It instruments it to create a static initializer block to set
* all the static variables used by the agent and injected in the 
* instrumented application./*from   w w  w  . j av a 2s  . c  o m*/
* Warning: this is not the only place to set these variables, see class
* "CojacReferences" !
* This is used when there is more than one classloader in the application
*/
private byte[] setGlobalFields(byte[] byteCode, ClassLoader loader) {
    ClassReader cr = new ClassReader(byteCode);
    ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
    ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw) {
        @Override
        public void visit(int version, int access, String name, String signature, String superName,
                String[] interfaces) {
            super.visit(version, access, name, signature, superName, interfaces);
            MethodVisitor mv = cv.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
            mv.visitLdcInsn(references.getDoubleWrapper());
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setNgWrapper", "(Ljava/lang/String;)V", false);
            mv.visitLdcInsn(references.getNgWrapper());
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setDoubleWrapper", "(Ljava/lang/String;)V", false);
            mv.visitLdcInsn(references.getFloatWrapper());
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setFloatWrapper", "(Ljava/lang/String;)V", false);
            mv.visitLdcInsn(references.getBigDecimalPrecision());
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setBigDecimalPrecision", "(I)V", false);
            mv.visitLdcInsn(references.getStabilityThreshold());
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setStabilityThreshold", "(D)V", false);
            mv.visitLdcInsn(references.getCheckUnstableComparisons() ? 1 : 0);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setCheckUnstableComparisons", "(Z)V", false);
            mv.visitInsn(Opcodes.RETURN);
            mv.visitMaxs(0, 0);
        }
    };
    cr.accept(cv, ClassReader.EXPAND_FRAMES);
    return cw.toByteArray();
}

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());
        }//w w  w.ja  v  a 2 s .c o  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   w ww . java2s .c  o 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:com.asakusafw.dag.compiler.codegen.AsmUtil.java

License:Apache License

/**
 * Adds {@link Result#add(Object)} method.
 * @param writer the current writer/*  w  w w  .j a va2  s .  com*/
 * @param callback the callback
 */
public static void defineResultAdd(ClassVisitor writer, Consumer<MethodVisitor> callback) {
    MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC, "add",
            Type.getMethodDescriptor(Type.VOID_TYPE, typeOf(Object.class)), null, null);
    callback.accept(method);
    method.visitInsn(Opcodes.RETURN);
    method.visitMaxs(0, 0);
    method.visitEnd();
}

From source file:com.asakusafw.dag.compiler.codegen.AsmUtil.java

License:Apache License

/**
 * Adds constant {@code toString()} method.
 * @param writer the current writer//from   w w w  .  jav a2 s . c o  m
 * @param value the constant value
 */
public static void defineToString(ClassVisitor writer, String value) {
    MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC, "toString",
            Type.getMethodDescriptor(typeOf(String.class)), null, null);
    getConst(method, value);
    method.visitInsn(Opcodes.ARETURN);
    method.visitMaxs(0, 0);
    method.visitEnd();
}

From source file:com.asakusafw.dag.compiler.codegen.AsmUtil.java

License:Apache License

private static List<Tuple<VertexElement, FieldRef>> defineDependenciesConstructor0(ClassDescription aClass,
        ClassVisitor writer, Iterable<? extends VertexElement> dependencies,
        Consumer<MethodVisitor> superConstructor, Consumer<MethodVisitor> callback) {
    List<Tuple<VertexElement, FieldRef>> results = new ArrayList<>();
    int index = 0;
    int varIndex = 1;
    List<Type> parameterTypes = new ArrayList<>();
    List<Consumer<MethodVisitor>> ctor = new ArrayList<>();
    for (VertexElement element : dependencies) {
        int current = index++;
        int currentVar = varIndex;
        String name = getDependencyId(current);
        Type type = typeOf(element.getRuntimeType());
        parameterTypes.add(type);/*from w w w.ja  v a2  s .  co  m*/
        FieldRef ref = defineField(writer, aClass, name, type);
        ctor.add(v -> {
            v.visitVarInsn(Opcodes.ALOAD, 0);
            v.visitVarInsn(loadOpcodeOf(element.getRuntimeType()), currentVar);
            putField(v, ref);
        });
        varIndex += categoryOf(element.getRuntimeType());
        results.add(new Tuple<>(element, ref));
    }
    MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC, CONSTRUCTOR_NAME,
            Type.getMethodDescriptor(Type.VOID_TYPE, parameterTypes.stream().toArray(Type[]::new)), null, null);
    superConstructor.accept(method);
    ctor.forEach(c -> c.accept(method));
    callback.accept(method);
    method.visitInsn(Opcodes.RETURN);
    method.visitMaxs(0, 0);
    method.visitEnd();
    return results;
}