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

org.sfm.reflect.asm.GetterBuilder 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.Getter;
import org.sfm.reflect.primitive.IntGetter;

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

public class GetterBuilder implements Opcodes {

	private static final String GETTER_TYPE = AsmUtils.toType(Getter.class);
	private static final String ORG_SFM_REFLECT_PRIMITIVE = AsmUtils.toType(IntGetter.class.getPackage().getName());


    public static byte[] createObjectGetter(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" + GETTER_TYPE + ";",
                "java/lang/Object", new String[] {GETTER_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();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "get",
                    "(L" + targetType + ";)" + AsmUtils.toTypeParam(propertyType), null,
                    new String[] { "java/lang/Exception" });
            mv.visitCode();
            mv.visitVarInsn(ALOAD, 1);

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

            mv.visitInsn(ARETURN);
            mv.visitMaxs(1, 2);
            mv.visitEnd();
        }

        appendBridge(cw, targetType, propertyType, classType);

        appendToString(cw);

        cw.visitEnd();

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

    }

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

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

		Class target = method.getDeclaringClass();
		Class property = method.getReturnType();
		
		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" + GETTER_TYPE + ";",
				"java/lang/Object", new String[] {GETTER_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();
		}
		{
			mv = cw.visitMethod(ACC_PUBLIC, "get",
					"(L" + targetType + ";)" + AsmUtils.toTypeParam(propertyType), null,
					new String[] { "java/lang/Exception" });
			mv.visitCode();
			mv.visitVarInsn(ALOAD, 1);

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

			mv.visitInsn(ARETURN);
			mv.visitMaxs(1, 2);
			mv.visitEnd();
		}

        appendBridge(cw, targetType, propertyType, classType);

        appendToString(cw);

		cw.visitEnd();

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

	}

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

    public static byte[] createPrimitiveGetter(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 getMethod = "get" + methodSuffix;

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


        {
            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, getMethod, "(L" + targetType + ";)" + primitiveType , null, new String[] { "java/lang/Exception" });
            mv.visitCode();
            mv.visitVarInsn(ALOAD, 1);

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

            mv.visitInsn(AsmUtils.returnOps.get(primitive));
            mv.visitMaxs(1, 2);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "get", "(L" + targetType + ";)" + AsmUtils.toTypeParam(propertyType), null, new String[] { "java/lang/Exception" });
            mv.visitCode();
            mv.visitVarInsn(ALOAD, 1);
            mv.visitFieldInsn(GETFIELD, targetType, field.getName(), primitiveType);
            mv.visitMethodInsn(INVOKESTATIC, propertyType, "valueOf", "(" +  primitiveType + ")L" + propertyType + ";" , false);
            mv.visitInsn(ARETURN);
            mv.visitMaxs(1, 2);
            mv.visitEnd();
        }
        appendPrimitiveBridges(cw, primitive, targetType, primitiveType, propertyType, classType, getMethod);

        appendToString(cw);
        cw.visitEnd();

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

    }

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

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

		Class target = method.getDeclaringClass();
		Class primitive = method.getReturnType();
		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 getMethod = "get" + methodSuffix;

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


		{
		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, getMethod, "(L" + targetType + ";)" + primitiveType , null, new String[] { "java/lang/Exception" });
		mv.visitCode();
		mv.visitVarInsn(ALOAD, 1);

		AsmUtils.invoke(mv, target, method.getName(), "()" +  primitiveType);
		
		mv.visitInsn(AsmUtils.returnOps.get(primitive));
		mv.visitMaxs(1, 2);
		mv.visitEnd();
		}
		{
		mv = cw.visitMethod(ACC_PUBLIC, "get", "(L" + targetType + ";)" + AsmUtils.toTypeParam(propertyType), null, new String[] { "java/lang/Exception" });
		mv.visitCode();
		mv.visitVarInsn(ALOAD, 1);
		AsmUtils.invoke(mv, target, method.getName(), "()" + primitiveType);
        mv.visitMethodInsn(INVOKESTATIC, propertyType, "valueOf", "(" +  primitiveType + ")L" + propertyType + ";" , false);
        mv.visitInsn(ARETURN);
		mv.visitMaxs(1, 2);
		mv.visitEnd();
		}
        appendPrimitiveBridges(cw, primitive, targetType, primitiveType, propertyType, classType, getMethod);

        appendToString(cw);
        cw.visitEnd();

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

	}

    private static void appendPrimitiveBridges(ClassWriter cw, Class primitive, String targetType, String primitiveType, String propertyType, String classType, String getMethod) {
        MethodVisitor mv;
        {
        mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, getMethod, "(Ljava/lang/Object;)" + primitiveType, null, new String[] { "java/lang/Exception" });
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST, targetType);
        mv.visitMethodInsn(INVOKEVIRTUAL,  classType , getMethod, "(L" + targetType + ";)" + primitiveType, false);
        mv.visitInsn(AsmUtils.returnOps.get(primitive));
        mv.visitMaxs(2, 2);
        mv.visitEnd();
        }
        {
        mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", null, new String[] { "java/lang/Exception" });
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST,  targetType );
        mv.visitMethodInsn(INVOKEVIRTUAL,  classType , "get", "(L" + targetType + ";)" + AsmUtils.toTypeParam(propertyType), false);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(2, 2);
        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();
    }

    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