access &= ~ACC_NATIVE;
access &= ~ACC_ABSTRACT;
access = ProxettaAsmUtil.makePrivateFinalAccess(access);
final MethodVisitor mv = wd.dest.visitMethod(access, td.methodName(), td.msign.getDescription(), null, null);
mv.visitCode();
//*** VISIT ADVICE - called for each aspect and each method
aspectData.getAdviceClassReader().accept(new EmptyClassVisitor() {
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (name.equals(executeMethodName) == false) {
return null;
}
return new HistoryMethodAdapter(mv) {
@Override
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
if (owner.equals(aspectData.adviceReference)) {
owner = wd.thisReference; // [F5]
name = adviceFieldName(name, aspectData.aspectIndex);
}
super.visitFieldInsn(opcode, owner, name, desc);
}
@Override
public void visitVarInsn(int opcode, int var) {
var += (var == 0 ? 0 : td.msign.getAllArgumentsSize());
super.visitVarInsn(opcode, var); // [F1]
}
@Override
public void visitIincInsn(int var, int increment) {
var += (var == 0 ? 0 : td.msign.getAllArgumentsSize());
super.visitIincInsn(var, increment); // [F1]
}
@Override
public void visitInsn(int opcode) {
if (opcode == ARETURN) {
visitReturn(mv, td.msign, true);
return;
}
if (traceNext == true) {
if ((opcode == POP) || (opcode == POP2)) { // [F3] - invoke invoked without assignment
return;
}
}
super.visitInsn(opcode);
}
@SuppressWarnings({"ParameterNameDiffersFromOverriddenParameter"})
@Override
public void visitMethodInsn(int opcode, String string, String mname, String mdesc) {
if ((opcode == INVOKEVIRTUAL) || (opcode == INVOKEINTERFACE) || (opcode == INVOKESPECIAL)) {
if (string.equals(aspectData.adviceReference)) {
string = wd.thisReference;
mname = adviceMethodName(mname, aspectData.aspectIndex);
}
} else
if (opcode == INVOKESTATIC) {
if (string.equals(aspectData.adviceReference)) {
string = wd.thisReference;
mname = adviceMethodName(mname, aspectData.aspectIndex);
} else
if (string.endsWith('/' + TARGET_CLASS_NAME) == true) {
if (isInvokeMethod(mname, mdesc)) { // [R7]
if (td.isLastMethodInChain()) { // last proxy method just calls super target method
if (wd.isWrapper() == false) {
// PROXY
loadSpecialMethodArguments(mv, td.msign);
mv.visitMethodInsn(INVOKESPECIAL, wd.superReference, td.msign.getMethodName(), td.msign.getDescription());
} else {
// WRAPPER
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, wd.thisReference, wd.wrapperRef, wd.wrapperType);
loadVirtualMethodArguments(mv, td.msign);
if (wd.wrapInterface) {
mv.visitMethodInsn(INVOKEINTERFACE, wd.wrapperType.substring(1, wd.wrapperType.length() - 1), td.msign.getMethodName(), td.msign.getDescription());
} else {
mv.visitMethodInsn(INVOKEVIRTUAL, wd.wrapperType.substring(1, wd.wrapperType.length() - 1), td.msign.getMethodName(), td.msign.getDescription());
}
}
prepareReturnValue(mv, td.msign, aspectData.maxLocalVarOffset); // [F4]
traceNext = true;
} else { // calls next proxy method
loadSpecialMethodArguments(mv, td.msign);
mv.visitMethodInsn(INVOKESPECIAL, wd.thisReference, td.nextMethodName(), td.msign.getDescription());
visitReturn(mv, td.msign, false);
}
return;
}
if (isArgumentsCountMethod(mname, mdesc)) { // [R2]
ProxyTargetReplacement.argumentsCount(mv, td.msign);
return;
}
if (isArgumentTypeMethod(mname, mdesc)) { // [R3]
int argIndex = this.getArgumentIndex();
ProxyTargetReplacement.argumentType(mv, td.msign, argIndex);
return;
}
if (isArgumentMethod(mname, mdesc)) { // [R4]
int argIndex = this.getArgumentIndex();
ProxyTargetReplacement.argument(mv, td.msign, argIndex);
return;
}
if (isSetArgumentMethod(mname, mdesc)) { // [R5]
int argIndex = this.getArgumentIndex();
checkArgumentIndex(td.msign, argIndex);
mv.visitInsn(POP);
storeMethodArgumentFromObject(mv, td.msign, argIndex);
return;
}
if (isCreateArgumentsArrayMethod(mname, mdesc)) { // [R6]
ProxyTargetReplacement.createArgumentsArray(mv, td.msign);
return;
}
if (isCreateArgumentsClassArrayMethod(mname, mdesc)) { // [R11]
ProxyTargetReplacement.createArgumentsClassArray(mv, td.msign);
return;
}
if (isTargetMethod(mname, mdesc)) { // [R9.1]
mv.visitVarInsn(ALOAD, 0);
return;
}
if (isTargetClassMethod(mname, mdesc)) { // [R9]
ProxyTargetReplacement.targetClass(mv, td.msign);
//ProxyTargetReplacement.targetClass(mv, wd.superReference);
return;
}
if (isTargetMethodNameMethod(mname, mdesc)) { // [R10]
ProxyTargetReplacement.targetMethodName(mv, td.msign);
return;
}
if (isTargetMethodSignatureMethod(mname, mdesc)) {
ProxyTargetReplacement.targetMethodSignature(mv, td.msign);
return;
}
if (isTargetMethodDescriptionMethod(mname, mdesc)) {
ProxyTargetReplacement.targetMethodDescription(mv, td.msign);
return;
}
if (isInfoMethod(mname, mdesc)) {
ProxyTargetReplacement.info(mv, td.msign);
return;
}
if (isReturnTypeMethod(mname, mdesc)) { // [R11]
ProxyTargetReplacement.returnType(mv, td.msign);
return;
}
if (isReturnValueMethod(mname, mdesc)) {
castToReturnType(mv, td.msign);
return;
}
if (isTargetMethodAnnotationMethod(mname, mdesc)) {
String[] args = getLastTwoStringArguments();
// pop current two args
mv.visitInsn(POP);
mv.visitInsn(POP);
ProxyTargetReplacement.targetMethodAnnotation(mv, td.msign, args);
return;
}
if (isTargetClassAnnotationMethod(mname, mdesc)) {
String[] args = getLastTwoStringArguments();
// pop current two args
mv.visitInsn(POP);
mv.visitInsn(POP);
ProxyTargetReplacement.targetClassAnnotation(mv, td.msign.getClassInfo(), args);
return;
}
}