Search in sources :

Example 1 with MethodVisitor

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

the class EnhancerClassAdapter method visitMethod.

/**
 * Method called when a method of the class is visited.
 * @param access Access for the method
 * @param name Name of the method
 * @param desc Descriptor
 * @param signature Signature
 * @param exceptions Exceptions that this method is declared to throw
 * @return Visitor to visit this (or null if not wanting to visit it)
 */
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    if (name.equals("<init>") && desc != null && desc.equals("()V")) {
        // Check for default constructor
        hasDefaultConstructor = true;
    }
    if (name.equals("writeObject") && desc != null && desc.equals("(Ljava/io/ObjectOutputStream;)V")) {
        // Has writeObject() for use in serialisation
        hasWriteObject = true;
    }
    if (name.equals("<clinit>") && desc != null && desc.equals("()V")) {
        hasStaticInitialisation = true;
    }
    MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
    if (mv == null) {
        return null;
    }
    if (name.equals("jdoPreClear") || name.equals("jdoPostLoad")) {
        // jdoPreClear/jdoPostLoad should not be enhanced (JDO spec [10.1, 10.3]
        return mv;
    } else if (name.equals("readObject") && desc != null && (desc.equals("(Ljava/io/ObjectOutputStream;)V") || desc.equals("(Ljava/io/ObjectInputStream;)V"))) {
        // readObject(ObjectInputStream), readObject(ObjectOutputStream) should not be enhanced (JDO spec [21.6])
        return mv;
    }
    String propGetterName = ClassUtils.getFieldNameForJavaBeanGetter(name);
    String propSetterName = ClassUtils.getFieldNameForJavaBeanSetter(name);
    if (// Ignore bridge methods and treat as normal methods
    (access & Opcodes.ACC_BRIDGE) != Opcodes.ACC_BRIDGE) {
        if (propGetterName != null) {
            AbstractMemberMetaData mmd = enhancer.getClassMetaData().getMetaDataForMember(propGetterName);
            if (mmd != null && mmd instanceof PropertyMetaData && mmd.getPersistenceModifier() != FieldPersistenceModifier.NONE) {
                // Property getter method "getXXX" - generated dnGetXXX
                return new EnhancerPropertyGetterAdapter(mv, enhancer, name, desc, mmd, cv);
            }
        } else if (propSetterName != null) {
            AbstractMemberMetaData mmd = enhancer.getClassMetaData().getMetaDataForMember(propSetterName);
            if (mmd != null && mmd instanceof PropertyMetaData && mmd.getPersistenceModifier() != FieldPersistenceModifier.NONE) {
                // Property setter method "setXXX" - generates dnSetXXX
                return new EnhancerPropertySetterAdapter(mv, enhancer, name, desc, mmd, cv);
            }
        }
    }
    // normal method, so just enhance it
    return new EnhancerMethodAdapter(mv, enhancer, name, desc);
}
Also used : PropertyMetaData(org.datanucleus.metadata.PropertyMetaData) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) MethodVisitor(org.datanucleus.enhancer.asm.MethodVisitor)

Example 2 with MethodVisitor

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

the class ImplementationGenerator method createSetter.

/**
 * Create a setter method for a property.
 * @param mmd MetaData for the property
 */
protected void createSetter(AbstractMemberMetaData mmd) {
    String setterName = ClassUtils.getJavaBeanSetterName(mmd.getName());
    String dnSetterName = namer.getSetMethodPrefixMethodName() + mmd.getName();
    if (inputCmd instanceof InterfaceMetaData) {
        // Interface so generate setXXX
        String fieldDesc = Type.getDescriptor(mmd.getType());
        MethodVisitor visitor = writer.visitMethod(Opcodes.ACC_PUBLIC, setterName, "(" + fieldDesc + ")V", null, null);
        visitor.visitCode();
        Label l0 = new Label();
        visitor.visitLabel(l0);
        visitor.visitVarInsn(Opcodes.ALOAD, 0);
        EnhanceUtils.addLoadForType(visitor, mmd.getType(), 1);
        visitor.visitFieldInsn(Opcodes.PUTFIELD, asmClassName, mmd.getName(), fieldDesc);
        visitor.visitInsn(Opcodes.RETURN);
        Label l2 = new Label();
        visitor.visitLabel(l2);
        visitor.visitLocalVariable("this", asmTypeDescriptor, null, l0, l2, 0);
        visitor.visitLocalVariable("val", fieldDesc, null, l0, l2, 1);
        visitor.visitMaxs(2, 2);
        visitor.visitEnd();
    } else {
        // Abstract class so generate setXXX
        String fieldDesc = Type.getDescriptor(mmd.getType());
        int setAccess = (mmd.isPublic() ? Opcodes.ACC_PUBLIC : 0) | (mmd.isProtected() ? Opcodes.ACC_PROTECTED : 0) | (mmd.isPrivate() ? Opcodes.ACC_PRIVATE : 0);
        MethodVisitor setVisitor = writer.visitMethod(setAccess, setterName, "(" + fieldDesc + ")V", null, null);
        EnhancerPropertySetterAdapter.generateSetXXXMethod(setVisitor, mmd, asmClassName, asmTypeDescriptor, namer);
        // Abstract class so generate dnSetXXX
        int access = (mmd.isPublic() ? Opcodes.ACC_PUBLIC : 0) | (mmd.isProtected() ? Opcodes.ACC_PROTECTED : 0) | (mmd.isPrivate() ? Opcodes.ACC_PRIVATE : 0);
        MethodVisitor visitor = writer.visitMethod(access, dnSetterName, "(" + fieldDesc + ")V", null, null);
        visitor.visitCode();
        Label l0 = new Label();
        visitor.visitLabel(l0);
        visitor.visitVarInsn(Opcodes.ALOAD, 0);
        EnhanceUtils.addLoadForType(visitor, mmd.getType(), 1);
        visitor.visitFieldInsn(Opcodes.PUTFIELD, asmClassName, mmd.getName(), fieldDesc);
        visitor.visitInsn(Opcodes.RETURN);
        Label l2 = new Label();
        visitor.visitLabel(l2);
        visitor.visitLocalVariable("this", asmTypeDescriptor, null, l0, l2, 0);
        visitor.visitLocalVariable("val", fieldDesc, null, l0, l2, 1);
        visitor.visitMaxs(2, 2);
        visitor.visitEnd();
    }
}
Also used : Label(org.datanucleus.enhancer.asm.Label) InterfaceMetaData(org.datanucleus.metadata.InterfaceMetaData) MethodVisitor(org.datanucleus.enhancer.asm.MethodVisitor)

Example 3 with MethodVisitor

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

the class ImplementationGenerator method createGetter.

/**
 * Create a getter method for a /property.
 * @param mmd MetaData for the property
 */
protected void createGetter(AbstractMemberMetaData mmd) {
    boolean isBoolean = mmd.getTypeName().equals("boolean");
    String getterName = ClassUtils.getJavaBeanGetterName(mmd.getName(), isBoolean);
    String dnGetterName = namer.getGetMethodPrefixMethodName() + mmd.getName();
    if (inputCmd instanceof InterfaceMetaData) {
        // Interface so generate getXXX
        String fieldDesc = Type.getDescriptor(mmd.getType());
        MethodVisitor visitor = writer.visitMethod(Opcodes.ACC_PUBLIC, getterName, "()" + fieldDesc, null, null);
        visitor.visitCode();
        Label l0 = new Label();
        visitor.visitLabel(l0);
        visitor.visitVarInsn(Opcodes.ALOAD, 0);
        visitor.visitFieldInsn(Opcodes.GETFIELD, asmClassName, mmd.getName(), fieldDesc);
        EnhanceUtils.addReturnForType(visitor, mmd.getType());
        Label l1 = new Label();
        visitor.visitLabel(l1);
        visitor.visitLocalVariable("this", asmTypeDescriptor, null, l0, l1, 0);
        visitor.visitMaxs(1, 1);
        visitor.visitEnd();
    } else {
        // Abstract class so generate getXXX
        String fieldDesc = Type.getDescriptor(mmd.getType());
        int getAccess = (mmd.isPublic() ? Opcodes.ACC_PUBLIC : 0) | (mmd.isProtected() ? Opcodes.ACC_PROTECTED : 0) | (mmd.isPrivate() ? Opcodes.ACC_PRIVATE : 0);
        MethodVisitor getVisitor = writer.visitMethod(getAccess, getterName, "()" + fieldDesc, null, null);
        EnhancerPropertyGetterAdapter.generateGetXXXMethod(getVisitor, mmd, asmClassName, asmTypeDescriptor, false, namer);
        // Abstract class so generate dnGetXXX
        int access = (mmd.isPublic() ? Opcodes.ACC_PUBLIC : 0) | (mmd.isProtected() ? Opcodes.ACC_PROTECTED : 0) | (mmd.isPrivate() ? Opcodes.ACC_PRIVATE : 0);
        MethodVisitor visitor = writer.visitMethod(access, dnGetterName, "()" + fieldDesc, null, null);
        visitor.visitCode();
        Label l0 = new Label();
        visitor.visitLabel(l0);
        visitor.visitVarInsn(Opcodes.ALOAD, 0);
        visitor.visitFieldInsn(Opcodes.GETFIELD, asmClassName, mmd.getName(), fieldDesc);
        EnhanceUtils.addReturnForType(visitor, mmd.getType());
        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) InterfaceMetaData(org.datanucleus.metadata.InterfaceMetaData) MethodVisitor(org.datanucleus.enhancer.asm.MethodVisitor)

Example 4 with MethodVisitor

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

the class PrimaryKeyGenerator method addStringConstructor.

/**
 * Method to add a constructor taking in a String.
 * @param cw The ClassWriter to use
 */
protected void addStringConstructor(ClassWriter cw) {
    if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) {
        DataNucleusEnhancer.LOGGER.debug(Localiser.msg("005020", pkClassName + "(String str)"));
    }
    MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "(Ljava/lang/String;)V", null, null);
    mv.visitCode();
    int[] pkPositions = cmd.getPKMemberPositions();
    Label[] fieldLabels = new Label[pkPositions.length];
    Label startLabel = new Label();
    mv.visitLabel(startLabel);
    // Invoke default constructor of superclass (Object)
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
    // StringTokenizer tokeniser = new StringTokenizer(str, {stringSeparator});
    mv.visitTypeInsn(Opcodes.NEW, "java/util/StringTokenizer");
    mv.visitInsn(Opcodes.DUP);
    mv.visitVarInsn(Opcodes.ALOAD, 1);
    mv.visitLdcInsn(stringSeparator);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/StringTokenizer", "<init>", "(Ljava/lang/String;Ljava/lang/String;)V");
    mv.visitVarInsn(Opcodes.ASTORE, 2);
    Label l5 = new Label();
    mv.visitLabel(l5);
    // Get the next token and set the respective field from it
    int astorePosition = 2;
    for (int i = 0; i < pkPositions.length; i++) {
        AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtRelativePosition(pkPositions[i]);
        String typeName_ASM = mmd.getTypeName().replace('.', '/');
        astorePosition++;
        // String tokenX = tokeniser.nextToken();
        mv.visitVarInsn(Opcodes.ALOAD, 2);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/StringTokenizer", "nextToken", "()Ljava/lang/String;");
        mv.visitVarInsn(Opcodes.ASTORE, astorePosition);
        fieldLabels[i] = new Label();
        mv.visitLabel(fieldLabels[i]);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        if (mmd.getType() == long.class || mmd.getType() == int.class || mmd.getType() == short.class) {
            // Uses the following pattern (e.g for Integer)
            // fieldX = Integer.valueOf(tokenX).intValue();
            String type_desc = EnhanceUtils.getTypeDescriptorForType(mmd.getTypeName());
            String wrapperClassName_ASM = "java/lang/Long";
            String wrapperConverterMethod = "longValue";
            if (mmd.getType() == int.class) {
                wrapperClassName_ASM = "java/lang/Integer";
                wrapperConverterMethod = "intValue";
            } else if (mmd.getType() == short.class) {
                wrapperClassName_ASM = "java/lang/Short";
                wrapperConverterMethod = "shortValue";
            }
            mv.visitVarInsn(Opcodes.ALOAD, astorePosition);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, wrapperClassName_ASM, "valueOf", "(Ljava/lang/String;)L" + wrapperClassName_ASM + ";");
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, wrapperClassName_ASM, wrapperConverterMethod, "()" + type_desc);
            mv.visitFieldInsn(Opcodes.PUTFIELD, className_ASM, mmd.getName(), type_desc);
        } else if (mmd.getType() == char.class) {
            mv.visitVarInsn(Opcodes.ALOAD, astorePosition);
            mv.visitInsn(Opcodes.ICONST_0);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C");
            mv.visitFieldInsn(Opcodes.PUTFIELD, className_ASM, "field1", "C");
        } else if (mmd.getType() == String.class) {
            mv.visitVarInsn(Opcodes.ALOAD, astorePosition);
            mv.visitFieldInsn(Opcodes.PUTFIELD, className_ASM, mmd.getName(), EnhanceUtils.getTypeDescriptorForType(mmd.getTypeName()));
        } else if (mmd.getType() == Long.class || mmd.getType() == Integer.class || mmd.getType() == Short.class || mmd.getType() == BigInteger.class) {
            // Uses the following pattern (e.g for Long)
            // fieldX = Long.valueOf(tokenX);
            mv.visitVarInsn(Opcodes.ALOAD, astorePosition);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, typeName_ASM, "valueOf", "(Ljava/lang/String;)L" + typeName_ASM + ";");
            mv.visitFieldInsn(Opcodes.PUTFIELD, className_ASM, mmd.getName(), "L" + typeName_ASM + ";");
        } else if (mmd.getType() == Currency.class) {
            // "fieldX = TypeX.newInstance(tokenX)"
            mv.visitVarInsn(Opcodes.ALOAD, astorePosition);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/util/Currency", "getInstance", "(Ljava/lang/String;)Ljava/util/Currency;");
            mv.visitFieldInsn(Opcodes.PUTFIELD, className_ASM, mmd.getName(), "Ljava/util/Currency;");
        } else if (mmd.getType() == TimeZone.class) {
            // "fieldX = TimeZone.getTimeZone(tokenX)"
            mv.visitVarInsn(Opcodes.ALOAD, astorePosition);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/util/TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;");
            mv.visitFieldInsn(Opcodes.PUTFIELD, className_ASM, mmd.getName(), "Ljava/util/TimeZone;");
        } else if (mmd.getType() == UUID.class) {
            // "fieldX = UUID.fromString(tokenX)"
            mv.visitVarInsn(Opcodes.ALOAD, astorePosition);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/util/UUID", "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
            mv.visitFieldInsn(Opcodes.PUTFIELD, className_ASM, mmd.getName(), "Ljava/util/UUID;");
        } else if (Date.class.isAssignableFrom(mmd.getType())) {
            // fieldX = new Date(new Long(tokenX).longValue());
            mv.visitTypeInsn(Opcodes.NEW, typeName_ASM);
            mv.visitInsn(Opcodes.DUP);
            mv.visitTypeInsn(Opcodes.NEW, "java/lang/Long");
            mv.visitInsn(Opcodes.DUP);
            mv.visitVarInsn(Opcodes.ALOAD, astorePosition);
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Long", "<init>", "(Ljava/lang/String;)V");
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, typeName_ASM, "<init>", "(J)V");
            mv.visitFieldInsn(Opcodes.PUTFIELD, className_ASM, mmd.getName(), EnhanceUtils.getTypeDescriptorForType(mmd.getTypeName()));
        } else if (Calendar.class.isAssignableFrom(mmd.getType())) {
            // fieldX = Calendar.getInstance();
            // fieldX.setTimeInMillis(Long.valueOf(tokenX).longValue());
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/util/Calendar", "getInstance", "()Ljava/util/Calendar;");
            mv.visitFieldInsn(Opcodes.PUTFIELD, className_ASM, mmd.getName(), "Ljava/util/Calendar;");
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitFieldInsn(Opcodes.GETFIELD, className_ASM, mmd.getName(), "Ljava/util/Calendar;");
            mv.visitVarInsn(Opcodes.ALOAD, astorePosition);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(Ljava/lang/String;)Ljava/lang/Long;");
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/Calendar", "setTimeInMillis", "(J)V");
        } else {
            // "fieldX = new TypeX(tokenX)"
            // TODO If this is compound identity and the related object uses SingleFieldIdentity then
            // we need to use a different constructor with this value
            String fieldTypeName = getTypeNameForField(mmd);
            String fieldTypeName_ASM = fieldTypeName.replace('.', '/');
            mv.visitTypeInsn(Opcodes.NEW, fieldTypeName_ASM);
            mv.visitInsn(Opcodes.DUP);
            mv.visitVarInsn(Opcodes.ALOAD, astorePosition);
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, fieldTypeName_ASM, "<init>", "(Ljava/lang/String;)V");
            mv.visitFieldInsn(Opcodes.PUTFIELD, className_ASM, mmd.getName(), EnhanceUtils.getTypeDescriptorForType(fieldTypeName));
        }
    }
    mv.visitInsn(Opcodes.RETURN);
    Label endLabel = new Label();
    mv.visitLabel(endLabel);
    int variableNum = 0;
    mv.visitLocalVariable("this", className_DescName, null, startLabel, endLabel, variableNum++);
    mv.visitLocalVariable("str", "Ljava/lang/String;", null, startLabel, endLabel, variableNum++);
    mv.visitLocalVariable("tokeniser", "Ljava/util/StringTokenizer;", null, l5, endLabel, variableNum++);
    for (int i = 0; i < pkPositions.length; i++) {
        mv.visitLocalVariable("token" + i, "Ljava/lang/String;", null, fieldLabels[i], endLabel, variableNum++);
    }
    mv.visitMaxs(6, variableNum);
    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)

Example 5 with MethodVisitor

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

the class PrimaryKeyGenerator method addDefaultConstructor.

/**
 * Method to add an empty default constructor.
 * @param cw The ClassWriter to use
 */
protected void addDefaultConstructor(ClassWriter cw) {
    if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) {
        DataNucleusEnhancer.LOGGER.debug(Localiser.msg("005020", pkClassName + "()"));
    }
    MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
    mv.visitCode();
    Label startLabel = new Label();
    mv.visitLabel(startLabel);
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
    mv.visitInsn(Opcodes.RETURN);
    Label endLabel = new Label();
    mv.visitLabel(endLabel);
    mv.visitLocalVariable("this", className_DescName, null, startLabel, endLabel, 0);
    mv.visitMaxs(1, 1);
    mv.visitEnd();
}
Also used : Label(org.datanucleus.enhancer.asm.Label) 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