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);
}
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();
}
}
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();
}
}
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();
}
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();
}
Aggregations