/**************************************************************************************
* Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. *
* http://aspectwerkz.codehaus.org *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the LGPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package org.codehaus.aspectwerkz.transform.inlining.compiler;
import org.codehaus.aspectwerkz.DeploymentModel;
import org.codehaus.aspectwerkz.aspect.AdviceInfo;
import org.codehaus.aspectwerkz.aspect.AdviceType;
import org.codehaus.aspectwerkz.aspect.container.AspectFactoryManager;
import org.codehaus.aspectwerkz.cflow.CflowCompiler;
import org.codehaus.aspectwerkz.definition.AspectDefinition;
import org.codehaus.aspectwerkz.exception.DefinitionException;
import org.codehaus.aspectwerkz.joinpoint.management.AdviceInfoContainer;
import org.codehaus.aspectwerkz.reflect.ClassInfo;
import org.codehaus.aspectwerkz.reflect.ClassInfoHelper;
import org.codehaus.aspectwerkz.reflect.MethodInfo;
import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo;
import org.codehaus.aspectwerkz.transform.TransformationConstants;
import org.codehaus.aspectwerkz.transform.JoinPointCompiler;
import org.codehaus.aspectwerkz.transform.inlining.AdviceMethodInfo;
import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
import org.codehaus.aspectwerkz.transform.inlining.AspectInfo;
import org.codehaus.aspectwerkz.transform.inlining.spi.AspectModel;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* FIXME doc
*
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public class AspectWerkzAspectModel implements AspectModel, Opcodes, TransformationConstants {
protected final List m_customProceedMethodStructs;
public AspectWerkzAspectModel() {
m_customProceedMethodStructs = null;
//prototype
}
private AspectWerkzAspectModel(CompilationInfo.Model compilationModel) {
m_customProceedMethodStructs = new ArrayList(0);
collectCustomProceedMethods(compilationModel, compilationModel.getAdviceInfoContainer());
}
public static final String TYPE = AspectWerkzAspectModel.class.getName();
public AspectModel getInstance(CompilationInfo.Model compilationModel) {
// return a new instance to handle custom proceed
return new AspectWerkzAspectModel(compilationModel);
}
public String getAspectModelType() {
return TYPE;
}
public void defineAspect(ClassInfo aspectClassInfo, AspectDefinition aspectDef, ClassLoader loader) {
//FIXME - refactor there ?
}
public AroundClosureClassInfo getAroundClosureClassInfo() {
if (m_customProceedMethodStructs.isEmpty()) {
//let the compiler deal with JP / SJP interface
return new AroundClosureClassInfo(OBJECT_CLASS_NAME, new String[0]);
} else {
// get the custom join point interfaces
Set interfaces = new HashSet();
for (Iterator it = m_customProceedMethodStructs.iterator(); it.hasNext();) {
MethodInfo methodInfo = ((CustomProceedMethodStruct) it.next()).customProceed;
interfaces.add(methodInfo.getDeclaringType().getName().replace('.', '/'));
}
return new AroundClosureClassInfo(OBJECT_CLASS_NAME, (String[]) interfaces.toArray(new String[]{}));
}
}
public void createMandatoryMethods(ClassWriter cw, JoinPointCompiler compiler) {
createCustomProceedMethods(cw, (AbstractJoinPointCompiler)compiler);
}
public void createInvocationOfAroundClosureSuperClass(MethodVisitor cv) {
;// AW model has no super class apart Object, which is handled by the compiler
}
/**
* Create and initialize the aspect field for a specific aspect (qualified since it depends
* on the param, deployment model, container etc).
* And creates instantiation of aspects using the Aspects.aspectOf() methods which uses the AspectContainer impls.
* We are using the THIS_CLASS classloader since the aspect can be visible from that one only f.e. for get/set/call
*
* TODO for perJVM and perClass aspect this means we eagerly load the aspect. Different from AJ
*
* @param cw
* @param cv
* @param aspectInfo
* @param joinPointClassName
*/
public void createAndStoreStaticAspectInstantiation(ClassVisitor cw, MethodVisitor cv, AspectInfo aspectInfo, String joinPointClassName) {
String aspectClassSignature = aspectInfo.getAspectClassSignature();
String aspectClassName = aspectInfo.getAspectClassName();
// retrieve the aspect set it to the field
DeploymentModel deploymentModel = aspectInfo.getDeploymentModel();
if (CflowCompiler.isCflowClass(aspectClassName)) {
cw.visitField(ACC_PRIVATE + ACC_STATIC, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null);
// handle Cflow native aspectOf
//TODO: would be better done with a custom aspectModel for cflow, or with default factory handling
//FIXME AVF what does factory do there ?
cv.visitMethodInsn(
INVOKESTATIC,
aspectClassName,
CflowCompiler.CFLOW_ASPECTOF_METHOD_NAME,
"()" + aspectClassSignature
);
cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature);
} else if (deploymentModel.equals(DeploymentModel.PER_JVM)) {
cw.visitField(ACC_PRIVATE + ACC_STATIC, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null);
cv.visitMethodInsn(
INVOKESTATIC,
aspectInfo.getAspectFactoryClassName(),
"aspectOf",
"()"+aspectClassSignature
);
cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature);
} else if (deploymentModel.equals(DeploymentModel.PER_CLASS)) {
cw.visitField(ACC_PRIVATE + ACC_STATIC, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null);
cv.visitFieldInsn(GETSTATIC, joinPointClassName, THIS_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
cv.visitMethodInsn(
INVOKESTATIC,
aspectInfo.getAspectFactoryClassName(),
"aspectOf",
"(Ljava/lang/Class;)"+aspectClassSignature
);
cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature);
} else if (AbstractJoinPointCompiler.requiresCallerOrCallee(deploymentModel)) {
cw.visitField(ACC_PRIVATE, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null);
} else {
throw new UnsupportedOperationException(
"unsupported deployment model - " +
aspectInfo.getAspectClassName() + " " +
deploymentModel
);
}
}
/**
* Initializes instance level aspects, retrieves them from the target instance through the
* <code>HasInstanceLevelAspect</code> interfaces.
* <p/>
* Use by 'perInstance', 'perThis' and 'perTarget' deployment models.
*
* @param cv
* @param aspectInfo
* @param input
*/
public void createAndStoreRuntimeAspectInstantiation(final MethodVisitor cv,
final CompilerInput input,
final AspectInfo aspectInfo) {
// gen code: if (Aspects.hasAspect(...) { aspectField = (<TYPE>)((HasInstanceLocalAspect)CALLER).aw$getAspect(className, qualifiedName, containerClassName) }
if (DeploymentModel.PER_INSTANCE.equals(aspectInfo.getDeploymentModel())) {//TODO && callerIndex >= 0
//storeAspectInstance(cv, input, aspectInfo, input.callerIndex);
} else if (DeploymentModel.PER_THIS.equals(aspectInfo.getDeploymentModel())
&& input.callerIndex >= 0) {
Label hasAspectCheck = pushPerXCondition(cv, input.callerIndex, aspectInfo);
storeAspectInstance(cv, input, aspectInfo, input.callerIndex);
cv.visitLabel(hasAspectCheck);
} else if (DeploymentModel.PER_TARGET.equals(aspectInfo.getDeploymentModel())
&& input.calleeIndex >= 0) {
Label hasAspectCheck = pushPerXCondition(cv, input.calleeIndex, aspectInfo);
storeAspectInstance(cv, input, aspectInfo, input.calleeIndex);
cv.visitLabel(hasAspectCheck);
}
if (aspectInfo.getDeploymentModel() == DeploymentModel.PER_INSTANCE) {//TODO refactor with previous if block
// gen code: aspectField = (<TYPE>)((HasInstanceLocalAspect)CALLER).aw$getAspect(className, qualifiedName, containerClassName)
AbstractJoinPointCompiler.loadJoinPointInstance(cv, input);
if (input.callerIndex >= 0) {
cv.visitVarInsn(ALOAD, input.callerIndex);
} else {
// caller instance not available - skipping
//TODO clean up should not occur
}
cv.visitMethodInsn(
INVOKESTATIC,
aspectInfo.getAspectFactoryClassName(),
"aspectOf",
"(Ljava/lang/Object;)"+aspectInfo.getAspectClassSignature()
);
// cv.visitLdcInsn(aspectInfo.getAspectClassName().replace('/', '.'));
// cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
// AsmHelper.loadStringConstant(cv, aspectInfo.getAspectDefinition().getContainerClassName());
// cv.visitMethodInsn(
// INVOKEINTERFACE,
// HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME,
// INSTANCE_LEVEL_GETASPECT_METHOD_NAME,
// INSTANCE_LEVEL_GETASPECT_METHOD_SIGNATURE
// );
// cv.visitTypeInsn(CHECKCAST, aspectInfo.getAspectClassName());
cv.visitFieldInsn(
PUTFIELD,
input.joinPointClassName,
aspectInfo.getAspectFieldName(),
aspectInfo.getAspectClassSignature()
);
}
}
/**
* Load aspect instance on stack
*
* @param cv
* @param input
* @param aspectInfo
*/
public void loadAspect(final MethodVisitor cv,
final CompilerInput input,
final AspectInfo aspectInfo) {
DeploymentModel deploymentModel = aspectInfo.getDeploymentModel();
if (DeploymentModel.PER_JVM.equals(deploymentModel)
|| DeploymentModel.PER_CLASS.equals(deploymentModel)) {
cv.visitFieldInsn(
GETSTATIC, input.joinPointClassName, aspectInfo.getAspectFieldName(),
aspectInfo.getAspectClassSignature()
);
} else if (DeploymentModel.PER_INSTANCE.equals(deploymentModel)) {
AbstractJoinPointCompiler.loadJoinPointInstance(cv, input);
cv.visitFieldInsn(
GETFIELD, input.joinPointClassName, aspectInfo.getAspectFieldName(),
aspectInfo.getAspectClassSignature()
);
} else if (DeploymentModel.PER_THIS.equals(deploymentModel)) {
AbstractJoinPointCompiler.loadJoinPointInstance(cv, input);
cv.visitFieldInsn(
GETFIELD,
input.joinPointClassName,
aspectInfo.getAspectFieldName(),
aspectInfo.getAspectClassSignature()
);
//FIXME see FIXME on aspect instantion
Label nullCheck = new Label();
cv.visitJumpInsn(IFNONNULL, nullCheck);
storeAspectInstance(cv, input, aspectInfo, input.callerIndex);
cv.visitLabel(nullCheck);
AbstractJoinPointCompiler.loadJoinPointInstance(cv, input);
cv.visitFieldInsn(
GETFIELD,
input.joinPointClassName,
aspectInfo.getAspectFieldName(),
aspectInfo.getAspectClassSignature()
);
} else if (DeploymentModel.PER_TARGET.equals(deploymentModel)) {
AbstractJoinPointCompiler.loadJoinPointInstance(cv, input);
cv.visitFieldInsn(
GETFIELD,
input.joinPointClassName,
aspectInfo.getAspectFieldName(),
aspectInfo.getAspectClassSignature()
);
//FIXME see FIXME on aspect instantion
Label nullCheck = new Label();
cv.visitJumpInsn(IFNONNULL, nullCheck);
storeAspectInstance(cv, input, aspectInfo, input.calleeIndex);
cv.visitLabel(nullCheck);
AbstractJoinPointCompiler.loadJoinPointInstance(cv, input);
cv.visitFieldInsn(
GETFIELD,
input.joinPointClassName,
aspectInfo.getAspectFieldName(),
aspectInfo.getAspectClassSignature()
);
} else {
throw new DefinitionException("deployment model [" + deploymentModel + "] is not supported");
}
}
public void createAroundAdviceArgumentHandling(MethodVisitor cv,
CompilerInput input,
Type[] joinPointArgumentTypes,
AdviceMethodInfo adviceMethodInfo) {
defaultCreateAroundAdviceArgumentHandling(
cv,
input,
joinPointArgumentTypes,
adviceMethodInfo
);
}
public void createBeforeOrAfterAdviceArgumentHandling(MethodVisitor cv,
CompilerInput input,
Type[] joinPointArgumentTypes,
AdviceMethodInfo adviceMethodInfo,
int specialArgIndex) {
defaultCreateBeforeOrAfterAdviceArgumentHandling(
cv,
input,
joinPointArgumentTypes,
adviceMethodInfo,
specialArgIndex
);
}
public boolean requiresReflectiveInfo() {
// custom proceed() JoinPoint will not be recognize by the default logic
return m_customProceedMethodStructs.size() > 0;
}
///////---------- Helpers
/**
* Generate a "if Aspects.hasAspect(qName, instance)"
*
* @param cv
* @param perInstanceIndex
* @param aspectInfo
* @return
*/
private Label pushPerXCondition(final MethodVisitor cv,
final int perInstanceIndex,
final AspectInfo aspectInfo) {
Label hasAspectCheck = new Label();
cv.visitVarInsn(ALOAD, perInstanceIndex);
cv.visitMethodInsn(
INVOKESTATIC,
aspectInfo.getAspectFactoryClassName(),
FACTORY_HASASPECT_METHOD_NAME,
FACTORY_HASASPECT_PEROBJECT_METHOD_SIGNATURE
);
cv.visitJumpInsn(IFEQ, hasAspectCheck);
return hasAspectCheck;
}
/**
* Creates the instance of an aspect by invoking
* "HasInstanceLevelAspect.aw$getAspect(String, String)" on perInstanceIndex variable
* and stores the aspect instance in the joinpoint instance field
*/
private void storeAspectInstance(final MethodVisitor cv,
final CompilerInput input,
final AspectInfo aspectInfo,
final int perInstanceIndex) {
AbstractJoinPointCompiler.loadJoinPointInstance(cv, input);
if (perInstanceIndex >= 0) {
cv.visitVarInsn(ALOAD, perInstanceIndex);
}
cv.visitMethodInsn(
INVOKESTATIC,
aspectInfo.getAspectFactoryClassName(),
FACTORY_ASPECTOF_METHOD_NAME,
"(Ljava/lang/Object;)" + aspectInfo.getAspectClassSignature()
);
//
// cv.visitLdcInsn(aspectInfo.getAspectClassName().replace('/', '.'));
// cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
// AsmHelper.loadStringConstant(cv, aspectInfo.getAspectDefinition().getContainerClassName());
// cv.visitMethodInsn(
// INVOKEINTERFACE,
// HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME,
// INSTANCE_LEVEL_GETASPECT_METHOD_NAME,
// INSTANCE_LEVEL_GETASPECT_METHOD_SIGNATURE
// );
//
// cv.visitTypeInsn(CHECKCAST, aspectInfo.getAspectClassName());
cv.visitFieldInsn(
PUTFIELD,
input.joinPointClassName,
aspectInfo.getAspectFieldName(),
aspectInfo.getAspectClassSignature()
);
}
/**
* Creates the custom proceed methods.
*/
private void createCustomProceedMethods(ClassWriter cw, AbstractJoinPointCompiler compiler) {
Set addedMethodSignatures = new HashSet();
for (Iterator it = m_customProceedMethodStructs.iterator(); it.hasNext();) {
CustomProceedMethodStruct customProceedStruct = (CustomProceedMethodStruct) it.next();
MethodInfo methodInfo = customProceedStruct.customProceed;
final String desc = methodInfo.getSignature();
if (addedMethodSignatures.contains(desc)) {
continue;
}
addedMethodSignatures.add(desc);
MethodVisitor cv = cw.visitMethod(
ACC_PUBLIC | ACC_FINAL,
PROCEED_METHOD_NAME,
desc,
null,
new String[]{
THROWABLE_CLASS_NAME
}
);
// update the joinpoint instance with the given values
// starts at 1 since first arg is the custom join point by convention
//TODO see JoinPointManage for this custom jp is first convention
int argStackIndex = 1;
for (int i = 1; i < customProceedStruct.adviceToTargetArgs.length; i++) {
int targetArg = customProceedStruct.adviceToTargetArgs[i];
if (targetArg >= 0) {
// regular arg
String fieldName = compiler.m_fieldNames[targetArg];
cv.visitVarInsn(ALOAD, 0);
Type type = compiler.m_argumentTypes[targetArg];
argStackIndex = AsmHelper.loadType(cv, argStackIndex, type);
cv.visitFieldInsn(PUTFIELD, compiler.m_joinPointClassName, fieldName, type.getDescriptor());
} else if (targetArg == AdviceInfo.TARGET_ARG) {
cv.visitVarInsn(ALOAD, 0);
argStackIndex = AsmHelper.loadType(
cv, argStackIndex, Type.getType(compiler.m_calleeClassSignature)
);
cv.visitFieldInsn(
PUTFIELD,
compiler.m_joinPointClassName,
CALLEE_INSTANCE_FIELD_NAME,
compiler.m_calleeClassSignature
);
} else if (targetArg == AdviceInfo.THIS_ARG) {
cv.visitVarInsn(ALOAD, 0);
argStackIndex = AsmHelper.loadType(
cv, argStackIndex, Type.getType(compiler.m_callerClassSignature)
);
cv.visitFieldInsn(
PUTFIELD,
compiler.m_joinPointClassName,
CALLER_INSTANCE_FIELD_NAME,
compiler.m_callerClassSignature
);
} else {
;//skip it
}
}
// call proceed()
// and handles unwrapping for returning primitive
Type returnType = Type.getType(customProceedStruct.customProceed.getReturnType().getSignature());
if (AsmHelper.isPrimitive(returnType)) {
cv.visitVarInsn(ALOAD, 0);
cv.visitMethodInsn(
INVOKESPECIAL,
compiler.m_joinPointClassName,
PROCEED_METHOD_NAME,
PROCEED_METHOD_SIGNATURE
);
AsmHelper.unwrapType(cv, returnType);
} else {
cv.visitVarInsn(ALOAD, 0);
cv.visitMethodInsn(
INVOKESPECIAL,
compiler.m_joinPointClassName,
PROCEED_METHOD_NAME,
PROCEED_METHOD_SIGNATURE
);
if (!returnType.getClassName().equals(OBJECT_CLASS_SIGNATURE)) {
cv.visitTypeInsn(CHECKCAST, returnType.getInternalName());
}
}
AsmHelper.addReturnStatement(cv, returnType);
cv.visitMaxs(0, 0);
}
}
//---------- Model specific methods
/**
* Collects the custom proceed methods used in the advice specified.
*
* @param model
* @param advices
*/
private void collectCustomProceedMethods(final CompilationInfo.Model model,
final AdviceInfoContainer advices) {
ClassLoader loader = model.getThisClassInfo().getClassLoader();
final AdviceInfo[] beforeAdviceInfos = advices.getBeforeAdviceInfos();
for (int i = 0; i < beforeAdviceInfos.length; i++) {
collectCustomProceedMethods(beforeAdviceInfos[i], loader);
}
final AdviceInfo[] aroundAdviceInfos = advices.getAroundAdviceInfos();
for (int i = 0; i < aroundAdviceInfos.length; i++) {
collectCustomProceedMethods(aroundAdviceInfos[i], loader);
}
final AdviceInfo[] afterFinallyAdviceInfos = advices.getAfterFinallyAdviceInfos();
for (int i = 0; i < afterFinallyAdviceInfos.length; i++) {
collectCustomProceedMethods(afterFinallyAdviceInfos[i], loader);
}
final AdviceInfo[] afterReturningAdviceInfos = advices.getAfterReturningAdviceInfos();
for (int i = 0; i < afterReturningAdviceInfos.length; i++) {
collectCustomProceedMethods(afterReturningAdviceInfos[i], loader);
}
final AdviceInfo[] afterThrowingAdviceInfos = advices.getAfterThrowingAdviceInfos();
for (int i = 0; i < afterThrowingAdviceInfos.length; i++) {
collectCustomProceedMethods(afterThrowingAdviceInfos[i], loader);
}
}
/**
* Collects the custom proceed methods used in the advice specified.
*
* @param adviceInfo
* @param loader
*/
private void collectCustomProceedMethods(final AdviceInfo adviceInfo, final ClassLoader loader) {
final Type[] paramTypes = adviceInfo.getMethodParameterTypes();
if (paramTypes.length != 0) {
Type firstParam = paramTypes[0];
//TODO should we support JP at other positions or lock the other advice models then so that JP..
// ..is not there or first only ?
// check if first param is an object but not a JP or SJP
if (firstParam.getSort() == Type.OBJECT &&
!firstParam.getClassName().equals(JOIN_POINT_JAVA_CLASS_NAME) &&
!firstParam.getClassName().equals(STATIC_JOIN_POINT_JAVA_CLASS_NAME)) {
ClassInfo classInfo = AsmClassInfo.getClassInfo(firstParam.getClassName(), loader);
if (ClassInfoHelper.implementsInterface(classInfo, JOIN_POINT_JAVA_CLASS_NAME) ||
ClassInfoHelper.implementsInterface(classInfo, STATIC_JOIN_POINT_JAVA_CLASS_NAME)) {
// we have ourselves a custom joinpoint
MethodInfo[] methods = classInfo.getMethods();
for (int j = 0; j < methods.length; j++) {
MethodInfo method = methods[j];
if (method.getName().equals(PROCEED_METHOD_NAME)) {
// we inherit the binding from the advice that actually use us
// for now the first advice sets the rule
// it is up to the user to ensure consistency if the custom proceed
// is used more than once in different advices.
m_customProceedMethodStructs.add(
new CustomProceedMethodStruct(
method,
adviceInfo.getMethodToArgIndexes()
)
);
}
}
}
}
}
}
private static class CustomProceedMethodStruct {
MethodInfo customProceed;
int[] adviceToTargetArgs;
public CustomProceedMethodStruct(MethodInfo customProceed, int[] adviceToTargetArgs) {
this.customProceed = customProceed;
this.adviceToTargetArgs = adviceToTargetArgs;
}
}
public static void defaultCreateBeforeOrAfterAdviceArgumentHandling(MethodVisitor cv,
CompilerInput input,
Type[] joinPointArgumentTypes,
AdviceMethodInfo adviceMethodInfo,
int specialArgIndex) {
int[] argIndexes = adviceMethodInfo.getAdviceMethodArgIndexes();
// if empty, we consider for now that we have to push JoinPoint for old advice with JoinPoint as sole arg
for (int j = 0; j < argIndexes.length; j++) {
int argIndex = argIndexes[j];
if (argIndex >= 0) {
Type argumentType = joinPointArgumentTypes[argIndex];
int argStackIndex = AsmHelper.getRegisterIndexOf(joinPointArgumentTypes, argIndex) + input.argStartIndex;
AsmHelper.loadType(cv, argStackIndex, argumentType);
} else if (argIndex == AdviceInfo.JOINPOINT_ARG || argIndex == AdviceInfo.STATIC_JOINPOINT_ARG) {
AbstractJoinPointCompiler.loadJoinPointInstance(cv, input);
} else if (argIndex == AdviceInfo.TARGET_ARG) {
AbstractJoinPointCompiler.loadCallee(cv, input);
// add a cast if runtime check was used
if (adviceMethodInfo.getAdviceInfo().hasTargetWithRuntimeCheck()) {
cv.visitTypeInsn(
CHECKCAST,
adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j].getInternalName()
);
}
} else if (argIndex == AdviceInfo.THIS_ARG) {
AbstractJoinPointCompiler.loadCaller(cv, input);
} else if (argIndex == AdviceInfo.SPECIAL_ARGUMENT && specialArgIndex != INDEX_NOTAVAILABLE) {
Type argumentType = adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j];
AsmHelper.loadType(cv, specialArgIndex, argumentType);
if (AdviceType.AFTER_THROWING.equals(adviceMethodInfo.getAdviceInfo().getAdviceDefinition().getType())
|| AdviceType.AFTER_RETURNING.equals(adviceMethodInfo.getAdviceInfo().getAdviceDefinition().getType())) {
cv.visitTypeInsn(CHECKCAST, argumentType.getInternalName());
}
} else {
throw new Error("magic index is not supported: " + argIndex);
}
}
}
public static void defaultCreateAroundAdviceArgumentHandling(MethodVisitor cv,
CompilerInput input,
Type[] joinPointArgumentTypes,
AdviceMethodInfo adviceMethodInfo) {
int[] argIndexes = adviceMethodInfo.getAdviceMethodArgIndexes();
for (int j = 0; j < argIndexes.length; j++) {
int argIndex = argIndexes[j];
if (argIndex >= 0) {
Type argumentType = joinPointArgumentTypes[argIndex];
cv.visitVarInsn(ALOAD, 0);
cv.visitFieldInsn(
GETFIELD,
input.joinPointClassName,
ARGUMENT_FIELD + argIndex,
argumentType.getDescriptor()
);
} else if (argIndex == AdviceInfo.JOINPOINT_ARG ||
argIndex == AdviceInfo.STATIC_JOINPOINT_ARG ||
argIndex == AdviceInfo.VALID_NON_AW_AROUND_CLOSURE_TYPE ||
argIndex == AdviceInfo.CUSTOM_JOIN_POINT_ARG) {
cv.visitVarInsn(ALOAD, 0);
} else if (argIndex == AdviceInfo.TARGET_ARG) {
AbstractJoinPointCompiler.loadCallee(cv, input);
// add a cast if runtime check was used
if (adviceMethodInfo.getAdviceInfo().hasTargetWithRuntimeCheck()) {
cv.visitTypeInsn(
CHECKCAST,
adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j].getInternalName()
);
}
} else if (argIndex == AdviceInfo.THIS_ARG) {
AbstractJoinPointCompiler.loadCaller(cv, input);
} else {
throw new Error("advice method argument index type is not supported: " + argIndex);
}
}
}
}