Search in sources :

Example 6 with MethodVisitor

use of org.datanucleus.enhancer.asm.MethodVisitor in project datanucleus-core by datanucleus.

the class PrimaryKeyGenerator method addMethodHashCode.

/**
 * Method to add a hashCode() method.
 * @param cw The ClassWriter to use
 */
protected void addMethodHashCode(ClassWriter cw) {
    if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) {
        DataNucleusEnhancer.LOGGER.debug(Localiser.msg("005019", "int " + pkClassName + ".hashCode()"));
    }
    MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "hashCode", "()I", null, null);
    mv.visitCode();
    Label startLabel = new Label();
    mv.visitLabel(startLabel);
    int[] pkPositions = cmd.getPKMemberPositions();
    for (int i = 0; i < pkPositions.length; i++) {
        AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtRelativePosition(pkPositions[i]);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitFieldInsn(Opcodes.GETFIELD, className_ASM, mmd.getName(), EnhanceUtils.getTypeDescriptorForType(mmd.getTypeName()));
        if (mmd.getType() == long.class) {
            // "(int)fieldX"
            mv.visitInsn(Opcodes.L2I);
        } else if (mmd.getType() == int.class || mmd.getType() == short.class || mmd.getType() == char.class) {
        // "fieldX"
        } else {
            // "fieldX.hashCode"
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, mmd.getTypeName().replace('.', '/'), "hashCode", "()I");
        }
        if (i > 0) {
            // "^"
            mv.visitInsn(Opcodes.IXOR);
        }
    }
    mv.visitInsn(Opcodes.IRETURN);
    Label endLabel = new Label();
    mv.visitLabel(endLabel);
    mv.visitLocalVariable("this", className_DescName, null, startLabel, endLabel, 0);
    mv.visitMaxs(3, 1);
    mv.visitEnd();
}
Also used : Label(org.datanucleus.enhancer.asm.Label) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) MethodVisitor(org.datanucleus.enhancer.asm.MethodVisitor)

Example 7 with MethodVisitor

use of org.datanucleus.enhancer.asm.MethodVisitor in project tests by datanucleus.

the class DynamicEnhanceSchemaToolTest method createClass.

private static byte[] createClass(String className) throws Exception {
    ClassWriter cw = new ClassWriter(0);
    MethodVisitor mv;
    FieldVisitor fv;
    String classNameASM = className.replace('.', '/');
    // TODO Use getAsmVersionForJRE instead of V1_6 (requires proper stack map)
    cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, classNameASM, null, "java/lang/Object", new String[] {});
    fv = cw.visitField(Opcodes.ACC_PRIVATE, "name", "Ljava/lang/String;", null, null);
    fv.visitEnd();
    // Default Constructor
    {
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
        mv.visitInsn(Opcodes.RETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + classNameASM + ";", null, l0, l1, 0);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    // String getName()
    {
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "getName", "()Ljava/lang/String;", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitFieldInsn(Opcodes.GETFIELD, classNameASM, "name", "Ljava/lang/String;");
        mv.visitInsn(Opcodes.ARETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + classNameASM + ";", null, l0, l1, 0);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    // void setName(String)
    {
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "setName", "(Ljava/lang/String;)V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitFieldInsn(Opcodes.PUTFIELD, classNameASM, "name", "Ljava/lang/String;");
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitInsn(Opcodes.RETURN);
        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitLocalVariable("this", "L" + classNameASM + ";", null, l0, l2, 0);
        mv.visitLocalVariable("s", "Ljava/lang/String;", null, l0, l2, 1);
        mv.visitMaxs(2, 2);
        mv.visitEnd();
    }
    // Object getProperty(String)
    {
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "getProperty", "(Ljava/lang/String;)Ljava/lang/Object;", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitInsn(Opcodes.ACONST_NULL);
        mv.visitVarInsn(Opcodes.ASTORE, 2);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitLdcInsn("name");
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
        Label l2 = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, l2);
        Label l3 = new Label();
        mv.visitLabel(l3);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitFieldInsn(Opcodes.GETFIELD, classNameASM, "name", "Ljava/lang/String;");
        mv.visitVarInsn(Opcodes.ASTORE, 2);
        mv.visitLabel(l2);
        mv.visitVarInsn(Opcodes.ALOAD, 2);
        mv.visitInsn(Opcodes.ARETURN);
        Label l4 = new Label();
        mv.visitLabel(l4);
        mv.visitLocalVariable("this", "L" + classNameASM + ";", null, l0, l4, 0);
        mv.visitLocalVariable("propertyName", "Ljava/lang/String;", null, l0, l4, 1);
        mv.visitLocalVariable("o", "Ljava/lang/Object;", null, l1, l4, 2);
        mv.visitMaxs(2, 3);
        mv.visitEnd();
    }
    // void setProperty(String, Object)
    {
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "setProperty", "(Ljava/lang/String;Ljava/lang/Object;)V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitLdcInsn("name");
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
        Label l1 = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, l1);
        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitVarInsn(Opcodes.ALOAD, 2);
        mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String");
        mv.visitFieldInsn(Opcodes.PUTFIELD, classNameASM, "name", "Ljava/lang/String;");
        mv.visitLabel(l1);
        mv.visitInsn(Opcodes.RETURN);
        Label l3 = new Label();
        mv.visitLabel(l3);
        mv.visitLocalVariable("this", "L" + classNameASM + ";", null, l0, l3, 0);
        mv.visitLocalVariable("propertyName", "Ljava/lang/String;", null, l0, l3, 1);
        mv.visitLocalVariable("value", "Ljava/lang/Object;", null, l0, l3, 2);
        mv.visitMaxs(2, 3);
        mv.visitEnd();
    }
    return cw.toByteArray();
}
Also used : Label(org.datanucleus.enhancer.asm.Label) FieldVisitor(org.datanucleus.enhancer.asm.FieldVisitor) ClassWriter(org.datanucleus.enhancer.asm.ClassWriter) MethodVisitor(org.datanucleus.enhancer.asm.MethodVisitor)

Example 8 with MethodVisitor

use of org.datanucleus.enhancer.asm.MethodVisitor in project datanucleus-core by datanucleus.

the class ImplementationGenerator method createDefaultConstructor.

/**
 * Create a default constructor, assuming that there is no persistent superclass.
 */
protected void createDefaultConstructor() {
    MethodVisitor visitor = writer.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
    visitor.visitCode();
    Label l0 = new Label();
    visitor.visitLabel(l0);
    visitor.visitVarInsn(Opcodes.ALOAD, 0);
    visitor.visitMethodInsn(Opcodes.INVOKESPECIAL, fullSuperclassName.replace('.', '/'), "<init>", "()V");
    visitor.visitInsn(Opcodes.RETURN);
    Label l1 = new Label();
    visitor.visitLabel(l1);
    visitor.visitLocalVariable("this", asmTypeDescriptor, null, l0, l1, 0);
    visitor.visitMaxs(1, 1);
    visitor.visitEnd();
}
Also used : Label(org.datanucleus.enhancer.asm.Label) MethodVisitor(org.datanucleus.enhancer.asm.MethodVisitor)

Example 9 with MethodVisitor

use of org.datanucleus.enhancer.asm.MethodVisitor in project datanucleus-core by datanucleus.

the class PrimaryKeyGenerator method addMethodEquals.

/**
 * Method to add an equals() method.
 * @param cw The ClassWriter to use
 */
protected void addMethodEquals(ClassWriter cw) {
    if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) {
        DataNucleusEnhancer.LOGGER.debug(Localiser.msg("005019", "boolean " + pkClassName + ".equals(Object obj)"));
    }
    MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
    mv.visitCode();
    Label startLabel = new Label();
    mv.visitLabel(startLabel);
    // if (obj == this) {return true;}
    mv.visitVarInsn(Opcodes.ALOAD, 1);
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    Label l1 = new Label();
    mv.visitJumpInsn(Opcodes.IF_ACMPNE, l1);
    mv.visitInsn(Opcodes.ICONST_1);
    mv.visitInsn(Opcodes.IRETURN);
    mv.visitLabel(l1);
    // if (!(obj instanceof ThePK)) {return false;}
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    mv.visitVarInsn(Opcodes.ALOAD, 1);
    mv.visitTypeInsn(Opcodes.INSTANCEOF, className_ASM);
    Label l3 = new Label();
    mv.visitJumpInsn(Opcodes.IFNE, l3);
    mv.visitInsn(Opcodes.ICONST_0);
    mv.visitInsn(Opcodes.IRETURN);
    mv.visitLabel(l3);
    // ThePK other = (ThePK)obj;
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    mv.visitVarInsn(Opcodes.ALOAD, 1);
    mv.visitTypeInsn(Opcodes.CHECKCAST, className_ASM);
    mv.visitVarInsn(Opcodes.ASTORE, 2);
    Label compareStartLabel = new Label();
    mv.visitLabel(compareStartLabel);
    int[] pkPositions = cmd.getPKMemberPositions();
    Label compareSepLabel = null;
    for (int i = 0; i < pkPositions.length; i++) {
        AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtRelativePosition(pkPositions[i]);
        if (mmd.getType() == long.class) {
            // "fieldX == other.fieldX"
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitFieldInsn(Opcodes.GETFIELD, className_ASM, mmd.getName(), EnhanceUtils.getTypeDescriptorForType(mmd.getTypeName()));
            mv.visitVarInsn(Opcodes.ALOAD, 2);
            mv.visitFieldInsn(Opcodes.GETFIELD, className_ASM, mmd.getName(), EnhanceUtils.getTypeDescriptorForType(mmd.getTypeName()));
            mv.visitInsn(Opcodes.LCMP);
            if (i == 0) {
                compareSepLabel = new Label();
            }
            mv.visitJumpInsn(Opcodes.IFNE, compareSepLabel);
        } else if (mmd.getType() == int.class || mmd.getType() == short.class || mmd.getType() == char.class) {
            // "fieldX == other.fieldX"
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitFieldInsn(Opcodes.GETFIELD, className_ASM, mmd.getName(), EnhanceUtils.getTypeDescriptorForType(mmd.getTypeName()));
            mv.visitVarInsn(Opcodes.ALOAD, 2);
            mv.visitFieldInsn(Opcodes.GETFIELD, className_ASM, mmd.getName(), EnhanceUtils.getTypeDescriptorForType(mmd.getTypeName()));
            if (i == 0) {
                compareSepLabel = new Label();
            }
            mv.visitJumpInsn(Opcodes.IF_ICMPNE, compareSepLabel);
        } else {
            // "fieldX.equals(other.fieldX)"
            String typeName = getTypeNameForField(mmd);
            String typeName_ASM = typeName.replace('.', '/');
            String typeNameDesc = "L" + typeName_ASM + ";";
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitFieldInsn(Opcodes.GETFIELD, className_ASM, mmd.getName(), typeNameDesc);
            mv.visitVarInsn(Opcodes.ALOAD, 2);
            mv.visitFieldInsn(Opcodes.GETFIELD, className_ASM, mmd.getName(), typeNameDesc);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, typeName_ASM, "equals", "(Ljava/lang/Object;)Z");
            if (i == 0) {
                compareSepLabel = new Label();
            }
            mv.visitJumpInsn(Opcodes.IFEQ, compareSepLabel);
        }
    }
    mv.visitInsn(Opcodes.ICONST_1);
    mv.visitInsn(Opcodes.IRETURN);
    mv.visitLabel(compareSepLabel);
    mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { className_ASM }, 0, null);
    mv.visitInsn(Opcodes.ICONST_0);
    mv.visitInsn(Opcodes.IRETURN);
    Label endLabel = new Label();
    mv.visitLabel(endLabel);
    mv.visitLocalVariable("this", className_DescName, null, startLabel, endLabel, 0);
    mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, startLabel, endLabel, 1);
    mv.visitLocalVariable("other", className_DescName, null, compareStartLabel, endLabel, 2);
    // TODO Can be (2, 3) in some situations, e.g if char is one of PK fields?
    mv.visitMaxs(4, 3);
    mv.visitEnd();
}
Also used : Label(org.datanucleus.enhancer.asm.Label) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) MethodVisitor(org.datanucleus.enhancer.asm.MethodVisitor)

Example 10 with MethodVisitor

use of org.datanucleus.enhancer.asm.MethodVisitor in project datanucleus-core by datanucleus.

the class PrimaryKeyGenerator method addMethodToString.

/**
 * Method to add a toString() method.
 * @param cw The ClassWriter to use
 */
protected void addMethodToString(ClassWriter cw) {
    if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) {
        DataNucleusEnhancer.LOGGER.debug(Localiser.msg("005019", "String " + pkClassName + ".toString()"));
    }
    MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
    mv.visitCode();
    Label startLabel = new Label();
    mv.visitLabel(startLabel);
    // "StringBuilder str = new StringBuilder();"
    mv.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder");
    mv.visitInsn(Opcodes.DUP);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V");
    mv.visitVarInsn(Opcodes.ASTORE, 1);
    Label l1 = new Label();
    mv.visitLabel(l1);
    // "str.append(field1).append(":").append(field2) ..." etc
    mv.visitVarInsn(Opcodes.ALOAD, 1);
    int[] pkPositions = cmd.getPKMemberPositions();
    for (int i = 0; i < pkPositions.length; i++) {
        AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtRelativePosition(pkPositions[i]);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitFieldInsn(Opcodes.GETFIELD, className_ASM, mmd.getName(), EnhanceUtils.getTypeDescriptorForType(mmd.getTypeName()));
        // Use most representive form of "StringBuilder.append()"
        if (mmd.getType() == int.class || mmd.getType() == long.class || mmd.getType() == float.class || mmd.getType() == double.class) {
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(" + EnhanceUtils.getTypeDescriptorForType(mmd.getTypeName()) + ")Ljava/lang/StringBuilder;");
        } else if (mmd.getType() == char.class) {
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(" + EnhanceUtils.getTypeDescriptorForType(mmd.getTypeName()) + ")Ljava/lang/StringBuilder;");
        } else if (mmd.getType() == String.class) {
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
        } else if (Date.class.isAssignableFrom(mmd.getType())) {
            // Use the long value of the date (millisecs)
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, mmd.getTypeName().replace('.', '/'), "getTime", "()J");
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(J)Ljava/lang/StringBuilder;");
        } else if (Calendar.class.isAssignableFrom(mmd.getType())) {
            // Use the long value of the Calendar (millisecs)
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/Calendar", "getTime", "()Ljava/util/Date;");
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/Date", "getTime", "()J");
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(J)Ljava/lang/StringBuilder;");
        } else if (mmd.getType() == TimeZone.class) {
            // Use the ID of the TimeZone
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/TimeZone", "getID", "()Ljava/lang/String;");
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
        } else {
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, mmd.getTypeName().replace('.', '/'), "toString", "()Ljava/lang/String;");
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
        }
        if (i < (pkPositions.length - 1)) {
            // Add separator ({stringSeparator})
            mv.visitLdcInsn(stringSeparator);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
        }
    }
    mv.visitInsn(Opcodes.POP);
    // "return str.toString();"
    mv.visitVarInsn(Opcodes.ALOAD, 1);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
    mv.visitInsn(Opcodes.ARETURN);
    Label endLabel = new Label();
    mv.visitLabel(endLabel);
    mv.visitLocalVariable("this", className_DescName, null, startLabel, endLabel, 0);
    mv.visitLocalVariable("str", "Ljava/lang/StringBuilder;", null, l1, endLabel, 1);
    mv.visitMaxs(pkPositions.length, 2);
    mv.visitEnd();
}
Also used : TimeZone(java.util.TimeZone) Label(org.datanucleus.enhancer.asm.Label) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) Date(java.util.Date) MethodVisitor(org.datanucleus.enhancer.asm.MethodVisitor)

Aggregations

MethodVisitor (org.datanucleus.enhancer.asm.MethodVisitor)10 Label (org.datanucleus.enhancer.asm.Label)9 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)5 Date (java.util.Date)2 TimeZone (java.util.TimeZone)2 InterfaceMetaData (org.datanucleus.metadata.InterfaceMetaData)2 ClassWriter (org.datanucleus.enhancer.asm.ClassWriter)1 FieldVisitor (org.datanucleus.enhancer.asm.FieldVisitor)1 PropertyMetaData (org.datanucleus.metadata.PropertyMetaData)1