package com.avaje.ebean.enhance.agent;
import com.avaje.ebean.enhance.asm.MethodVisitor;
import com.avaje.ebean.enhance.asm.Opcodes;
/**
* Modify the constructor to additionally initialise the entityBeanIntercept
* field.
*
* <pre class="code">
* // added into constructor
* _ebean_intercept = new EntityBeanIntercept(this);
* </pre>
*/
public class ConstructorAdapter extends MethodVisitor implements EnhanceConstants, Opcodes {
private final ClassMeta meta;
private final String className;
private final String constructorDesc;
private boolean constructorInitializationDone;
public ConstructorAdapter(MethodVisitor mv, ClassMeta meta, String constructorDesc) {
super(Opcodes.ASM5, mv);
this.meta = meta;
this.className = meta.getClassName();
this.constructorDesc = constructorDesc;
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
super.visitMethodInsn(opcode, owner, name, desc);
addInitialisationIfRequired(opcode, owner, name, desc);
}
/**
* Add initialisation of EntityBeanIntercept to constructor.
*
* <pre>
* _ebean_intercept = new EntityBeanIntercept(this);
* </pre>
*/
public void addInitialisationIfRequired(int opcode, String owner, String name, String desc) {
if (opcode == INVOKESPECIAL && name.equals("<init>") && desc.equals("()V")) {
if (meta.isSuperClassEntity()) {
if (meta.isLog(3)) {
meta.log("... skipping intercept <init> ... handled by super class... CONSTRUCTOR:"
+ constructorDesc);
}
} else if (owner.equals(meta.getClassName())) {
if (meta.isLog(3)) {
meta.log("... skipping intercept <init> ... handled by other constructor... CONSTRUCTOR:"
+ constructorDesc);
}
} else if (owner.equals(meta.getSuperClassName())){
if (meta.isLog(2)) {
meta.log("... adding intercept <init> in CONSTRUCTOR:" + constructorDesc + " OWNER/SUPER:" + owner);
}
if (constructorInitializationDone) {
// hopefully this is never called but put it in here to be
// on the safe side.
String msg = "Error in Enhancement. Only expecting to add <init> of intercept object"
+ " once but it is trying to add it twice for " + meta.getClassName() + " CONSTRUCTOR:"
+ constructorDesc+ " OWNER:" + owner;
System.err.println(msg);
} else {
// add the initialisation of the intercept object
super.visitVarInsn(ALOAD, 0);
super.visitTypeInsn(NEW, C_INTERCEPT);
super.visitInsn(DUP);
super.visitVarInsn(ALOAD, 0);
super.visitMethodInsn(INVOKESPECIAL, C_INTERCEPT, "<init>", "(Ljava/lang/Object;)V");
super.visitFieldInsn(PUTFIELD, className, INTERCEPT_FIELD, EnhanceConstants.L_INTERCEPT);
constructorInitializationDone = true;
}
} else {
if (meta.isLog(3)) {
meta.log("... skipping intercept <init> ... incorrect type "+owner);
}
}
}
}
}