All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sfm.reflect.asm.SetterBuilder Maven / Gradle / Ivy

Go to download

Java library to map flat record - ResultSet, csv - to java object with minimum configuration and low footprint.

There is a newer version: 1.10.3
Show newest version
package org.sfm.reflect.asm;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.sfm.reflect.Setter;
import org.sfm.reflect.primitive.IntSetter;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class SetterBuilder implements Opcodes {

	private static final String SETTER_TYPE = AsmUtils.toType(Setter.class);
	private static final String ORG_SFM_REFLECT_PRIMITIVE = AsmUtils.toType(IntSetter.class.getPackage().getName());

    public static byte[] createObjectSetter(final String className, final Field field) throws Exception {

        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        MethodVisitor mv;

        Class target = field.getDeclaringClass();
        Class property = field.getType();

        String targetType = toType(target);
        String propertyType = toType(property);
        String classType = toType(className);

        cw.visit(
                V1_6,
                ACC_PUBLIC + ACC_FINAL + ACC_SUPER,
                classType,
                "Ljava/lang/Object;L" + SETTER_TYPE + ";",
                "java/lang/Object", new String[] {SETTER_TYPE});

        {
            mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null);
            mv.visitCode();
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        appendSet(field, cw, target, targetType, propertyType, classType);


        appendToString(cw);
        cw.visitEnd();

        return AsmUtils.writeClassToFile(className, cw.toByteArray());

    }

	public static byte[] createObjectSetter(final String className, final Method method) throws Exception {

		ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
		MethodVisitor mv;

		Class target = method.getDeclaringClass();
		Class property = method.getParameterTypes()[0];
		
		String targetType = toType(target);
		String propertyType = toType(property);
		String classType = toType(className);
		
		cw.visit(
				V1_6,
				ACC_PUBLIC + ACC_FINAL + ACC_SUPER,
				classType,
				"Ljava/lang/Object;L" + SETTER_TYPE + ";",
				"java/lang/Object", new String[] {SETTER_TYPE});

		{
			mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null);
			mv.visitCode();
			mv.visitVarInsn(ALOAD, 0);
			mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false);
			mv.visitInsn(RETURN);
			mv.visitMaxs(1, 1);
			mv.visitEnd();
		}
        appendSet(method, cw, target, targetType, propertyType, classType);


        appendToString(cw);
        cw.visitEnd();

		return AsmUtils.writeClassToFile(className, cw.toByteArray());

	}

    private static void appendSet(Field field, ClassWriter cw, Class target, String targetType, String propertyType, String classType) {
        MethodVisitor mv;
        {
            mv = cw.visitMethod(ACC_PUBLIC, "set",
                    "(L" + targetType + ";" + AsmUtils.toTypeParam(propertyType) + ")V", null,
                    new String[] { "java/lang/Exception" });
            mv.visitCode();
            mv.visitVarInsn(ALOAD, 1);
            mv.visitVarInsn(ALOAD, 2);

            mv.visitFieldInsn(PUTFIELD, targetType, field.getName(), AsmUtils.toTypeParam(propertyType));

            mv.visitInsn(RETURN);
            mv.visitMaxs(2, 3);
            mv.visitEnd();
        }
        appendSynthetic(cw, targetType, propertyType, classType);
    }


    private static void appendSet(Method method, ClassWriter cw, Class target, String targetType, String propertyType, String classType) {
        MethodVisitor mv;
        {
            mv = cw.visitMethod(ACC_PUBLIC, "set",
                    "(L" + targetType + ";" + AsmUtils.toTypeParam(propertyType) + ")V", null,
                    new String[] { "java/lang/Exception" });
            mv.visitCode();
            mv.visitVarInsn(ALOAD, 1);
            mv.visitVarInsn(ALOAD, 2);

            AsmUtils.invoke(mv, target, method.getName(),  "(" + AsmUtils.toTypeParam(propertyType) + ")V");

            mv.visitInsn(RETURN);
            mv.visitMaxs(2, 3);
            mv.visitEnd();
        }
        appendSynthetic(cw, targetType, propertyType, classType);
    }

    private static void appendSynthetic(ClassWriter cw, String targetType, String propertyType, String classType) {
        MethodVisitor mv;
        mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, new String[] { "java/lang/Exception" });
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST, targetType);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitTypeInsn(CHECKCAST,  propertyType );
        mv.visitMethodInsn(INVOKEVIRTUAL, classType , "set", "(L" + targetType + ";" + AsmUtils.toTypeParam(propertyType) + ")V", false);
        mv.visitInsn(RETURN);
        mv.visitMaxs(3, 3);
        mv.visitEnd();
    }

    private static void appendToString(ClassWriter cw) {
        MethodVisitor mv;
        mv = cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
        mv.visitCode();
        mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "", "()V", false);
        mv.visitVarInsn(ASTORE, 1);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getSimpleName", "()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.visitLdcInsn("}");
        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();
    }

    public static byte[] createPrimitiveSetter(String className, Method method) throws Exception {

		ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
		MethodVisitor mv;

		Class target = method.getDeclaringClass();
		Class primitive = method.getParameterTypes()[0];
		Class property = AsmUtils.wrappers.get(primitive);
		
		String targetType = toType(target);
		String primitiveType = AsmUtils.primitivesType.get(primitive);
		String propertyType = toType(property);
		String classType = toType(className);
		
		String methodSuffix =  property.getSimpleName();
		if ("Integer".equals(methodSuffix)) {
			methodSuffix = "Int";
		}
		
		String valueMethodPrefix = methodSuffix.toLowerCase();
		if ("character".equals(valueMethodPrefix)) {
			valueMethodPrefix = "char";
		}
		
		String setMethod = "set" + methodSuffix;
		String valueMethod = valueMethodPrefix + "Value";

		
		int primitiveLoadOp = AsmUtils.loadOps.get(primitive);
		
		cw.visit(V1_6, ACC_PUBLIC + ACC_FINAL  + ACC_SUPER,  classType, 
				"Ljava/lang/Object;"
				+ "L"  + SETTER_TYPE + ";"
				+ "L" + ORG_SFM_REFLECT_PRIMITIVE + methodSuffix + "Setter;",
				"java/lang/Object", 
				new String[] { SETTER_TYPE,
								ORG_SFM_REFLECT_PRIMITIVE + "/" + methodSuffix + "Setter" });


		{
		mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null);
		mv.visitCode();
		mv.visitVarInsn(ALOAD, 0);
		mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false);
		mv.visitInsn(RETURN);
		mv.visitMaxs(1, 1);
		mv.visitEnd();
		}
		{
		mv = cw.visitMethod(ACC_PUBLIC, setMethod, "(L" + targetType + ";" + primitiveType + ")V", null, new String[] { "java/lang/Exception" });
		mv.visitCode();
		mv.visitVarInsn(ALOAD, 1);
		mv.visitVarInsn(primitiveLoadOp, 2);
		
		AsmUtils.invoke(mv, target, method.getName(), "(" + primitiveType + ")V");
		
		mv.visitInsn(RETURN);
		mv.visitMaxs(2, 3);
		mv.visitEnd();
		}
		{
		mv = cw.visitMethod(ACC_PUBLIC, "set", "(L" + targetType + ";" + AsmUtils.toTypeParam(propertyType) + ")V", null, new String[] { "java/lang/Exception" });
		mv.visitCode();
		mv.visitVarInsn(ALOAD, 1);
		mv.visitVarInsn(ALOAD, 2);
		AsmUtils.invoke(mv, property, valueMethod, "()" + primitiveType);
		AsmUtils.invoke(mv, target, method.getName(), "(" + primitiveType + ")V");
		mv.visitInsn(RETURN);
		mv.visitMaxs(2, 3);
		mv.visitEnd();
		}
        appendPrimitiveSynthetic(cw, targetType, primitiveType, propertyType, classType, setMethod, primitiveLoadOp);

        appendToString(cw);

		cw.visitEnd();

		return AsmUtils.writeClassToFile(className, cw.toByteArray());

	}


    public static byte[] createPrimitiveSetter(String className, Field field) throws Exception {

        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        MethodVisitor mv;

        Class target = field.getDeclaringClass();
        Class primitive = field.getType();
        Class property = AsmUtils.wrappers.get(primitive);

        String targetType = toType(target);
        String primitiveType = AsmUtils.primitivesType.get(primitive);
        String propertyType = toType(property);
        String classType = toType(className);

        String methodSuffix =  property.getSimpleName();
        if ("Integer".equals(methodSuffix)) {
            methodSuffix = "Int";
        }

        String valueMethodPrefix = methodSuffix.toLowerCase();
        if ("character".equals(valueMethodPrefix)) {
            valueMethodPrefix = "char";
        }

        String setMethod = "set" + methodSuffix;
        String valueMethod = valueMethodPrefix + "Value";


        int primitiveLoadOp = AsmUtils.loadOps.get(primitive);

        cw.visit(V1_6, ACC_PUBLIC + ACC_FINAL  + ACC_SUPER,  classType,
                "Ljava/lang/Object;"
                        + "L"  + SETTER_TYPE + ";"
                        + "L" + ORG_SFM_REFLECT_PRIMITIVE + methodSuffix + "Setter;",
                "java/lang/Object",
                new String[] { SETTER_TYPE,
                        ORG_SFM_REFLECT_PRIMITIVE + "/" + methodSuffix + "Setter" });


        {
            mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null);
            mv.visitCode();
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false);
            mv.visitInsn(RETURN);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, setMethod, "(L" + targetType + ";" + primitiveType + ")V", null, new String[] { "java/lang/Exception" });
            mv.visitCode();
            mv.visitVarInsn(ALOAD, 1);
            mv.visitVarInsn(primitiveLoadOp, 2);

            mv.visitFieldInsn(PUTFIELD, targetType, field.getName(), primitiveType);

            mv.visitInsn(RETURN);
            mv.visitMaxs(2, 3);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "set", "(L" + targetType + ";" + AsmUtils.toTypeParam(propertyType) + ")V", null, new String[] { "java/lang/Exception" });
            mv.visitCode();
            mv.visitVarInsn(ALOAD, 1);
            mv.visitVarInsn(ALOAD, 2);
            AsmUtils.invoke(mv, property, valueMethod, "()" + primitiveType);

            mv.visitFieldInsn(PUTFIELD, targetType, field.getName(), primitiveType);

            mv.visitInsn(RETURN);
            mv.visitMaxs(2, 3);
            mv.visitEnd();
        }
        appendPrimitiveSynthetic(cw, targetType, primitiveType, propertyType, classType, setMethod, primitiveLoadOp);

        appendToString(cw);

        cw.visitEnd();

        return AsmUtils.writeClassToFile(className, cw.toByteArray());

    }

    private static void appendPrimitiveSynthetic(ClassWriter cw, String targetType, String primitiveType, String propertyType, String classType, String setMethod, int primitiveLoadOp) {
        MethodVisitor mv;
        {
        mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, setMethod, "(Ljava/lang/Object;" + primitiveType + ")V", null, new String[] { "java/lang/Exception" });
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST,  targetType );
        mv.visitVarInsn(primitiveLoadOp, 2);
        mv.visitMethodInsn(INVOKEVIRTUAL,  classType , setMethod, "(L" + targetType + ";" + primitiveType + ")V", false);
        mv.visitInsn(RETURN);
        mv.visitMaxs(3, 3);
        mv.visitEnd();
        }
        {
        mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, new String[] { "java/lang/Exception" });
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST,  targetType );
        mv.visitVarInsn(ALOAD, 2);
        mv.visitTypeInsn(CHECKCAST,  propertyType );
        mv.visitMethodInsn(INVOKEVIRTUAL,  classType , "set", "(L" + targetType + ";" + AsmUtils.toTypeParam(propertyType) + ")V", false);
        mv.visitInsn(RETURN);
        mv.visitMaxs(3, 3);
        mv.visitEnd();
        }
    }

    private static String toType(Class target) {
		String name = target.getName();
		return toType(name);
	}

	private static String toType(String name) {
		return name.replace('.', '/');
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy