0001: /**************************************************************************************
0002: * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
0003: * http://aspectwerkz.codehaus.org *
0004: * ---------------------------------------------------------------------------------- *
0005: * The software in this package is published under the terms of the LGPL license *
0006: * a copy of which has been included with this distribution in the license.txt file. *
0007: **************************************************************************************/package org.codehaus.aspectwerkz.transform.inlining.compiler;
0008:
0009: import org.objectweb.asm.ClassWriter;
0010: import org.objectweb.asm.CodeVisitor;
0011: import org.objectweb.asm.Constants;
0012: import org.objectweb.asm.Label;
0013: import org.objectweb.asm.Type;
0014:
0015: import org.codehaus.aspectwerkz.DeploymentModel;
0016: import org.codehaus.aspectwerkz.cflow.CflowCompiler;
0017: import org.codehaus.aspectwerkz.reflect.ClassInfo;
0018: import org.codehaus.aspectwerkz.reflect.ClassInfoHelper;
0019: import org.codehaus.aspectwerkz.reflect.MethodInfo;
0020: import org.codehaus.aspectwerkz.reflect.ReflectionInfo;
0021: import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo;
0022: import org.codehaus.aspectwerkz.aspect.AdviceInfo;
0023: import org.codehaus.aspectwerkz.exception.DefinitionException;
0024: import org.codehaus.aspectwerkz.aspect.AdviceType;
0025: import org.codehaus.aspectwerkz.definition.AspectDefinition;
0026: import org.codehaus.aspectwerkz.transform.Compiler;
0027: import org.codehaus.aspectwerkz.transform.TransformationConstants;
0028: import org.codehaus.aspectwerkz.transform.inlining.EmittedJoinPoint;
0029: import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
0030: import org.codehaus.aspectwerkz.transform.inlining.AdviceMethodInfo;
0031: import org.codehaus.aspectwerkz.transform.inlining.AspectInfo;
0032: import org.codehaus.aspectwerkz.transform.inlining.AspectModelManager;
0033: import org.codehaus.aspectwerkz.transform.inlining.spi.AspectModel;
0034: import org.codehaus.aspectwerkz.joinpoint.management.JoinPointType;
0035: import org.codehaus.aspectwerkz.joinpoint.management.AdviceInfoContainer;
0036:
0037: import java.lang.reflect.InvocationTargetException;
0038: import java.lang.reflect.Modifier;
0039: import java.util.Iterator;
0040: import java.util.ArrayList;
0041: import java.util.List;
0042: import java.util.Set;
0043: import java.util.HashSet;
0044: import java.util.HashMap;
0045: import java.util.Map;
0046:
0047: /**
0048: * Abstract base class for the different join point compiler implementations.
0049: * <p/>
0050: * Compiles/generates a class that represents a specific join point, a class which invokes the advices
0051: * and the target join point statically.
0052: * <p/>
0053: * FIXME: depending on hotswap needs, remove the implements StaticJP or JP decision
0054: * FIXME: remove isOptimizedJP and put it global
0055: *
0056: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
0057: * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur </a>
0058: * @author <a href="mailto:the_mindstorm@evolva.ro">Alex Popescu</a>
0059: */
0060: public abstract class AbstractJoinPointCompiler implements Compiler,
0061: TransformationConstants {
0062:
0063: protected static final String TARGET_CLASS_FIELD_NAME = "TARGET_CLASS";
0064: protected static final String THIS_CLASS_FIELD_NAME = "THIS_CLASS";
0065:
0066: // FIXME define these two using VM option - if dump dir specified then dump
0067: public static final boolean DUMP_JIT_CLASSES = false;
0068: protected static final String DUMP_DIR = "_dump";
0069:
0070: protected final String m_callerClassName;
0071: protected final String m_calleeClassName;
0072: protected final String m_callerClassSignature;
0073: protected final String m_calleeClassSignature;
0074: protected final String m_joinPointClassName;
0075: protected final int m_joinPointType;
0076: protected final int m_joinPointHash;
0077: protected final String m_callerMethodName;
0078: protected final String m_callerMethodDesc;
0079: protected final int m_callerMethodModifiers;
0080: protected final String m_calleeMemberName;
0081: protected final String m_calleeMemberDesc;
0082: protected final int m_calleeMemberModifiers;
0083:
0084: protected ClassWriter m_cw;
0085: protected AspectInfo[] m_aspectInfos;
0086: protected AspectModel[] m_aspectModels;
0087: protected AdviceMethodInfo[] m_aroundAdviceMethodInfos;
0088: protected AdviceMethodInfo[] m_beforeAdviceMethodInfos;
0089: protected AdviceMethodInfo[] m_afterFinallyAdviceMethodInfos;
0090: protected AdviceMethodInfo[] m_afterReturningAdviceMethodInfos;
0091: protected AdviceMethodInfo[] m_afterThrowingAdviceMethodInfos;
0092: protected final List m_customProceedMethodStructs = new ArrayList();
0093:
0094: protected boolean m_hasAroundAdvices = false;
0095: protected boolean m_requiresThisOrTarget = false;
0096: protected boolean m_requiresJoinPoint = false;
0097:
0098: protected String[] m_fieldNames;
0099: protected Type[] m_argumentTypes;
0100: protected Type m_returnType;
0101: protected boolean m_isThisAdvisable = false;
0102:
0103: /**
0104: * Creates a new join point compiler instance.
0105: *
0106: * @param model the compilation model
0107: */
0108: public AbstractJoinPointCompiler(final CompilationInfo.Model model) {
0109: m_joinPointClassName = model.getJoinPointClassName();
0110:
0111: final EmittedJoinPoint emittedJoinPoint = model
0112: .getEmittedJoinPoint();
0113:
0114: m_joinPointHash = emittedJoinPoint.getJoinPointHash();
0115: m_joinPointType = emittedJoinPoint.getJoinPointType();
0116:
0117: m_callerMethodName = emittedJoinPoint.getCallerMethodName();
0118: m_callerMethodDesc = emittedJoinPoint.getCallerMethodDesc();
0119: m_callerMethodModifiers = emittedJoinPoint
0120: .getCallerMethodModifiers();
0121:
0122: m_calleeMemberName = emittedJoinPoint.getCalleeMemberName();
0123: m_calleeMemberDesc = emittedJoinPoint.getCalleeMemberDesc();
0124: m_calleeMemberModifiers = emittedJoinPoint
0125: .getCalleeMemberModifiers();
0126:
0127: // NOTE: internal compiler class name format is ALWAYS using '/'
0128: m_callerClassName = emittedJoinPoint.getCallerClassName()
0129: .replace('.', '/');
0130: m_calleeClassName = emittedJoinPoint.getCalleeClassName()
0131: .replace('.', '/');
0132: m_callerClassSignature = L
0133: + emittedJoinPoint.getCallerClassName().replace('.',
0134: '/') + SEMICOLON;
0135: m_calleeClassSignature = L
0136: + emittedJoinPoint.getCalleeClassName().replace('.',
0137: '/') + SEMICOLON;
0138:
0139: m_argumentTypes = getJoinPointArgumentTypes();
0140: m_returnType = getJoinPointReturnType();
0141:
0142: initialize(model);
0143: }
0144:
0145: /**
0146: * Initializes the the join point compiler.
0147: *
0148: * @param model the compilation model
0149: */
0150: private synchronized void initialize(
0151: final CompilationInfo.Model model) {
0152: // check if 'target' is Advisable, e.g. can handle runtime per instance deployment
0153: checkIfThisIsAdvisable(model);
0154:
0155: // create the aspect fields
0156: final AdviceInfoContainer advices = model
0157: .getAdviceInfoContainer();
0158:
0159: collectAdviceInfo(advices);
0160: collectCustomProceedMethods(model, advices);
0161:
0162: // compute the optimization we can use
0163: m_hasAroundAdvices = m_aroundAdviceMethodInfos.length > 0;
0164: m_requiresThisOrTarget = requiresThisOrTarget();
0165: m_requiresJoinPoint = requiresJoinPoint();
0166:
0167: // setup models at the end so that they can override m_requiresJoinPoint
0168: setupReferencedAspectModels();
0169:
0170: m_cw = AsmHelper.newClassWriter(true);
0171: }
0172:
0173: /**
0174: * Collects the advice info.
0175: *
0176: * @param advices
0177: */
0178: private void collectAdviceInfo(final AdviceInfoContainer advices) {
0179: final List aspectQualifiedNames = new ArrayList();// in fact a Set but we need indexOf
0180: final Set aspectInfos = new HashSet();
0181: m_beforeAdviceMethodInfos = getAdviceMethodInfos(
0182: aspectQualifiedNames, aspectInfos, advices
0183: .getBeforeAdviceInfos());
0184: m_aroundAdviceMethodInfos = getAdviceMethodInfos(
0185: aspectQualifiedNames, aspectInfos, advices
0186: .getAroundAdviceInfos());
0187: m_afterReturningAdviceMethodInfos = getAdviceMethodInfos(
0188: aspectQualifiedNames, aspectInfos, advices
0189: .getAfterReturningAdviceInfos());
0190: m_afterFinallyAdviceMethodInfos = getAdviceMethodInfos(
0191: aspectQualifiedNames, aspectInfos, advices
0192: .getAfterFinallyAdviceInfos());
0193: m_afterThrowingAdviceMethodInfos = getAdviceMethodInfos(
0194: aspectQualifiedNames, aspectInfos, advices
0195: .getAfterThrowingAdviceInfos());
0196:
0197: m_aspectInfos = (AspectInfo[]) aspectInfos
0198: .toArray(new AspectInfo[aspectInfos.size()]);
0199: }
0200:
0201: /**
0202: * Collects the custom proceed methods used in the advice specified.
0203: *
0204: * @param model
0205: * @param advices
0206: */
0207: private void collectCustomProceedMethods(
0208: final CompilationInfo.Model model,
0209: final AdviceInfoContainer advices) {
0210: ClassLoader loader = model.getThisClassInfo().getClassLoader();
0211: final AdviceInfo[] beforeAdviceInfos = advices
0212: .getBeforeAdviceInfos();
0213: for (int i = 0; i < beforeAdviceInfos.length; i++) {
0214: collectCustomProceedMethods(beforeAdviceInfos[i], loader);
0215: }
0216: final AdviceInfo[] aroundAdviceInfos = advices
0217: .getAroundAdviceInfos();
0218: for (int i = 0; i < aroundAdviceInfos.length; i++) {
0219: collectCustomProceedMethods(aroundAdviceInfos[i], loader);
0220: }
0221: final AdviceInfo[] afterFinallyAdviceInfos = advices
0222: .getAfterFinallyAdviceInfos();
0223: for (int i = 0; i < afterFinallyAdviceInfos.length; i++) {
0224: collectCustomProceedMethods(afterFinallyAdviceInfos[i],
0225: loader);
0226: }
0227: final AdviceInfo[] afterReturningAdviceInfos = advices
0228: .getAfterReturningAdviceInfos();
0229: for (int i = 0; i < afterReturningAdviceInfos.length; i++) {
0230: collectCustomProceedMethods(afterReturningAdviceInfos[i],
0231: loader);
0232: }
0233: final AdviceInfo[] afterThrowingAdviceInfos = advices
0234: .getAfterThrowingAdviceInfos();
0235: for (int i = 0; i < afterThrowingAdviceInfos.length; i++) {
0236: collectCustomProceedMethods(afterThrowingAdviceInfos[i],
0237: loader);
0238: }
0239: }
0240:
0241: /**
0242: * Collects the custom proceed methods used in the advice specified.
0243: *
0244: * @param adviceInfo
0245: * @param loader
0246: */
0247: private void collectCustomProceedMethods(
0248: final AdviceInfo adviceInfo, final ClassLoader loader) {
0249: final Type[] paramTypes = adviceInfo.getMethodParameterTypes();
0250: if (paramTypes.length != 0) {
0251: Type firstParam = paramTypes[0];
0252: //TODO should we support JP at other positions or lock the other advice models then so that JP..
0253: // ..is not there or first only ?
0254: // check if first param is an object but not a JP or SJP
0255: if (firstParam.getSort() == Type.OBJECT
0256: && !firstParam.getClassName().equals(
0257: JOIN_POINT_JAVA_CLASS_NAME)
0258: && !firstParam.getClassName().equals(
0259: STATIC_JOIN_POINT_JAVA_CLASS_NAME)) {
0260: ClassInfo classInfo = AsmClassInfo.getClassInfo(
0261: firstParam.getClassName(), loader);
0262: if (ClassInfoHelper.implements Interface(classInfo,
0263: JOIN_POINT_JAVA_CLASS_NAME)
0264: || ClassInfoHelper.implements Interface(
0265: classInfo,
0266: STATIC_JOIN_POINT_JAVA_CLASS_NAME)) {
0267: // we have ourselves a custom joinpoint
0268: MethodInfo[] methods = classInfo.getMethods();
0269: for (int j = 0; j < methods.length; j++) {
0270: MethodInfo method = methods[j];
0271: if (method.getName()
0272: .equals(PROCEED_METHOD_NAME)) {
0273: // we inherit the binding from the advice that actually use us
0274: // for now the first advice sets the rule
0275: // it is up to the user to ensure consistency if the custom proceed
0276: // is used more than once in different advices.
0277: m_customProceedMethodStructs
0278: .add(new CustomProceedMethodStruct(
0279: method,
0280: adviceInfo
0281: .getMethodToArgIndexes()));
0282: }
0283: }
0284: }
0285: }
0286: }
0287: }
0288:
0289: /**
0290: * Checks if the this class implements the Advisable interface.
0291: *
0292: * @param model
0293: */
0294: private void checkIfThisIsAdvisable(
0295: final CompilationInfo.Model model) {
0296: if (!Modifier.isStatic(m_callerMethodModifiers)) {
0297: ClassInfo[] interfaces = model.getThisClassInfo()
0298: .getInterfaces();
0299: for (int i = 0; i < interfaces.length; i++) {
0300: if (interfaces[i].getName().equals(
0301: ADVISABLE_CLASS_JAVA_NAME)) {
0302: m_isThisAdvisable = true;
0303: break;
0304: }
0305: }
0306: }
0307: }
0308:
0309: /**
0310: * Retrives and sets the aspect models that are referenced in this compilation phase.
0311: */
0312: private void setupReferencedAspectModels() {
0313: Map aspectModelMap = new HashMap();
0314: for (int i = 0; i < m_aspectInfos.length; i++) {
0315: AspectDefinition aspectDef = m_aspectInfos[i]
0316: .getAspectDefinition();
0317: if (aspectDef.isAspectWerkzAspect()) {
0318: continue; // AW Aspect Model not managed by AspectModelManager
0319: }
0320: String type = aspectDef.getAspectModel();
0321: AspectModel aspectModel = AspectModelManager
0322: .getModelFor(type);
0323: aspectModelMap.put(type, aspectModel);
0324: if (aspectModel.requiresReflectiveInfo()) {
0325: m_requiresJoinPoint = true; // if at least one model requries RTTI then build it
0326: }
0327: }
0328: m_aspectModels = (AspectModel[]) aspectModelMap.values()
0329: .toArray(new AspectModel[aspectModelMap.size()]);
0330: }
0331:
0332: /**
0333: * Returns the join point interface class name.
0334: *
0335: * @return
0336: */
0337: private String getJoinPointInterface() {
0338: String joinPointInterface;
0339: if (requiresProceedMethod() || m_requiresJoinPoint) {
0340: joinPointInterface = JOIN_POINT_CLASS_NAME;
0341: } else {
0342: joinPointInterface = STATIC_JOIN_POINT_CLASS_NAME;
0343: }
0344: return joinPointInterface;
0345: }
0346:
0347: /**
0348: * Retrieves the advice method infos.
0349: *
0350: * @param aspectQualifiedNames
0351: * @param aspectInfos
0352: * @param adviceInfos
0353: * @return
0354: */
0355: protected AdviceMethodInfo[] getAdviceMethodInfos(
0356: final List aspectQualifiedNames, final Set aspectInfos,
0357: final AdviceInfo[] adviceInfos) {
0358: List adviceMethodInfosSet = new ArrayList();
0359: for (int i = 0; i < adviceInfos.length; i++) {
0360: AdviceInfo adviceInfo = adviceInfos[i];
0361:
0362: // if we have a perinstance deployed aspect and a static member CALLER -> skip and go on
0363: DeploymentModel deploymentModel = adviceInfo
0364: .getAdviceDefinition().getAspectDefinition()
0365: .getDeploymentModel();
0366: if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)
0367: && Modifier.isStatic(m_callerMethodModifiers)) {
0368: continue;
0369: }
0370:
0371: final String aspectClassName = adviceInfo
0372: .getAspectClassName().replace('.', '/');
0373:
0374: if (!aspectQualifiedNames.contains(adviceInfo
0375: .getAspectQualifiedName())) {
0376: aspectQualifiedNames.add(adviceInfo
0377: .getAspectQualifiedName());
0378: }
0379: int aspectIndex = aspectQualifiedNames.indexOf(adviceInfo
0380: .getAspectQualifiedName());
0381: AdviceMethodInfo adviceMethodInfo = new AdviceMethodInfo(
0382: adviceInfo, ASPECT_FIELD_PREFIX + aspectIndex,
0383: aspectClassName, L + aspectClassName + SEMICOLON,
0384: m_callerClassSignature, m_calleeClassSignature,
0385: m_joinPointClassName, m_calleeMemberDesc);
0386: adviceMethodInfosSet.add(adviceMethodInfo);
0387: aspectInfos.add(adviceMethodInfo.getAspectInfo());
0388: }
0389: return (AdviceMethodInfo[]) adviceMethodInfosSet
0390: .toArray(new AdviceMethodInfo[adviceMethodInfosSet
0391: .size()]);
0392: }
0393:
0394: /**
0395: * Creates join point specific fields.
0396: */
0397: protected abstract void createJoinPointSpecificFields();
0398:
0399: /**
0400: * Creates the signature for the join point.
0401: *
0402: * @param cv
0403: */
0404: protected abstract void createSignature(final CodeVisitor cv);
0405:
0406: /**
0407: * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
0408: * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
0409: * exists.
0410: *
0411: * @param cv
0412: * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or not)
0413: */
0414: protected abstract void createInlinedJoinPointInvocation(
0415: final CodeVisitor cv, final boolean isOptimizedJoinPoint,
0416: final int argStartIndex, final int joinPointIndex);
0417:
0418: /**
0419: * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
0420: * local join point instance.
0421: *
0422: * @param cv
0423: */
0424: protected abstract void createJoinPointInvocation(
0425: final CodeVisitor cv);
0426:
0427: /**
0428: * Returns the join points return type.
0429: *
0430: * @return
0431: */
0432: protected abstract Type getJoinPointReturnType();
0433:
0434: /**
0435: * Returns the join points argument type(s).
0436: *
0437: * @return
0438: */
0439: protected abstract Type[] getJoinPointArgumentTypes();
0440:
0441: /**
0442: * Creates the getRtti method
0443: */
0444: protected abstract void createGetRttiMethod();
0445:
0446: /**
0447: * Creates the getSignature method
0448: */
0449: protected abstract void createGetSignatureMethod();
0450:
0451: /**
0452: * Compiles a join point class, one specific class for each distinct join point. The compiled join point class
0453: * inherits the base join point class.
0454: *
0455: * @return the generated, compiled and loaded join point class
0456: */
0457: public byte[] compile() {
0458: try {
0459: // TODO: INNER CLASS OR NOT?
0460: // flag it as a public static inner class
0461: // Note: if <init> changes, we will need to pass the containing instance as arg0 and add a syntetic field
0462: // int innerIndex = m_joinPointClassName.lastIndexOf('$');
0463: // m_cw.visitInnerClass(m_joinPointClassName,
0464: // m_joinPointClassName.substring(0, innerIndex),
0465: // m_joinPointClassName.substring(innerIndex + 1, m_joinPointClassName.length()),
0466: // ACC_PUBLIC + ACC_STATIC);
0467:
0468: createClassHeader();
0469: createMandatoryMethodInAspectModels();
0470: createFieldsCommonToAllJoinPoints();
0471: createJoinPointSpecificFields();
0472: createStaticInitializer();
0473: createClinit();
0474: createInit();
0475: createUtilityMethods();
0476: createCopyMethod();
0477: createGetSignatureMethod();
0478: createInvokeMethod();
0479: if (requiresProceedMethod()) {
0480: createProceedMethod();
0481: }
0482: if (m_requiresJoinPoint) {
0483: createGetRttiMethod();
0484: }
0485: createCustomProceedMethods();
0486: m_cw.visitEnd();
0487:
0488: if (DUMP_JIT_CLASSES) {
0489: AsmHelper.dumpClass(DUMP_DIR, m_joinPointClassName,
0490: m_cw);
0491: }
0492: return m_cw.toByteArray();
0493:
0494: } catch (Exception e) {
0495: e.printStackTrace();
0496: StringBuffer buf = new StringBuffer();
0497: buf
0498: .append("could not compile join point instance for join point with hash [");
0499: buf.append(m_joinPointHash);
0500: buf.append("] and declaring class [");
0501: buf.append(m_callerClassName);
0502: buf.append("] due to: ");
0503: if (e instanceof InvocationTargetException) {
0504: buf.append(((InvocationTargetException) e)
0505: .getTargetException().toString());
0506: } else {
0507: buf.append(e.toString());
0508: }
0509: throw new RuntimeException(buf.toString());
0510: }
0511: }
0512:
0513: /**
0514: * Creates join point specific fields.
0515: */
0516: protected void createFieldsCommonToAllJoinPoints() {
0517: if (m_returnType.getSort() != Type.VOID) {
0518: m_cw.visitField(ACC_PRIVATE, RETURN_VALUE_FIELD_NAME,
0519: m_returnType.getDescriptor(), null, null);
0520: }
0521: m_cw.visitField(ACC_PRIVATE + ACC_STATIC,
0522: TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE, null,
0523: null);
0524:
0525: m_cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_FINAL,
0526: THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE, null,
0527: null);
0528:
0529: m_cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_FINAL,
0530: ENCLOSING_SJP_FIELD_NAME,
0531: ENCLOSING_SJP_FIELD_CLASS_SIGNATURE, null, null);
0532:
0533: m_cw.visitField(ACC_PRIVATE + ACC_STATIC, META_DATA_FIELD_NAME,
0534: MAP_CLASS_SIGNATURE, null, null);
0535: m_cw.visitField(ACC_PRIVATE + ACC_STATIC,
0536: OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME, L
0537: + m_joinPointClassName + SEMICOLON, null, null);
0538: m_cw.visitField(ACC_PRIVATE, CALLEE_INSTANCE_FIELD_NAME,
0539: m_calleeClassSignature, null, null);
0540: m_cw.visitField(ACC_PRIVATE, CALLER_INSTANCE_FIELD_NAME,
0541: m_callerClassSignature, null, null);
0542: m_cw.visitField(ACC_PRIVATE, STACK_FRAME_COUNTER_FIELD_NAME, I,
0543: null, null);
0544:
0545: if (m_isThisAdvisable) {
0546: m_cw.visitField(ACC_PRIVATE, INTERCEPTOR_INDEX_FIELD_NAME,
0547: I, null, null);
0548:
0549: m_cw.visitField(ACC_PRIVATE,
0550: AROUND_INTERCEPTORS_FIELD_NAME,
0551: AROUND_ADVICE_ARRAY_CLASS_SIGNATURE, null, null);
0552: m_cw
0553: .visitField(ACC_PRIVATE,
0554: NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I,
0555: null, null);
0556:
0557: m_cw.visitField(ACC_PRIVATE,
0558: BEFORE_INTERCEPTORS_FIELD_NAME,
0559: BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE, null, null);
0560: m_cw
0561: .visitField(ACC_PRIVATE,
0562: NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I,
0563: null, null);
0564:
0565: m_cw.visitField(ACC_PRIVATE, AFTER_INTERCEPTORS_FIELD_NAME,
0566: AFTER_ADVICE_ARRAY_CLASS_SIGNATURE, null, null);
0567: m_cw.visitField(ACC_PRIVATE,
0568: NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I, null, null);
0569:
0570: m_cw.visitField(ACC_PRIVATE,
0571: AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
0572: AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE, null,
0573: null);
0574: m_cw.visitField(ACC_PRIVATE,
0575: NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I,
0576: null, null);
0577:
0578: m_cw.visitField(ACC_PRIVATE,
0579: AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
0580: AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE, null,
0581: null);
0582: m_cw.visitField(ACC_PRIVATE,
0583: NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I,
0584: null, null);
0585: }
0586: }
0587:
0588: /**
0589: * Creates the clinit method for the join point.
0590: */
0591: protected void createClinit() {
0592: CodeVisitor cv = m_cw.visitMethod(ACC_STATIC,
0593: CLINIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE,
0594: null, null);
0595: cv.visitMethodInsn(INVOKESTATIC, m_joinPointClassName,
0596: STATIC_INITIALIZATION_METHOD_NAME,
0597: NO_PARAM_RETURN_VOID_SIGNATURE);
0598: cv.visitInsn(RETURN);
0599: cv.visitMaxs(0, 0);
0600: }
0601:
0602: /**
0603: * Creates the init method for the join point.
0604: */
0605: protected void createInit() {
0606: CodeVisitor cv = m_cw.visitMethod(ACC_PRIVATE,
0607: INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE, null,
0608: null);
0609: cv.visitVarInsn(ALOAD, 0);
0610:
0611: boolean hasAroundClosureBaseClass = false;
0612: AspectModel aspectModel = null;
0613:
0614: for (int i = 0; i < m_aspectModels.length; i++) {
0615: aspectModel = m_aspectModels[i];
0616: if (aspectModel.getAroundClosureClassInfo()
0617: .getSuperClassName() != null) {
0618: hasAroundClosureBaseClass = true;
0619: break;
0620: }
0621: }
0622:
0623: if (hasAroundClosureBaseClass) {
0624: // invoke the super class constructor
0625: aspectModel.createInvocationOfAroundClosureSuperClass(cv);
0626: } else {
0627: // invoke the constructor of java.lang.Object
0628: cv.visitMethodInsn(INVOKESPECIAL, OBJECT_CLASS_NAME,
0629: INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
0630: }
0631:
0632: resetStackFrameCounter(cv);
0633:
0634: cv.visitInsn(RETURN);
0635: cv.visitMaxs(0, 0);
0636: }
0637:
0638: /**
0639: * Creates the class header for the join point.
0640: */
0641: private void createClassHeader() {
0642:
0643: Set interfaces = new HashSet();
0644: String baseClass = OBJECT_CLASS_NAME;
0645:
0646: // get the different aspect models required interfaces
0647: for (int i = 0; i < m_aspectModels.length; i++) {
0648: AspectModel aspectModel = m_aspectModels[i];
0649: AspectModel.AroundClosureClassInfo closureClassInfo = aspectModel
0650: .getAroundClosureClassInfo();
0651: final String super ClassName = closureClassInfo
0652: .getSuperClassName();
0653: final String[] interfaceNames = closureClassInfo
0654: .getInterfaceNames();
0655: if (super ClassName != null) {
0656: if (!baseClass.equals(OBJECT_CLASS_NAME)) {
0657: throw new RuntimeException(
0658: "compiled join point can only subclass one around closure base class but more than registered aspect model requires a closure base class");
0659: }
0660: baseClass = super ClassName;
0661: }
0662: if (interfaceNames.length != 0) {
0663: for (int j = 0; j < interfaceNames.length; j++) {
0664: interfaces.add(interfaceNames[j]);
0665: }
0666: }
0667: }
0668:
0669: // get the custom join point interfaces
0670: for (Iterator it = m_customProceedMethodStructs.iterator(); it
0671: .hasNext();) {
0672: MethodInfo methodInfo = ((CustomProceedMethodStruct) it
0673: .next()).customProceed;
0674: interfaces.add(methodInfo.getDeclaringType().getName()
0675: .replace('.', '/'));
0676: }
0677:
0678: int i = 1;
0679: String[] interfaceArr = new String[interfaces.size() + 1];
0680: interfaceArr[0] = getJoinPointInterface();
0681: for (Iterator it = interfaces.iterator(); it.hasNext(); i++) {
0682: interfaceArr[i] = (String) it.next();
0683: }
0684:
0685: m_cw.visit(AsmHelper.JAVA_VERSION, ACC_PUBLIC + ACC_SUPER,
0686: m_joinPointClassName, baseClass, interfaceArr, null);
0687: }
0688:
0689: /**
0690: * Creates the methods that are mandatory methods in the around closure in the different aspect models.
0691: */
0692: private void createMandatoryMethodInAspectModels() {
0693: for (int i = 0; i < m_aspectModels.length; i++) {
0694: m_aspectModels[i].createMandatoryMethods(m_cw,
0695: m_joinPointClassName);
0696: }
0697: }
0698:
0699: /**
0700: * Creates the custom proceed methods.
0701: */
0702: private void createCustomProceedMethods() {
0703: Set addedMethodSignatures = new HashSet();
0704: for (Iterator it = m_customProceedMethodStructs.iterator(); it
0705: .hasNext();) {
0706: CustomProceedMethodStruct customProceedStruct = (CustomProceedMethodStruct) it
0707: .next();
0708: MethodInfo methodInfo = customProceedStruct.customProceed;
0709: final String desc = methodInfo.getSignature();
0710:
0711: if (addedMethodSignatures.contains(desc)) {
0712: continue;
0713: }
0714: addedMethodSignatures.add(desc);
0715:
0716: CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC | ACC_FINAL,
0717: PROCEED_METHOD_NAME, desc,
0718: new String[] { THROWABLE_CLASS_NAME }, null);
0719:
0720: // update the joinpoint instance with the given values
0721: // starts at 1 since first arg is the custom join point by convention
0722: //TODO see JoinPointManage for this custom jp is first convention
0723: int argStackIndex = 1;
0724: for (int i = 1; i < customProceedStruct.adviceToTargetArgs.length; i++) {
0725: int targetArg = customProceedStruct.adviceToTargetArgs[i];
0726: if (targetArg >= 0) {
0727: // regular arg
0728: String fieldName = m_fieldNames[targetArg];
0729: cv.visitVarInsn(ALOAD, 0);
0730: Type type = m_argumentTypes[targetArg];
0731: argStackIndex = AsmHelper.loadType(cv,
0732: argStackIndex, type);
0733: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
0734: fieldName, type.getDescriptor());
0735: } else if (targetArg == AdviceInfo.TARGET_ARG) {
0736: cv.visitVarInsn(ALOAD, 0);
0737: argStackIndex = AsmHelper.loadType(cv,
0738: argStackIndex, Type
0739: .getType(m_calleeClassSignature));
0740: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
0741: CALLEE_INSTANCE_FIELD_NAME,
0742: m_calleeClassSignature);
0743: } else if (targetArg == AdviceInfo.THIS_ARG) {
0744: cv.visitVarInsn(ALOAD, 0);
0745: argStackIndex = AsmHelper.loadType(cv,
0746: argStackIndex, Type
0747: .getType(m_callerClassSignature));
0748: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
0749: CALLER_INSTANCE_FIELD_NAME,
0750: m_callerClassSignature);
0751: } else {
0752: ;//skip it
0753: }
0754: }
0755:
0756: // call proceed()
0757: // and handles unwrapping for returning primitive
0758: Type returnType = Type
0759: .getType(customProceedStruct.customProceed
0760: .getReturnType().getSignature());
0761: if (AsmHelper.isPrimitive(returnType)) {
0762: cv.visitVarInsn(ALOAD, 0);
0763: cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName,
0764: PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
0765: AsmHelper.unwrapType(cv, returnType);
0766: } else {
0767: cv.visitVarInsn(ALOAD, 0);
0768: cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName,
0769: PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
0770: if (!returnType.getClassName().equals(
0771: OBJECT_CLASS_SIGNATURE)) {
0772: cv.visitTypeInsn(CHECKCAST, returnType
0773: .getInternalName());
0774: }
0775: }
0776: AsmHelper.addReturnStatement(cv, returnType);
0777: cv.visitMaxs(0, 0);
0778: }
0779: }
0780:
0781: /**
0782: * Creates the static initialization method (not clinit) for the join point.
0783: */
0784: protected void createStaticInitializer() {
0785: CodeVisitor cv = m_cw.visitMethod(ACC_STATIC | ACC_PUBLIC,
0786: STATIC_INITIALIZATION_METHOD_NAME,
0787: NO_PARAM_RETURN_VOID_SIGNATURE, null, null);
0788:
0789: Label tryLabel = new Label();
0790: cv.visitLabel(tryLabel);
0791: cv.visitLdcInsn(m_calleeClassName.replace('/', '.'));
0792: cv.visitMethodInsn(INVOKESTATIC, CLASS_CLASS,
0793: FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
0794: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
0795: TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
0796:
0797: cv.visitLdcInsn(m_callerClassName.replace('/', '.'));
0798: cv.visitMethodInsn(INVOKESTATIC, CLASS_CLASS,
0799: FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
0800: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
0801: THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
0802:
0803: Label finallyLabel = new Label();
0804: cv.visitLabel(finallyLabel);
0805:
0806: Label gotoFinallyLabel = new Label();
0807: cv.visitJumpInsn(GOTO, gotoFinallyLabel);
0808:
0809: Label catchLabel = new Label();
0810: cv.visitLabel(catchLabel);
0811: cv.visitVarInsn(ASTORE, 0);
0812:
0813: cv.visitVarInsn(ALOAD, 0);
0814: cv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Throwable",
0815: "printStackTrace", "()V");
0816:
0817: cv.visitTypeInsn(NEW, RUNTIME_EXCEPTION_CLASS_NAME);
0818: cv.visitInsn(DUP);
0819: cv
0820: .visitLdcInsn("could not load target class using Class.forName() in generated join point base class "
0821: + m_joinPointClassName);
0822:
0823: cv.visitMethodInsn(INVOKESPECIAL, RUNTIME_EXCEPTION_CLASS_NAME,
0824: INIT_METHOD_NAME,
0825: RUNTIME_EXCEPTION_INIT_METHOD_SIGNATURE);
0826:
0827: cv.visitInsn(ATHROW);
0828: cv.visitLabel(gotoFinallyLabel);
0829:
0830: // create the enclosing static joinpoint
0831: createEnclosingStaticJoinPoint(cv);
0832:
0833: // create the metadata map
0834: cv.visitTypeInsn(NEW, HASH_MAP_CLASS_NAME);
0835: cv.visitInsn(DUP);
0836: cv.visitMethodInsn(INVOKESPECIAL, HASH_MAP_CLASS_NAME,
0837: INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
0838: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
0839: META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
0840:
0841: // create the Signature instance
0842: createSignature(cv);
0843:
0844: // create the static JoinPoint instance
0845: cv.visitTypeInsn(NEW, m_joinPointClassName);
0846: cv.visitInsn(DUP);
0847: cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName,
0848: INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
0849: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
0850: OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME, L
0851: + m_joinPointClassName + SEMICOLON);
0852:
0853: // create and initialize the aspect fields
0854: for (int i = 0; i < m_aspectInfos.length; i++) {
0855: createAndInitializeAspectField(m_aspectInfos[i], cv);
0856: }
0857:
0858: cv.visitInsn(RETURN);
0859: cv.visitTryCatchBlock(tryLabel, finallyLabel, catchLabel,
0860: CLASS_NOT_FOUND_EXCEPTION_CLASS_NAME);
0861: cv.visitMaxs(0, 0);
0862: }
0863:
0864: /**
0865: * Add and initialize the static field for enclosing joint point static part
0866: *
0867: * @param cv
0868: */
0869: protected void createEnclosingStaticJoinPoint(CodeVisitor cv) {
0870: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
0871: THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
0872: cv.visitLdcInsn(m_callerMethodName);
0873: cv.visitLdcInsn(m_callerMethodDesc);
0874:
0875: cv.visitMethodInsn(INVOKESTATIC, SIGNATURE_FACTORY_CLASS,
0876: NEW_ENCLOSING_SJP_METHOD_NAME,
0877: NEW_ENCLOSING_SJP_METHOD_SIGNATURE);
0878: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
0879: ENCLOSING_SJP_FIELD_NAME,
0880: ENCLOSING_SJP_FIELD_CLASS_SIGNATURE);
0881: }
0882:
0883: /**
0884: * Create and initialize the aspect field for a specific aspect (qualified since it depends
0885: * on the param, deployment model, container etc).
0886: *
0887: * @param aspectInfo
0888: * @param cv
0889: */
0890: protected boolean createAndInitializeAspectField(
0891: final AspectInfo aspectInfo, final CodeVisitor cv) {
0892: if (aspectInfo.getAspectDefinition().isAspectWerkzAspect()) {
0893: // AW aspect
0894: // create the field to host the aspect and retrieve the aspect to set it to the field
0895: createAspectReferenceField(m_cw, aspectInfo);
0896: createAspectInstantiation(cv, aspectInfo,
0897: m_joinPointClassName);
0898: } else {
0899: // non-AW aspect
0900: final String type = aspectInfo.getAspectDefinition()
0901: .getAspectModel();
0902: final AspectModel aspectModel = AspectModelManager
0903: .getModelFor(type);
0904: aspectModel.createAspectReferenceField(m_cw, aspectInfo,
0905: m_joinPointClassName);
0906: aspectModel.createAspectInstantiation(cv, aspectInfo,
0907: m_joinPointClassName);
0908: }
0909:
0910: return false;
0911: }
0912:
0913: /**
0914: * Creates aspect reference field (static or non static field).
0915: *
0916: * @param cw
0917: * @param aspectInfo
0918: */
0919: public static void createAspectReferenceField(final ClassWriter cw,
0920: final AspectInfo aspectInfo) {
0921: String aspectClassSignature = aspectInfo
0922: .getAspectClassSignature();
0923:
0924: // create a field depending on the aspect deployment model
0925: DeploymentModel deploymentModel = aspectInfo
0926: .getDeploymentModel();
0927: if (deploymentModel.equals(DeploymentModel.PER_JVM)
0928: || deploymentModel.equals(DeploymentModel.PER_CLASS)) {
0929: // add the aspect static field
0930: cw.visitField(ACC_PRIVATE + ACC_STATIC, aspectInfo
0931: .getAspectFieldName(), aspectClassSignature, null,
0932: null);
0933: } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) {
0934: // add the aspect field as a non static field
0935: //TODO - may bee skip the aspect and all its advice is target is static, or ctor call
0936: //that is no instance available
0937: cw.visitField(ACC_PRIVATE, aspectInfo.getAspectFieldName(),
0938: aspectClassSignature, null, null);
0939: } else {
0940: throw new UnsupportedOperationException(
0941: "unsupported deployment model - "
0942: + aspectInfo.getAspectClassName() + " "
0943: + deploymentModel);
0944: }
0945: }
0946:
0947: /**
0948: * Creates instantiation of aspects using the Aspects.aspectOf() methods which uses the AspectContainer impls.
0949: * We are using the THIS_CLASS classloader since the aspect can be visible from that one only f.e. for get/set/call
0950: *
0951: * @param cv
0952: * @param aspectInfo
0953: * @param joinPointClassName
0954: */
0955: public static void createAspectInstantiation(final CodeVisitor cv,
0956: final AspectInfo aspectInfo, final String joinPointClassName) {
0957: String aspectClassSignature = aspectInfo
0958: .getAspectClassSignature();
0959: String aspectClassName = aspectInfo.getAspectClassName();
0960: // retrieve the aspect set it to the field
0961: DeploymentModel deploymentModel = aspectInfo
0962: .getDeploymentModel();
0963: if (CflowCompiler.isCflowClass(aspectClassName)) {
0964: // handle Cflow native aspectOf
0965: cv.visitMethodInsn(INVOKESTATIC, aspectClassName,
0966: CflowCompiler.CFLOW_ASPECTOF_METHOD_NAME, "()"
0967: + aspectClassSignature);
0968: cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo
0969: .getAspectFieldName(), aspectClassSignature);
0970: } else if (deploymentModel.equals(DeploymentModel.PER_JVM)) {
0971: // AW-355, AW-415 we need a ClassLoader here
0972: cv.visitFieldInsn(GETSTATIC, joinPointClassName,
0973: THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
0974: cv.visitMethodInsn(INVOKEVIRTUAL, CLASS_CLASS,
0975: GETCLASSLOADER_METHOD_NAME,
0976: CLASS_CLASS_GETCLASSLOADER_METHOD_SIGNATURE);
0977: cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
0978: cv.visitLdcInsn(aspectInfo.getAspectDefinition()
0979: .getContainerClassName());
0980: cv.visitMethodInsn(INVOKESTATIC, ASPECTS_CLASS_NAME,
0981: ASPECT_OF_METHOD_NAME,
0982: ASPECT_OF_PER_JVM_METHOD_SIGNATURE);
0983: cv.visitTypeInsn(CHECKCAST, aspectClassName);
0984: cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo
0985: .getAspectFieldName(), aspectClassSignature);
0986: } else if (deploymentModel.equals(DeploymentModel.PER_CLASS)) {
0987: cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
0988: cv.visitLdcInsn(aspectInfo.getAspectDefinition()
0989: .getContainerClassName());
0990: cv.visitFieldInsn(GETSTATIC, joinPointClassName,
0991: THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
0992: cv.visitMethodInsn(INVOKESTATIC, ASPECTS_CLASS_NAME,
0993: ASPECT_OF_METHOD_NAME,
0994: ASPECT_OF_PER_CLASS_METHOD_SIGNATURE);
0995: cv.visitTypeInsn(CHECKCAST, aspectClassName);
0996: cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo
0997: .getAspectFieldName(), aspectClassSignature);
0998: } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) {
0999: } else {
1000: throw new UnsupportedOperationException(
1001: "unsupported deployment model - "
1002: + aspectInfo.getAspectClassName() + " "
1003: + deploymentModel);
1004: }
1005: }
1006:
1007: /**
1008: * Creates the 'invoke' method. If possible delegates to the target join point directly, e.g. does not invoke the
1009: * 'proceed' method (Used when a join point has zero around advice).
1010: */
1011: protected void createInvokeMethod() {
1012:
1013: final String invokeDesc = buildInvokeMethodSignature();
1014:
1015: // create the method
1016: CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC + ACC_FINAL
1017: + ACC_STATIC, INVOKE_METHOD_NAME, invokeDesc,
1018: new String[] { THROWABLE_CLASS_NAME }, null);
1019:
1020: // compute the callee and caller index from the invoke(..) signature
1021: int calleeIndex = INDEX_NOTAVAILABLE;
1022: int argStartIndex = 0;
1023: if (!Modifier.isStatic(m_calleeMemberModifiers)
1024: && m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT
1025: && m_joinPointType != JoinPointType.HANDLER_INT) {
1026: calleeIndex = 0;
1027: argStartIndex++;
1028: } else {
1029: calleeIndex = INDEX_NOTAVAILABLE;// no callee in the invoke(..) parameters
1030: }
1031: int callerIndex = argStartIndex
1032: + AsmHelper.getRegisterDepth(m_argumentTypes);
1033:
1034: // custom logic overrides for handler jp
1035: if (m_joinPointType == JoinPointType.HANDLER_INT) {
1036: calleeIndex = 0;
1037: callerIndex = 2;
1038: argStartIndex = 1;
1039: }
1040:
1041: // do we need to keep track of CALLEE, ARGS etc, if not then completely skip it
1042: // and make use of the optimized join point instance
1043: // while not using its fields (does not support reentrancy and thread safety)
1044: final boolean isOptimizedJoinPoint = !m_requiresJoinPoint
1045: && !requiresProceedMethod();
1046: int joinPointIndex = INDEX_NOTAVAILABLE;
1047:
1048: if (!isOptimizedJoinPoint) {
1049: // create a new JP and makes use of it
1050: joinPointIndex = callerIndex + 1;
1051: createInvocationLocalJoinPointInstance(cv, argStartIndex,
1052: joinPointIndex, callerIndex, calleeIndex);
1053: }
1054:
1055: // initialize the instance level aspects (perInstance)
1056: initializeInstanceLevelAspects(cv, isOptimizedJoinPoint,
1057: joinPointIndex, callerIndex, calleeIndex);
1058:
1059: // before advices
1060: createBeforeAdviceInvocations(cv, isOptimizedJoinPoint,
1061: argStartIndex, joinPointIndex, callerIndex, calleeIndex);
1062:
1063: // handle different combinations of after advice (finally/throwing/returning)
1064: if (m_afterFinallyAdviceMethodInfos.length == 0
1065: && m_afterThrowingAdviceMethodInfos.length == 0
1066: && !m_isThisAdvisable) {
1067: createPartOfInvokeMethodWithoutAfterFinallyAndAfterThrowingAdviceTypes(
1068: cv, isOptimizedJoinPoint, joinPointIndex,
1069: argStartIndex, callerIndex, calleeIndex);
1070: } else if (m_afterThrowingAdviceMethodInfos.length == 0
1071: && !m_isThisAdvisable) {
1072: createPartOfInvokeMethodWithoutAfterThrowingAdviceTypes(cv,
1073: isOptimizedJoinPoint, joinPointIndex,
1074: argStartIndex, callerIndex, calleeIndex);
1075: } else {
1076: createPartOfInvokeMethodWithAllAdviceTypes(cv,
1077: OPTIMIZED_JOIN_POINT, joinPointIndex,
1078: argStartIndex, callerIndex, calleeIndex);
1079: }
1080:
1081: cv.visitMaxs(0, 0);
1082: }
1083:
1084: /**
1085: * Initializes instance level aspects, retrieves them from the target instance through the
1086: * <code>HasInstanceLevelAspect</code> interfaces.
1087: * <p/>
1088: * Use by 'perInstance', 'perThis' and 'perTarget' deployment models.
1089: *
1090: * @param cv
1091: * @param isOptimizedJoinPoint
1092: * @param joinPointIndex
1093: * @param callerIndex
1094: * @param calleeIndex
1095: */
1096: protected void initializeInstanceLevelAspects(final CodeVisitor cv,
1097: final boolean isOptimizedJoinPoint,
1098: final int joinPointIndex, final int callerIndex,
1099: final int calleeIndex) {
1100: for (int i = 0; i < m_aspectInfos.length; i++) {
1101: AspectInfo aspectInfo = m_aspectInfos[i];
1102: if (aspectInfo.getDeploymentModel() == DeploymentModel.PER_INSTANCE) {
1103: // gen code: aspectField = (<TYPE>)((HasInstanceLocalAspect)CALLER).aw$getAspect(className, qualifiedName, containerClassName)
1104: loadJoinPointInstance(cv, isOptimizedJoinPoint,
1105: joinPointIndex);
1106: if (callerIndex >= 0) {
1107: cv.visitVarInsn(ALOAD, callerIndex);
1108: } else {
1109: // caller instance not available - skipping
1110: //TODO clean up should not occur
1111: }
1112: cv.visitLdcInsn(aspectInfo.getAspectClassName()
1113: .replace('/', '.'));
1114: cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
1115: cv.visitLdcInsn(aspectInfo.getAspectDefinition()
1116: .getContainerClassName());
1117: cv.visitMethodInsn(INVOKEINTERFACE,
1118: HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME,
1119: GET_INSTANCE_LEVEL_ASPECT_METHOD_NAME,
1120: GET_INSTANCE_LEVEL_ASPECT_METHOD_SIGNATURE);
1121: cv.visitTypeInsn(CHECKCAST, aspectInfo
1122: .getAspectClassName());
1123: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1124: aspectInfo.getAspectFieldName(), aspectInfo
1125: .getAspectClassSignature());
1126: }
1127: }
1128: }
1129:
1130: /**
1131: * @param cv
1132: * @param isOptimizedJoinPoint
1133: * @param joinPointInstanceIndex
1134: * @param argStartIndex
1135: * @param callerIndex
1136: * @param calleeIndex
1137: */
1138: protected void createPartOfInvokeMethodWithAllAdviceTypes(
1139: final CodeVisitor cv, final boolean isOptimizedJoinPoint,
1140: final int joinPointInstanceIndex, final int argStartIndex,
1141: final int callerIndex, final int calleeIndex) {
1142: final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ? (joinPointInstanceIndex + 1)
1143: : callerIndex + 1;
1144: final int exceptionIndex1 = returnValueIndex + 1;
1145: final int exceptionIndex2 = returnValueIndex + 2;
1146:
1147: cv.visitInsn(ACONST_NULL);
1148: cv.visitVarInsn(ASTORE, returnValueIndex);
1149:
1150: Label tryLabel = new Label();
1151: cv.visitLabel(tryLabel);
1152: if (!requiresProceedMethod()) {
1153: // if no around advice then optimize by invoking the target JP directly and no call to proceed()
1154: createInlinedJoinPointInvocation(cv, isOptimizedJoinPoint,
1155: argStartIndex, joinPointInstanceIndex);
1156: int stackIndex = returnValueIndex;//use another int since storeType will update it
1157: AsmHelper.storeType(cv, stackIndex, m_returnType);
1158: addReturnedValueToJoinPoint(cv, returnValueIndex,
1159: joinPointInstanceIndex, false);
1160: } else {
1161: createInvocationToProceedMethod(cv, joinPointInstanceIndex,
1162: returnValueIndex);
1163: }
1164:
1165: createAfterReturningAdviceInvocations(cv, isOptimizedJoinPoint,
1166: argStartIndex, joinPointInstanceIndex, callerIndex,
1167: calleeIndex);
1168:
1169: Label finallyLabel1 = new Label();
1170: cv.visitLabel(finallyLabel1);
1171:
1172: if (m_isThisAdvisable) {
1173: final int registerDepth = callerIndex + 2; // caller is using last register + possible return value
1174: createAfterInterceptorInvocations(cv,
1175: joinPointInstanceIndex, registerDepth);
1176: }
1177: createAfterFinallyAdviceInvocations(cv, isOptimizedJoinPoint,
1178: argStartIndex, joinPointInstanceIndex, callerIndex,
1179: calleeIndex);
1180:
1181: Label gotoFinallyLabel = new Label();
1182: cv.visitJumpInsn(GOTO, gotoFinallyLabel);
1183:
1184: Label catchLabel = new Label();
1185: cv.visitLabel(catchLabel);
1186:
1187: // store the exception
1188: cv.visitVarInsn(ASTORE, exceptionIndex1);
1189:
1190: if (m_isThisAdvisable) {
1191: createAfterThrowingInterceptorInvocations(cv,
1192: joinPointInstanceIndex, exceptionIndex1);
1193: }
1194:
1195: // loop over the after throwing advices
1196: for (int i = m_afterThrowingAdviceMethodInfos.length - 1; i >= 0; i--) {
1197: AdviceMethodInfo advice = m_afterThrowingAdviceMethodInfos[i];
1198:
1199: // set the exception argument index
1200: advice.setSpecialArgumentIndex(exceptionIndex1);
1201:
1202: // if (e instanceof TYPE) {...}
1203: cv.visitVarInsn(ALOAD, exceptionIndex1);
1204:
1205: final String specialArgTypeName = advice
1206: .getSpecialArgumentTypeName();
1207: if (specialArgTypeName != null) {
1208: // after throwing <TYPE>
1209: cv.visitTypeInsn(INSTANCEOF, specialArgTypeName);
1210:
1211: Label ifInstanceOfLabel = new Label();
1212: cv.visitJumpInsn(IFEQ, ifInstanceOfLabel);
1213:
1214: // after throwing advice invocation
1215: createAfterAdviceInvocation(cv, isOptimizedJoinPoint,
1216: advice, joinPointInstanceIndex, argStartIndex,
1217: callerIndex, calleeIndex, exceptionIndex1);
1218:
1219: cv.visitLabel(ifInstanceOfLabel);
1220: } else {
1221: // after throwing
1222: createAfterAdviceInvocation(cv, isOptimizedJoinPoint,
1223: advice, joinPointInstanceIndex, argStartIndex,
1224: callerIndex, calleeIndex, INDEX_NOTAVAILABLE);
1225: }
1226: }
1227:
1228: // rethrow exception
1229: cv.visitVarInsn(ALOAD, exceptionIndex1);
1230: cv.visitInsn(ATHROW);
1231:
1232: // store exception
1233: Label exceptionLabel = new Label();
1234: cv.visitLabel(exceptionLabel);
1235: cv.visitVarInsn(ASTORE, exceptionIndex2);
1236:
1237: // after finally advice invocation
1238: Label finallyLabel2 = new Label();
1239: cv.visitLabel(finallyLabel2);
1240:
1241: if (m_isThisAdvisable) {
1242: final int registerDepth = callerIndex + 2; // caller is using last register + possible return value
1243: createAfterInterceptorInvocations(cv,
1244: joinPointInstanceIndex, registerDepth);
1245: }
1246: createAfterFinallyAdviceInvocations(cv, isOptimizedJoinPoint,
1247: argStartIndex, joinPointInstanceIndex, callerIndex,
1248: calleeIndex);
1249:
1250: // rethrow exception
1251: cv.visitVarInsn(ALOAD, exceptionIndex2);
1252: cv.visitInsn(ATHROW);
1253: cv.visitLabel(gotoFinallyLabel);
1254:
1255: // unwrap if around advice and return in all cases
1256: if (m_returnType.getSort() != Type.VOID) {
1257: if (requiresProceedMethod()) {
1258: cv.visitVarInsn(ALOAD, returnValueIndex);
1259: AsmHelper.unwrapType(cv, m_returnType);
1260: } else {
1261: AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1262: }
1263: }
1264:
1265: AsmHelper.addReturnStatement(cv, m_returnType);
1266:
1267: // build up the exception table
1268: cv.visitTryCatchBlock(tryLabel, finallyLabel1, catchLabel,
1269: THROWABLE_CLASS_NAME);
1270: cv.visitTryCatchBlock(tryLabel, finallyLabel1, exceptionLabel,
1271: null);
1272: cv.visitTryCatchBlock(catchLabel, finallyLabel2,
1273: exceptionLabel, null);
1274: }
1275:
1276: /**
1277: * @param cv
1278: * @param isOptimizedJoinPoint
1279: * @param joinPointInstanceIndex
1280: * @param argStartIndex
1281: * @param callerIndex
1282: * @param calleeIndex
1283: */
1284: protected void createPartOfInvokeMethodWithoutAfterThrowingAdviceTypes(
1285: final CodeVisitor cv, final boolean isOptimizedJoinPoint,
1286: final int joinPointInstanceIndex, final int argStartIndex,
1287: final int callerIndex, final int calleeIndex) {
1288: final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ? (joinPointInstanceIndex + 1)
1289: : callerIndex + 1;
1290: final int exceptionIndex = returnValueIndex + 1;
1291:
1292: cv.visitInsn(ACONST_NULL);
1293: cv.visitVarInsn(ASTORE, returnValueIndex);
1294:
1295: Label tryLabel = new Label();
1296: cv.visitLabel(tryLabel);
1297: if (!requiresProceedMethod()) {
1298: // if no around advice then optimize by invoking the target JP directly and no call to proceed()
1299: createInlinedJoinPointInvocation(cv, isOptimizedJoinPoint,
1300: argStartIndex, joinPointInstanceIndex);
1301: int stackIndex = returnValueIndex;//use another int since storeType will update it
1302: AsmHelper.storeType(cv, stackIndex, m_returnType);
1303: addReturnedValueToJoinPoint(cv, returnValueIndex,
1304: joinPointInstanceIndex, false);
1305: } else {
1306: createInvocationToProceedMethod(cv, joinPointInstanceIndex,
1307: returnValueIndex);
1308: }
1309:
1310: createAfterReturningAdviceInvocations(cv, isOptimizedJoinPoint,
1311: argStartIndex, joinPointInstanceIndex, callerIndex,
1312: calleeIndex);
1313:
1314: Label finallyLabel1 = new Label();
1315: cv.visitLabel(finallyLabel1);
1316:
1317: createAfterFinallyAdviceInvocations(cv, isOptimizedJoinPoint,
1318: argStartIndex, joinPointInstanceIndex, callerIndex,
1319: calleeIndex);
1320:
1321: Label gotoFinallyLabel = new Label();
1322: cv.visitJumpInsn(GOTO, gotoFinallyLabel);
1323:
1324: Label exceptionLabel = new Label();
1325: cv.visitLabel(exceptionLabel);
1326: cv.visitVarInsn(ASTORE, exceptionIndex);
1327:
1328: Label finallyLabel2 = new Label();
1329: cv.visitLabel(finallyLabel2);
1330:
1331: createAfterFinallyAdviceInvocations(cv, isOptimizedJoinPoint,
1332: argStartIndex, joinPointInstanceIndex, callerIndex,
1333: calleeIndex);
1334:
1335: cv.visitVarInsn(ALOAD, exceptionIndex);
1336: cv.visitInsn(ATHROW);
1337:
1338: cv.visitLabel(gotoFinallyLabel);
1339:
1340: // unwrap if around advice and return in all cases
1341: if (m_returnType.getSort() != Type.VOID) {
1342: if (requiresProceedMethod()) {
1343: cv.visitVarInsn(ALOAD, returnValueIndex);
1344: AsmHelper.unwrapType(cv, m_returnType);
1345: } else {
1346: AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1347: }
1348: }
1349:
1350: AsmHelper.addReturnStatement(cv, m_returnType);
1351:
1352: cv.visitTryCatchBlock(tryLabel, finallyLabel1, exceptionLabel,
1353: null);
1354: cv.visitTryCatchBlock(exceptionLabel, finallyLabel2,
1355: exceptionLabel, null);
1356: }
1357:
1358: /**
1359: * @param cv
1360: * @param isOptimizedJoinPoint
1361: * @param joinPointInstanceIndex
1362: * @param argStartIndex
1363: * @param callerIndex
1364: * @param calleeIndex
1365: */
1366: protected void createPartOfInvokeMethodWithoutAfterFinallyAndAfterThrowingAdviceTypes(
1367: final CodeVisitor cv, final boolean isOptimizedJoinPoint,
1368: final int joinPointInstanceIndex, final int argStartIndex,
1369: final int callerIndex, final int calleeIndex) {
1370:
1371: final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ? (joinPointInstanceIndex + 1)
1372: : callerIndex + 1;
1373: if (!requiresProceedMethod()) {
1374: // if no around advice then optimize by invoking the target JP directly and no call to proceed()
1375: createInlinedJoinPointInvocation(cv, isOptimizedJoinPoint,
1376: argStartIndex, joinPointInstanceIndex);
1377: int stackIndex = returnValueIndex;//use another int since storeType will update it
1378: AsmHelper.storeType(cv, stackIndex, m_returnType);
1379: addReturnedValueToJoinPoint(cv, returnValueIndex,
1380: joinPointInstanceIndex, false);
1381: } else {
1382: createInvocationToProceedMethod(cv, joinPointInstanceIndex,
1383: returnValueIndex);
1384: }
1385:
1386: // after returning advice invocations
1387: createAfterReturningAdviceInvocations(cv, isOptimizedJoinPoint,
1388: argStartIndex, joinPointInstanceIndex, callerIndex,
1389: calleeIndex);
1390:
1391: // unwrap if around advice and return in all cases
1392: if (m_returnType.getSort() != Type.VOID) {
1393: if (requiresProceedMethod()) {
1394: cv.visitVarInsn(ALOAD, returnValueIndex);
1395: AsmHelper.unwrapType(cv, m_returnType);
1396: } else {
1397: AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1398: }
1399: }
1400:
1401: AsmHelper.addReturnStatement(cv, m_returnType);
1402: }
1403:
1404: /**
1405: * Creates an invocation to the proceed method.
1406: *
1407: * @param cv
1408: * @param joinPointInstanceIndex
1409: * @param returnValueIndex
1410: */
1411: protected void createInvocationToProceedMethod(
1412: final CodeVisitor cv, final int joinPointInstanceIndex,
1413: final int returnValueIndex) {
1414: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1415: cv.visitMethodInsn(INVOKEVIRTUAL, m_joinPointClassName,
1416: PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1417: cv.visitVarInsn(ASTORE, returnValueIndex);
1418: }
1419:
1420: /**
1421: * Creates an "invocation local" join point instance, e.g. one join point per invocation. Needed for thread-safety
1422: * when invoking around advice.
1423: *
1424: * @param cv
1425: * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or
1426: * not)
1427: * @param joinPointInstanceIndex
1428: * @param callerIndex
1429: * @param calleeIndex
1430: */
1431: protected void createInvocationLocalJoinPointInstance(
1432: final CodeVisitor cv, final int argStartIndex,
1433: final int joinPointInstanceIndex, final int callerIndex,
1434: final int calleeIndex) {
1435: // create the join point instance
1436: cv.visitTypeInsn(NEW, m_joinPointClassName);
1437: cv.visitInsn(DUP);
1438: cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName,
1439: INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
1440:
1441: // store the jp on the stack
1442: cv.visitVarInsn(ASTORE, joinPointInstanceIndex);
1443:
1444: // set the argument fields in the join point instance (jp.m_arg<i> = <arg_i>)
1445: int argStackIndex = argStartIndex;
1446: for (int i = 0; i < m_fieldNames.length; i++) {
1447: String fieldName = m_fieldNames[i];
1448: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1449: Type type = m_argumentTypes[i];
1450: argStackIndex = AsmHelper.loadType(cv, argStackIndex, type);
1451: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1452: fieldName, type.getDescriptor());
1453: }
1454:
1455: // caller (can be assigned to null)
1456: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1457: cv.visitVarInsn(ALOAD, callerIndex);
1458: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1459: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1460:
1461: // callee (can be not available)
1462: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1463: if (calleeIndex != INDEX_NOTAVAILABLE) {
1464: cv.visitVarInsn(ALOAD, 0);
1465: } else {
1466: cv.visitInsn(ACONST_NULL);
1467: }
1468: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1469: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1470:
1471: if (m_isThisAdvisable) {
1472: createInitializationForAdvisableManagement(cv,
1473: joinPointInstanceIndex, callerIndex);
1474: }
1475: }
1476:
1477: /**
1478: * Create the proceed() method.
1479: */
1480: protected void createProceedMethod() {
1481:
1482: CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC | ACC_FINAL,
1483: PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE,
1484: new String[] { THROWABLE_CLASS_NAME }, null);
1485:
1486: if (m_isThisAdvisable) {
1487: createAroundInterceptorInvocations(cv);
1488: }
1489:
1490: incrementStackFrameCounter(cv);
1491:
1492: // set up the labels
1493: Label tryLabel = new Label();
1494: Label defaultCaseLabel = new Label();
1495: Label gotoLabel = new Label();
1496: Label handlerLabel = new Label();
1497: Label endLabel = new Label();
1498:
1499: int nrOfCases = m_aroundAdviceMethodInfos.length;
1500: if (m_isThisAdvisable) {
1501: nrOfCases++;
1502: }
1503:
1504: Label[] caseLabels = new Label[nrOfCases];
1505: Label[] returnLabels = new Label[nrOfCases];
1506: int[] caseNumbers = new int[nrOfCases];
1507: for (int i = 0; i < caseLabels.length; i++) {
1508: caseLabels[i] = new Label();
1509: caseNumbers[i] = i;
1510: }
1511: for (int i = 0; i < returnLabels.length; i++) {
1512: returnLabels[i] = new Label();
1513: }
1514:
1515: // start try-catch block
1516: cv.visitLabel(tryLabel);
1517:
1518: // start the switch block and set the stackframe as the param to the switch
1519: cv.visitVarInsn(ALOAD, 0);
1520: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
1521: STACK_FRAME_COUNTER_FIELD_NAME, I);
1522: cv.visitLookupSwitchInsn(defaultCaseLabel, caseNumbers,
1523: caseLabels);
1524:
1525: // add one case for each around advice invocation
1526: for (int i = 0; i < m_aroundAdviceMethodInfos.length; i++) {
1527: cv.visitLabel(caseLabels[i]);
1528:
1529: // gather advice info
1530: AdviceMethodInfo adviceInfo = m_aroundAdviceMethodInfos[i];
1531:
1532: Label endInstanceOflabel = beginRuntimeCheck(cv, false, 0,
1533: adviceInfo.getAdviceInfo(), -1);
1534:
1535: // get the aspect instance
1536: loadAspect(cv, NON_OPTIMIZED_JOIN_POINT, 0, adviceInfo
1537: .getAspectInfo());
1538:
1539: // load the arguments to the advice from the join point instance plus build up the
1540: // advice method signature
1541: int[] argIndexes = adviceInfo.getAdviceMethodArgIndexes();
1542: for (int j = 0; j < argIndexes.length; j++) {
1543: int argIndex = argIndexes[j];
1544: if (argIndex >= 0) {
1545: Type argumentType = m_argumentTypes[argIndex];
1546: cv.visitVarInsn(ALOAD, 0);
1547: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
1548: ARGUMENT_FIELD + argIndex, argumentType
1549: .getDescriptor());
1550: } else if (argIndex == AdviceInfo.JOINPOINT_ARG
1551: || argIndex == AdviceInfo.STATIC_JOINPOINT_ARG
1552: || argIndex == AdviceInfo.VALID_NON_AW_AROUND_CLOSURE_TYPE
1553: || argIndex == AdviceInfo.CUSTOM_JOIN_POINT_ARG) {
1554: cv.visitVarInsn(ALOAD, 0);
1555: } else if (argIndex == AdviceInfo.TARGET_ARG) {
1556: loadCallee(cv, NON_OPTIMIZED_JOIN_POINT, 0,
1557: INDEX_NOTAVAILABLE);
1558: // add a cast if runtime check was used
1559: if (adviceInfo.getAdviceInfo()
1560: .hasTargetWithRuntimeCheck()) {
1561: cv.visitTypeInsn(CHECKCAST, adviceInfo
1562: .getAdviceInfo()
1563: .getMethodParameterTypes()[j]
1564: .getInternalName());
1565: }
1566: } else if (argIndex == AdviceInfo.THIS_ARG) {
1567: loadCaller(cv, NON_OPTIMIZED_JOIN_POINT, 0,
1568: INDEX_NOTAVAILABLE);
1569: } else {
1570: throw new Error(
1571: "advice method argument index type is not supported: "
1572: + argIndex);
1573: }
1574: }
1575:
1576: // invoke the advice method
1577: cv.visitMethodInsn(INVOKEVIRTUAL, adviceInfo
1578: .getAspectInfo().getAspectClassName(), adviceInfo
1579: .getAdviceInfo().getMethodName(), adviceInfo
1580: .getAdviceInfo().getMethodSignature());
1581: cv.visitVarInsn(ASTORE, 1);
1582:
1583: // we need to handle the case when the advice was skipped due to runtime check
1584: // that is : if (runtimeCheck) { ret = advice() } else { ret = proceed() }
1585: if (endInstanceOflabel != null) {
1586: Label elseInstanceOfLabel = new Label();
1587: cv.visitJumpInsn(GOTO, elseInstanceOfLabel);
1588: endRuntimeCheck(cv, adviceInfo.getAdviceInfo(),
1589: endInstanceOflabel);
1590: cv.visitVarInsn(ALOAD, 0);
1591: cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName,
1592: PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1593: cv.visitVarInsn(ASTORE, 1);
1594: cv.visitLabel(elseInstanceOfLabel);
1595: }
1596:
1597: cv.visitLabel(returnLabels[i]);
1598:
1599: cv.visitVarInsn(ALOAD, 1);
1600: cv.visitInsn(ARETURN);
1601: }
1602:
1603: if (m_isThisAdvisable) {
1604: int delegationCaseIndex = caseLabels.length - 1;
1605: cv.visitLabel(caseLabels[delegationCaseIndex]);
1606: cv.visitVarInsn(ALOAD, 0);
1607: cv.visitInsn(ICONST_0);
1608: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1609: INTERCEPTOR_INDEX_FIELD_NAME, I);
1610: cv.visitVarInsn(ALOAD, 0);
1611: cv.visitMethodInsn(INVOKEVIRTUAL, m_joinPointClassName,
1612: PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1613:
1614: cv.visitLabel(returnLabels[delegationCaseIndex]);
1615:
1616: cv.visitInsn(ARETURN);
1617: }
1618:
1619: // invoke the target join point in the default case
1620: cv.visitLabel(defaultCaseLabel);
1621:
1622: AsmHelper.prepareWrappingOfPrimitiveType(cv, Type
1623: .getReturnType(m_calleeMemberDesc));
1624:
1625: createJoinPointInvocation(cv);
1626:
1627: Type m_returnType = null;
1628: if (m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT) {
1629: m_returnType = Type.getReturnType(m_calleeMemberDesc);
1630: } else {
1631: m_returnType = Type.getType(m_calleeClassSignature);
1632: }
1633: AsmHelper.wrapPrimitiveType(cv, m_returnType);
1634: cv.visitVarInsn(ASTORE, 1);
1635:
1636: // store it in Rtti return value
1637: addReturnedValueToJoinPoint(cv, 1, 0, true);
1638:
1639: // set it as the CALLEE instance for ctor call - TODO refactor somewhere else
1640: if (m_joinPointType == JoinPointType.CONSTRUCTOR_CALL_INT) {
1641: cv.visitVarInsn(ALOAD, 0);
1642: cv.visitVarInsn(ALOAD, 1);
1643: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1644: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1645: }
1646:
1647: cv.visitLabel(gotoLabel);
1648:
1649: cv.visitVarInsn(ALOAD, 1);
1650: cv.visitInsn(ARETURN);
1651:
1652: // finally clause
1653: cv.visitLabel(handlerLabel);
1654: cv.visitVarInsn(ASTORE, 2);
1655: cv.visitLabel(endLabel);
1656:
1657: cv.visitVarInsn(ALOAD, 2);
1658: cv.visitInsn(ATHROW);
1659:
1660: // set up the label table
1661: cv.visitTryCatchBlock(tryLabel, returnLabels[0], handlerLabel,
1662: null);
1663: for (int i = 1; i < caseLabels.length; i++) {
1664: Label caseLabel = caseLabels[i];
1665: Label returnLabel = returnLabels[i];
1666: cv.visitTryCatchBlock(caseLabel, returnLabel, handlerLabel,
1667: null);
1668: }
1669: cv.visitTryCatchBlock(defaultCaseLabel, gotoLabel,
1670: handlerLabel, null);
1671: cv.visitTryCatchBlock(handlerLabel, endLabel, handlerLabel,
1672: null);
1673: cv.visitMaxs(0, 0);
1674: }
1675:
1676: /**
1677: * Adds before advice invocations.
1678: *
1679: * @param cv
1680: * @param isOptimizedJoinPoint
1681: * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or
1682: * not)
1683: * @param joinPointInstanceIndex >= 0 if STATIC_JOIN_POINT is NOT to be used (around advice)
1684: * @param callerIndex
1685: * @param calleeIndex
1686: */
1687: protected void createBeforeAdviceInvocations(final CodeVisitor cv,
1688: final boolean isOptimizedJoinPoint,
1689: final int argStartIndex, final int joinPointInstanceIndex, //FIXME redundant -1 with isStaticJP
1690: final int callerIndex, final int calleeIndex) {
1691: for (int i = 0; i < m_beforeAdviceMethodInfos.length; i++) {
1692: AdviceMethodInfo adviceMethodInfo = m_beforeAdviceMethodInfos[i];
1693:
1694: // runtime check for target() etc
1695: Label endInstanceOflabel = beginRuntimeCheck(cv,
1696: isOptimizedJoinPoint, joinPointInstanceIndex,
1697: adviceMethodInfo.getAdviceInfo(), calleeIndex);
1698:
1699: //get the aspect instance
1700: loadAspect(cv, isOptimizedJoinPoint,
1701: joinPointInstanceIndex, adviceMethodInfo
1702: .getAspectInfo());
1703:
1704: AspectDefinition aspectDef = adviceMethodInfo
1705: .getAdviceInfo().getAdviceDefinition()
1706: .getAspectDefinition();
1707: if (aspectDef.isAspectWerkzAspect()) {
1708: // AW aspect
1709: int[] argIndexes = adviceMethodInfo
1710: .getAdviceMethodArgIndexes();
1711: // if empty, we consider for now that we have to push JoinPoint for old advice with JoinPoint as sole arg
1712: for (int j = 0; j < argIndexes.length; j++) {
1713: int argIndex = argIndexes[j];
1714: if (argIndex >= 0) {
1715: Type argumentType = m_argumentTypes[argIndex];
1716: int argStackIndex = AsmHelper
1717: .getRegisterIndexOf(m_argumentTypes,
1718: argIndex)
1719: + argStartIndex;
1720: AsmHelper.loadType(cv, argStackIndex,
1721: argumentType);
1722: } else if (argIndex == AdviceInfo.JOINPOINT_ARG
1723: || argIndex == AdviceInfo.STATIC_JOINPOINT_ARG) {
1724: loadJoinPointInstance(cv, isOptimizedJoinPoint,
1725: joinPointInstanceIndex);
1726: } else if (argIndex == AdviceInfo.TARGET_ARG) {
1727: loadCallee(cv, isOptimizedJoinPoint,
1728: joinPointInstanceIndex, calleeIndex);
1729: // add a cast if runtime check was used
1730: if (adviceMethodInfo.getAdviceInfo()
1731: .hasTargetWithRuntimeCheck()) {
1732: cv
1733: .visitTypeInsn(
1734: CHECKCAST,
1735: adviceMethodInfo
1736: .getAdviceInfo()
1737: .getMethodParameterTypes()[j]
1738: .getInternalName());
1739: }
1740: } else if (argIndex == AdviceInfo.THIS_ARG) {
1741: loadCaller(cv, isOptimizedJoinPoint,
1742: joinPointInstanceIndex, callerIndex);
1743: } else {
1744: throw new Error(
1745: "special argument index is not supported: "
1746: + argIndex);
1747: }
1748: }
1749: } else {
1750: // non-AW aspect
1751: adviceMethodInfo
1752: .setJoinPointIndex(joinPointInstanceIndex);
1753: for (int j = 0; j < m_aspectModels.length; j++) {
1754: AspectModel aspectModel = m_aspectModels[j];
1755: if (aspectDef.getAspectModel().equals(
1756: aspectModel.getAspectModelType())) {
1757: aspectModel.createBeforeAdviceArgumentHandling(
1758: cv, adviceMethodInfo);
1759: }
1760: }
1761: }
1762:
1763: cv.visitMethodInsn(INVOKEVIRTUAL, adviceMethodInfo
1764: .getAspectInfo().getAspectClassName(),
1765: adviceMethodInfo.getAdviceInfo().getMethodName(),
1766: adviceMethodInfo.getAdviceInfo()
1767: .getMethodSignature());
1768:
1769: // end label of runtime checks
1770: endRuntimeCheck(cv, adviceMethodInfo.getAdviceInfo(),
1771: endInstanceOflabel);
1772: }
1773:
1774: if (m_isThisAdvisable) {
1775: createBeforeInterceptorInvocations(cv,
1776: joinPointInstanceIndex, callerIndex + 1);
1777: }
1778: }
1779:
1780: /**
1781: * Adds after advice invocations.
1782: *
1783: * @param cv
1784: * @param isOptimizedJoinPoint
1785: * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or
1786: * not)
1787: * @param joinPointInstanceIndex >= 0 if STATIC_JOIN_POINT is NOT to be used (around advice)
1788: * @param callerIndex
1789: * @param calleeIndex
1790: */
1791: protected void createAfterFinallyAdviceInvocations(
1792: final CodeVisitor cv, final boolean isOptimizedJoinPoint,
1793: final int argStartIndex, final int joinPointInstanceIndex,
1794: final int callerIndex, final int calleeIndex) {
1795: // add after advice in reverse order
1796: for (int i = m_afterFinallyAdviceMethodInfos.length - 1; i >= 0; i--) {
1797: AdviceMethodInfo advice = m_afterFinallyAdviceMethodInfos[i];
1798: createAfterAdviceInvocation(cv, isOptimizedJoinPoint,
1799: advice, joinPointInstanceIndex, argStartIndex,
1800: callerIndex, calleeIndex, INDEX_NOTAVAILABLE);
1801: }
1802: }
1803:
1804: /**
1805: * Adds after returning advice invocations.
1806: *
1807: * @param cv
1808: * @param isOptimizedJoinPoint
1809: * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or
1810: * not)
1811: * @param joinPointInstanceIndex >= 0 if STATIC_JOIN_POINT is NOT to be used (around advice)
1812: * @param callerIndex
1813: * @param calleeIndex
1814: */
1815: protected void createAfterReturningAdviceInvocations(
1816: final CodeVisitor cv, final boolean isOptimizedJoinPoint,
1817: final int argStartIndex, final int joinPointInstanceIndex,
1818: final int callerIndex, final int calleeIndex) {
1819:
1820: final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ? (joinPointInstanceIndex + 1)
1821: : callerIndex + 1;
1822:
1823: if (m_isThisAdvisable) {
1824: createAfterReturningInterceptorInvocations(cv,
1825: joinPointInstanceIndex, returnValueIndex);
1826: }
1827:
1828: boolean hasPoppedReturnValueFromStack = false;
1829: for (int i = m_afterReturningAdviceMethodInfos.length - 1; i >= 0; i--) {
1830: AdviceMethodInfo advice = m_afterReturningAdviceMethodInfos[i];
1831:
1832: // set the return value index that will be used as arg to advice
1833: advice.setSpecialArgumentIndex(returnValueIndex);
1834:
1835: String specialArgDesc = advice.getSpecialArgumentTypeDesc();
1836: if (specialArgDesc == null) {
1837: // after returning
1838: createAfterAdviceInvocation(cv, isOptimizedJoinPoint,
1839: advice, joinPointInstanceIndex, argStartIndex,
1840: callerIndex, calleeIndex, INDEX_NOTAVAILABLE);
1841: } else {
1842: // after returning <TYPE>
1843: if (AsmHelper.isPrimitive(m_returnType)) {
1844: if (m_returnType.getDescriptor().equals(
1845: specialArgDesc)) {
1846: createAfterAdviceInvocation(cv,
1847: isOptimizedJoinPoint, advice,
1848: joinPointInstanceIndex, argStartIndex,
1849: callerIndex, calleeIndex,
1850: returnValueIndex);
1851: }
1852: } else {
1853: cv.visitVarInsn(ALOAD, returnValueIndex);
1854:
1855: cv.visitTypeInsn(INSTANCEOF, advice
1856: .getSpecialArgumentTypeName());
1857:
1858: Label label = new Label();
1859: cv.visitJumpInsn(IFEQ, label);
1860:
1861: createAfterAdviceInvocation(cv,
1862: isOptimizedJoinPoint, advice,
1863: joinPointInstanceIndex, argStartIndex,
1864: callerIndex, calleeIndex, returnValueIndex);
1865:
1866: cv.visitLabel(label);
1867: }
1868: }
1869: }
1870:
1871: // need the return value in return operation
1872: if (!requiresProceedMethod() && hasPoppedReturnValueFromStack) {
1873: cv.visitVarInsn(ALOAD, returnValueIndex);
1874: }
1875: }
1876:
1877: /**
1878: * Adds a single generic after advice invocation.
1879: *
1880: * @param cv
1881: * @param isOptimizedJoinPoint
1882: * @param adviceMethodInfo
1883: * @param joinPointInstanceIndex
1884: * @param argStartIndex
1885: * @param callerIndex
1886: * @param calleeIndex
1887: * @param specialArgIndex for afterReturning / Throwing when binding is used
1888: */
1889: protected void createAfterAdviceInvocation(final CodeVisitor cv,
1890: final boolean isOptimizedJoinPoint,
1891: final AdviceMethodInfo adviceMethodInfo,
1892: final int joinPointInstanceIndex, final int argStartIndex,
1893: final int callerIndex, final int calleeIndex,
1894: final int specialArgIndex) {
1895: // runtime check for target() etc
1896: Label endInstanceOflabel = beginRuntimeCheck(cv,
1897: isOptimizedJoinPoint, joinPointInstanceIndex,
1898: adviceMethodInfo.getAdviceInfo(), calleeIndex);
1899:
1900: // get the aspect instance
1901: loadAspect(cv, isOptimizedJoinPoint, joinPointInstanceIndex,
1902: adviceMethodInfo.getAspectInfo());
1903:
1904: AspectDefinition aspectDef = adviceMethodInfo.getAdviceInfo()
1905: .getAdviceDefinition().getAspectDefinition();
1906: if (aspectDef.isAspectWerkzAspect()) {
1907: // AW aspect
1908: // load the arguments that should be passed to the advice
1909: int[] argIndexes = adviceMethodInfo
1910: .getAdviceMethodArgIndexes();
1911: for (int j = 0; j < argIndexes.length; j++) {
1912: int argIndex = argIndexes[j];
1913: if (argIndex >= 0) {
1914: Type argumentType = m_argumentTypes[argIndex];
1915: int argStackIndex = AsmHelper.getRegisterIndexOf(
1916: m_argumentTypes, argIndex)
1917: + argStartIndex;
1918: AsmHelper.loadType(cv, argStackIndex, argumentType);
1919: } else if (argIndex == AdviceInfo.JOINPOINT_ARG
1920: || argIndex == AdviceInfo.STATIC_JOINPOINT_ARG) {
1921: loadJoinPointInstance(cv, isOptimizedJoinPoint,
1922: joinPointInstanceIndex);
1923: } else if (argIndex == AdviceInfo.TARGET_ARG) {
1924: loadCallee(cv, isOptimizedJoinPoint,
1925: joinPointInstanceIndex, calleeIndex);
1926: // add a cast if runtime check was used
1927: if (adviceMethodInfo.getAdviceInfo()
1928: .hasTargetWithRuntimeCheck()) {
1929: cv.visitTypeInsn(CHECKCAST, adviceMethodInfo
1930: .getAdviceInfo()
1931: .getMethodParameterTypes()[j]
1932: .getInternalName());
1933: }
1934: } else if (argIndex == AdviceInfo.THIS_ARG) {
1935: loadCaller(cv, isOptimizedJoinPoint,
1936: joinPointInstanceIndex, callerIndex);
1937: } else if (argIndex == AdviceInfo.SPECIAL_ARGUMENT
1938: && specialArgIndex != INDEX_NOTAVAILABLE) {
1939: Type argumentType = adviceMethodInfo
1940: .getAdviceInfo().getMethodParameterTypes()[j];
1941: AsmHelper.loadType(cv, specialArgIndex,
1942: argumentType);
1943: if (adviceMethodInfo.getAdviceInfo()
1944: .getAdviceDefinition().getType().equals(
1945: AdviceType.AFTER_THROWING)) {
1946: cv.visitTypeInsn(CHECKCAST, argumentType
1947: .getInternalName());
1948: }
1949: } else {
1950: throw new Error("magic index is not supported: "
1951: + argIndex);
1952: }
1953: }
1954: } else {
1955: // non-AW aspect
1956: adviceMethodInfo.setJoinPointIndex(joinPointInstanceIndex);
1957: for (int i = 0; i < m_aspectModels.length; i++) {
1958: AspectModel aspectModel = m_aspectModels[i];
1959: if (aspectDef.getAspectModel().equals(
1960: aspectModel.getAspectModelType())) {
1961: aspectModel.createAfterAdviceArgumentHandling(cv,
1962: adviceMethodInfo);
1963: }
1964: }
1965: }
1966:
1967: cv.visitMethodInsn(INVOKEVIRTUAL, adviceMethodInfo
1968: .getAspectInfo().getAspectClassName(), adviceMethodInfo
1969: .getAdviceInfo().getMethodName(), adviceMethodInfo
1970: .getAdviceInfo().getMethodSignature());
1971:
1972: // end label of runtime checks
1973: endRuntimeCheck(cv, adviceMethodInfo.getAdviceInfo(),
1974: endInstanceOflabel);
1975: }
1976:
1977: /**
1978: * Adds the return value to the RETURNED field.
1979: *
1980: * @param cv
1981: * @param returnValueIndex
1982: * @param joinPointInstanceIndex
1983: * @param unwrap set to true if already wrapped on the stack (within proceed() code)
1984: */
1985: protected void addReturnedValueToJoinPoint(final CodeVisitor cv,
1986: final int returnValueIndex,
1987: final int joinPointInstanceIndex, final boolean unwrap) {
1988: if (m_requiresJoinPoint && m_returnType.getSort() != Type.VOID) {
1989: if (m_joinPointType == JoinPointType.METHOD_EXECUTION_INT
1990: || m_joinPointType == JoinPointType.METHOD_CALL_INT
1991: || m_joinPointType == JoinPointType.CONSTRUCTOR_CALL_INT) {
1992: //TODO should we do something for field get / set
1993: loadJoinPointInstance(cv, NON_OPTIMIZED_JOIN_POINT,
1994: joinPointInstanceIndex);
1995: if (unwrap && AsmHelper.isPrimitive(m_returnType)) {
1996: cv.visitVarInsn(ALOAD, returnValueIndex);
1997: AsmHelper.unwrapType(cv, m_returnType);
1998: } else {
1999: AsmHelper.loadType(cv, returnValueIndex,
2000: m_returnType);
2001: }
2002: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2003: RETURN_VALUE_FIELD_NAME, m_returnType
2004: .getDescriptor());
2005: }
2006: }
2007: }
2008:
2009: /**
2010: * Loads the join point instance, takes static/non-static join point access into account.
2011: *
2012: * @param cv
2013: * @param isOptimizedJoinPoint
2014: * @param joinPointInstanceIndex
2015: */
2016: protected void loadJoinPointInstance(final CodeVisitor cv,
2017: final boolean isOptimizedJoinPoint,
2018: final int joinPointInstanceIndex) {
2019: if (isOptimizedJoinPoint) {
2020: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
2021: OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME, L
2022: + m_joinPointClassName + SEMICOLON);
2023: } else {
2024: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2025: }
2026: }
2027:
2028: /**
2029: * Loads the argument member fields.
2030: *
2031: * @param cv
2032: * @param argStartIndex
2033: */
2034: protected void loadArgumentMemberFields(final CodeVisitor cv,
2035: final int argStartIndex) {
2036: int argStackIndex = argStartIndex;
2037: for (int index = 0; index < m_argumentTypes.length; index++) {
2038: Type argumentType = m_argumentTypes[index];
2039: argStackIndex = AsmHelper.loadType(cv, argStackIndex,
2040: argumentType);
2041: }
2042: }
2043:
2044: /**
2045: * Loads the arguments.
2046: *
2047: * @param cv
2048: */
2049: protected void loadArguments(final CodeVisitor cv) {
2050: for (int i = 0; i < m_fieldNames.length; i++) {
2051: String fieldName = m_fieldNames[i];
2052: Type argumentType = m_argumentTypes[i];
2053: cv.visitVarInsn(ALOAD, 0);
2054: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2055: fieldName, argumentType.getDescriptor());
2056: }
2057: }
2058:
2059: /**
2060: * Resets the stack frame counter.
2061: *
2062: * @param cv
2063: */
2064: protected void resetStackFrameCounter(final CodeVisitor cv) {
2065: cv.visitVarInsn(ALOAD, 0);
2066: cv.visitInsn(ICONST_M1);
2067: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2068: STACK_FRAME_COUNTER_FIELD_NAME, I);
2069: }
2070:
2071: /**
2072: * Handles the incrementation of the stack frame.
2073: *
2074: * @param cv
2075: */
2076: protected void incrementStackFrameCounter(final CodeVisitor cv) {
2077: cv.visitVarInsn(ALOAD, 0);
2078: cv.visitInsn(DUP);
2079: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2080: STACK_FRAME_COUNTER_FIELD_NAME, I);
2081: cv.visitInsn(ICONST_1);
2082: cv.visitInsn(IADD);
2083: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2084: STACK_FRAME_COUNTER_FIELD_NAME, I);
2085: }
2086:
2087: /**
2088: * Create and load a structure (f.e. array of Object) where args are stored, before setting the Rtti
2089: * with it (See addParametersToRttiInstance). The structure is stored at the given stackFreeIndex.
2090: * <p/>
2091: * We provide here a default implementation that is suitable for method and constructor call and execution.
2092: * See createParameterWrappedAt for field get/set and handler compiler (no array of argument needed)
2093: *
2094: * @param cv
2095: * @param stackFreeIndex
2096: */
2097: protected final void createArgumentArrayAt(final CodeVisitor cv,
2098: final int stackFreeIndex) {
2099: AsmHelper.loadIntegerConstant(cv, m_fieldNames.length);
2100: cv.visitTypeInsn(ANEWARRAY, OBJECT_CLASS_NAME);
2101: cv.visitVarInsn(ASTORE, stackFreeIndex);
2102:
2103: for (int i = 0; i < m_argumentTypes.length; i++) {
2104: cv.visitVarInsn(ALOAD, stackFreeIndex);
2105: AsmHelper.loadIntegerConstant(cv, i);
2106: AsmHelper.prepareWrappingOfPrimitiveType(cv,
2107: m_argumentTypes[i]);
2108: cv.visitVarInsn(ALOAD, 0);
2109: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2110: ARGUMENT_FIELD + i, m_argumentTypes[i]
2111: .getDescriptor());
2112: AsmHelper.wrapPrimitiveType(cv, m_argumentTypes[i]);
2113: cv.visitInsn(AASTORE);
2114: }
2115: }
2116:
2117: /**
2118: * Creates utility methods for the join point (getter, setters etc.).
2119: */
2120: protected void createUtilityMethods() {
2121: CodeVisitor cv;
2122:
2123: // addMetaData
2124: {
2125: cv = m_cw.visitMethod(ACC_PUBLIC,
2126: ADD_META_DATA_METHOD_NAME,
2127: ADD_META_DATA_METHOD_SIGNATURE, null, null);
2128: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
2129: META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
2130: cv.visitVarInsn(ALOAD, 1);
2131: cv.visitVarInsn(ALOAD, 2);
2132: cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME,
2133: PUT_METHOD_NAME, PUT_METHOD_SIGNATURE);
2134: cv.visitInsn(POP);
2135: cv.visitInsn(RETURN);
2136: cv.visitMaxs(0, 0);
2137: }
2138:
2139: // getMetaData
2140: {
2141: cv = m_cw.visitMethod(ACC_PUBLIC,
2142: GET_META_DATA_METHOD_NAME,
2143: GET_META_DATA_METHOD_SIGNATURE, null, null);
2144: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
2145: META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
2146: cv.visitVarInsn(ALOAD, 1);
2147: cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME,
2148: GET_METHOD_NAME, GET_METHOD_SIGNATURE);
2149: cv.visitInsn(ARETURN);
2150: cv.visitMaxs(0, 0);
2151: }
2152:
2153: // getCallee
2154: {
2155: cv = m_cw.visitMethod(ACC_PUBLIC, GET_CALLEE_METHOD_NAME,
2156: NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE, null,
2157: null);
2158: cv.visitVarInsn(ALOAD, 0);
2159: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2160: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2161: cv.visitInsn(ARETURN);
2162: cv.visitMaxs(0, 0);
2163: }
2164:
2165: // getCaller
2166: {
2167: cv = m_cw.visitMethod(ACC_PUBLIC, GET_CALLER_METHOD_NAME,
2168: NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE, null,
2169: null);
2170: cv.visitVarInsn(ALOAD, 0);
2171: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2172: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2173: cv.visitInsn(ARETURN);
2174: cv.visitMaxs(0, 0);
2175: }
2176:
2177: // getTarget
2178: {
2179: cv = m_cw.visitMethod(ACC_PUBLIC, GET_TARGET_METHOD_NAME,
2180: NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE, null,
2181: null);
2182: cv.visitVarInsn(ALOAD, 0);
2183: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2184: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2185: cv.visitInsn(ARETURN);
2186: cv.visitMaxs(0, 0);
2187: }
2188:
2189: // getThis
2190: {
2191: cv = m_cw.visitMethod(ACC_PUBLIC, GET_THIS_METHOD_NAME,
2192: NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE, null,
2193: null);
2194: cv.visitVarInsn(ALOAD, 0);
2195: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2196: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2197: cv.visitInsn(ARETURN);
2198: cv.visitMaxs(0, 0);
2199: }
2200:
2201: // getCallerClass
2202: {
2203: cv = m_cw.visitMethod(ACC_PUBLIC,
2204: GET_CALLER_CLASS_METHOD_NAME,
2205: GET_CALLER_CLASS_METHOD_SIGNATURE, null, null);
2206: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
2207: THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2208: cv.visitInsn(ARETURN);
2209: cv.visitMaxs(0, 0);
2210: }
2211:
2212: // getCalleeClass
2213: {
2214: cv = m_cw.visitMethod(ACC_PUBLIC,
2215: GET_CALLEE_CLASS_METHOD_NAME,
2216: GET_CALLEE_CLASS_METHOD_SIGNATURE, null, null);
2217: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
2218: TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2219: cv.visitInsn(ARETURN);
2220: cv.visitMaxs(0, 0);
2221: }
2222:
2223: // getTargetClass, deprecated but still there
2224: {
2225: cv = m_cw.visitMethod(ACC_PUBLIC,
2226: GET_TARGET_CLASS_METHOD_NAME,
2227: GET_TARGET_CLASS_METHOD_SIGNATURE, null, null);
2228: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
2229: TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2230: cv.visitInsn(ARETURN);
2231: cv.visitMaxs(0, 0);
2232: }
2233:
2234: // getType
2235: {
2236: cv = m_cw.visitMethod(ACC_PUBLIC, GET_TYPE_METHOD_NAME,
2237: GET_TYPE_METHOD_SIGNATURE, null, null);
2238: AsmHelper.loadIntegerConstant(cv, m_joinPointType);
2239: cv.visitMethodInsn(INVOKESTATIC, Type.getType(
2240: JoinPointType.class).getInternalName(), "fromInt",
2241: "(I)"
2242: + Type.getType(JoinPointType.class)
2243: .getDescriptor());
2244: cv.visitInsn(ARETURN);
2245: cv.visitMaxs(0, 0);
2246: }
2247:
2248: // getEnclosingStaticJoinPoint
2249: {
2250: cv = m_cw.visitMethod(ACC_PUBLIC,
2251: GET_ENCLOSING_SJP_METHOD_NAME,
2252: GET_ENCLOSING_SJP_METHOD_SIGNATURE, null, null);
2253: cv.visitVarInsn(ALOAD, 0);
2254: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
2255: ENCLOSING_SJP_FIELD_NAME,
2256: ENCLOSING_SJP_FIELD_CLASS_SIGNATURE);
2257: cv.visitInsn(ARETURN);
2258: cv.visitMaxs(0, 0);
2259: }
2260:
2261: }
2262:
2263: /**
2264: * Creates the copy method.
2265: * <p/>
2266: * TODO refactor and put in subclasses
2267: */
2268: protected void createCopyMethod() {
2269:
2270: CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC, COPY_METHOD_NAME,
2271: COPY_METHOD_SIGNATURE, null, null);
2272:
2273: // create a new join point instance
2274: cv.visitTypeInsn(NEW, m_joinPointClassName);
2275: cv.visitInsn(DUP);
2276: int joinPointCloneIndex = 1;
2277: cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName,
2278: INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
2279: cv.visitVarInsn(ASTORE, joinPointCloneIndex);
2280:
2281: // set stack frame index
2282: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2283: cv.visitVarInsn(ALOAD, 0);
2284: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2285: STACK_FRAME_COUNTER_FIELD_NAME, I);
2286: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2287: STACK_FRAME_COUNTER_FIELD_NAME, I);
2288:
2289: if (m_isThisAdvisable) {
2290: // set interceptor index
2291: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2292: cv.visitVarInsn(ALOAD, 0);
2293: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2294: INTERCEPTOR_INDEX_FIELD_NAME, I);
2295: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2296: INTERCEPTOR_INDEX_FIELD_NAME, I);
2297:
2298: // set array length fields
2299: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2300: cv.visitVarInsn(ALOAD, 0);
2301: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2302: NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2303: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2304: NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2305: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2306: cv.visitVarInsn(ALOAD, 0);
2307: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2308: NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2309: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2310: NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2311: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2312: cv.visitVarInsn(ALOAD, 0);
2313: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2314: NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2315: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2316: NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2317: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2318: cv.visitVarInsn(ALOAD, 0);
2319: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2320: NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2321: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2322: NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2323: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2324: cv.visitVarInsn(ALOAD, 0);
2325: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2326: NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2327: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2328: NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2329:
2330: // set arrays
2331: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2332: cv.visitVarInsn(ALOAD, 0);
2333: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2334: BEFORE_INTERCEPTORS_FIELD_NAME,
2335: BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE);
2336: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2337: BEFORE_INTERCEPTORS_FIELD_NAME,
2338: BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE);
2339: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2340: cv.visitVarInsn(ALOAD, 0);
2341: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2342: AROUND_INTERCEPTORS_FIELD_NAME,
2343: AROUND_ADVICE_ARRAY_CLASS_SIGNATURE);
2344: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2345: AROUND_INTERCEPTORS_FIELD_NAME,
2346: AROUND_ADVICE_ARRAY_CLASS_SIGNATURE);
2347: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2348: cv.visitVarInsn(ALOAD, 0);
2349: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2350: AFTER_INTERCEPTORS_FIELD_NAME,
2351: AFTER_ADVICE_ARRAY_CLASS_SIGNATURE);
2352: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2353: AFTER_INTERCEPTORS_FIELD_NAME,
2354: AFTER_ADVICE_ARRAY_CLASS_SIGNATURE);
2355: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2356: cv.visitVarInsn(ALOAD, 0);
2357: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2358: AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2359: AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE);
2360: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2361: AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2362: AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE);
2363: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2364: cv.visitVarInsn(ALOAD, 0);
2365: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2366: AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2367: AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE);
2368: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2369: AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2370: AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE);
2371: }
2372:
2373: // set callee
2374: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2375: cv.visitVarInsn(ALOAD, 0);
2376: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2377: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2378: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2379: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2380:
2381: // set caller
2382: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2383: cv.visitVarInsn(ALOAD, 0);
2384: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2385: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2386: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2387: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2388:
2389: // set the arguments
2390: for (int i = 0; i < m_fieldNames.length; i++) {
2391: String fieldName = m_fieldNames[i];
2392: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2393: cv.visitVarInsn(ALOAD, 0);
2394: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2395: fieldName, m_argumentTypes[i].getDescriptor());
2396: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2397: fieldName, m_argumentTypes[i].getDescriptor());
2398: }
2399:
2400: // set the returned field if any
2401: if (m_returnType.getSort() != Type.VOID) {
2402: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2403: cv.visitVarInsn(ALOAD, 0);
2404: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2405: RETURN_VALUE_FIELD_NAME, m_returnType
2406: .getDescriptor());
2407: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2408: RETURN_VALUE_FIELD_NAME, m_returnType
2409: .getDescriptor());
2410: }
2411:
2412: cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2413: cv.visitInsn(ARETURN);
2414: cv.visitMaxs(0, 0);
2415: }
2416:
2417: /**
2418: * Build up the signature of the 'invoke' methods.
2419: *
2420: * @return
2421: */
2422: protected String buildInvokeMethodSignature() {
2423: StringBuffer invokeDescBuf = new StringBuffer();
2424: invokeDescBuf.append('(');
2425: if (m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT) {
2426: if (!Modifier.isStatic(m_calleeMemberModifiers)) {
2427: // callee
2428: invokeDescBuf.append(m_calleeClassSignature);
2429: }
2430: }
2431: // args
2432: for (int i = 0; i < m_argumentTypes.length; i++) {
2433: Type type = m_argumentTypes[i];
2434: invokeDescBuf.append(type.getDescriptor());
2435: }
2436: // caller
2437: invokeDescBuf.append(m_callerClassSignature);
2438: invokeDescBuf.append(')');
2439: invokeDescBuf.append(m_returnType.getDescriptor());
2440: return invokeDescBuf.toString();
2441: }
2442:
2443: /**
2444: * Return the number of argument the joinpoint has (excludes JoinPoint, Rtti, this / target) but is only
2445: * the number of argument we will have in the rtti (advised method/ctor args or 1 for field / handler)
2446: *
2447: * @return
2448: */
2449: protected final boolean hasArguments() {
2450: return m_argumentTypes.length > 0;
2451: }
2452:
2453: /**
2454: * Checks if at least one advice is using this or target (bounded or runtime check)
2455: *
2456: * @return true if so
2457: */
2458: protected boolean requiresThisOrTarget() {
2459: return m_isThisAdvisable
2460: || requiresThisOrTarget(m_aroundAdviceMethodInfos)
2461: || requiresThisOrTarget(m_beforeAdviceMethodInfos)
2462: || requiresThisOrTarget(m_afterFinallyAdviceMethodInfos)
2463: || requiresThisOrTarget(m_afterReturningAdviceMethodInfos)
2464: || requiresThisOrTarget(m_afterThrowingAdviceMethodInfos);
2465: }
2466:
2467: /**
2468: * Checks if at least one advice is using the non static JoinPoint explicitly
2469: *
2470: * @return true if so
2471: */
2472: protected boolean requiresJoinPoint() {
2473: return m_isThisAdvisable
2474: || requiresJoinPoint(m_aroundAdviceMethodInfos)
2475: || requiresJoinPoint(m_beforeAdviceMethodInfos)
2476: || requiresJoinPoint(m_afterFinallyAdviceMethodInfos)
2477: || requiresJoinPoint(m_afterReturningAdviceMethodInfos)
2478: || requiresJoinPoint(m_afterThrowingAdviceMethodInfos);
2479: }
2480:
2481: /**
2482: * Checks if at least one advice is using target or this (bounded or runtime check)
2483: *
2484: * @param adviceMethodInfos
2485: * @return true if so
2486: */
2487: protected boolean requiresThisOrTarget(
2488: final AdviceMethodInfo[] adviceMethodInfos) {
2489: for (int i = 0; i < adviceMethodInfos.length; i++) {
2490: if (adviceMethodInfos[i].requiresThisOrTarget()) {
2491: return true;
2492: }
2493: }
2494: return false;
2495: }
2496:
2497: /**
2498: * Checks if at least one advice is using non static JoinPoint explicitly
2499: *
2500: * @param adviceMethodInfos
2501: * @return true if so
2502: */
2503: protected boolean requiresJoinPoint(
2504: final AdviceMethodInfo[] adviceMethodInfos) {
2505: for (int i = 0; i < adviceMethodInfos.length; i++) {
2506: if (adviceMethodInfos[i].requiresJoinPoint()) {
2507: return true;
2508: }
2509: }
2510: return false;
2511: }
2512:
2513: /**
2514: * Handles the if case for runtime check (target instanceof, cflow)
2515: *
2516: * @param cv
2517: * @param isOptimizedJoinPoint
2518: * @param joinPointInstanceIndex
2519: * @param adviceInfo
2520: * @return the label for endIf or null if the adviceInfo did not required runtime check
2521: */
2522: protected Label beginRuntimeCheck(final CodeVisitor cv,
2523: final boolean isOptimizedJoinPoint,
2524: final int joinPointInstanceIndex,
2525: final AdviceInfo adviceInfo, final int calleeIndex) {
2526: Label endRuntimeCheckLabel = null;
2527: if (adviceInfo.hasTargetWithRuntimeCheck()
2528: || adviceInfo.getAdviceDefinition()
2529: .hasCflowOrCflowBelow()) {
2530: endRuntimeCheckLabel = new Label();
2531: // create a specific visitor everytime
2532: RuntimeCheckVisitor runtimeCheckVisitor = new RuntimeCheckVisitor(
2533: this , cv, adviceInfo.getExpressionInfo(),
2534: isOptimizedJoinPoint, joinPointInstanceIndex,
2535: calleeIndex);
2536: runtimeCheckVisitor.pushCheckOnStack(adviceInfo
2537: .getExpressionContext());
2538: cv.visitJumpInsn(IFEQ, endRuntimeCheckLabel);
2539: }
2540: return endRuntimeCheckLabel;
2541: }
2542:
2543: /**
2544: * Ends the ifLabel of a runtime check
2545: *
2546: * @param cv
2547: * @param adviceInfo
2548: * @param label if null, then do nothing (means we did not had a runtime check)
2549: */
2550: protected void endRuntimeCheck(final CodeVisitor cv,
2551: final AdviceInfo adviceInfo, final Label label) {
2552: if (adviceInfo.hasTargetWithRuntimeCheck()
2553: || adviceInfo.getAdviceDefinition()
2554: .hasCflowOrCflowBelow()) {
2555: cv.visitLabel(label);
2556: }
2557: }
2558:
2559: /**
2560: * Helper method to load the callee on the stack
2561: *
2562: * @param cv
2563: * @param isOptimizedJoinPoint
2564: * @param joinPointIndex
2565: * @param calleeIndex
2566: */
2567: public void loadCallee(final CodeVisitor cv,
2568: final boolean isOptimizedJoinPoint,
2569: final int joinPointIndex, final int calleeIndex) {
2570: if (isOptimizedJoinPoint) {
2571: // grab the callee from the invoke parameters directly
2572: cv.visitVarInsn(ALOAD, calleeIndex);
2573: } else {
2574: loadJoinPointInstance(cv, isOptimizedJoinPoint,
2575: joinPointIndex);
2576: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2577: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2578: }
2579: }
2580:
2581: /**
2582: * Helper method to load the caller on the stack
2583: *
2584: * @param cv
2585: * @param isOptimizedJoinPoint
2586: * @param joinPointIndex
2587: * @param callerIndex
2588: */
2589: protected void loadCaller(final CodeVisitor cv,
2590: final boolean isOptimizedJoinPoint,
2591: final int joinPointIndex, final int callerIndex) {
2592: if (isOptimizedJoinPoint) {
2593: // grab the callee from the invoke parameters directly
2594: cv.visitVarInsn(ALOAD, callerIndex);
2595: } else {
2596: loadJoinPointInstance(cv, isOptimizedJoinPoint,
2597: joinPointIndex);
2598: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2599: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2600: }
2601: }
2602:
2603: /**
2604: * Loads the aspect instance.
2605: *
2606: * @param cv
2607: * @param isOptimizedJoinPoint
2608: * @param joinPointIndex
2609: * @param aspectInfo
2610: */
2611: protected void loadAspect(final CodeVisitor cv,
2612: final boolean isOptimizedJoinPoint,
2613: final int joinPointIndex, final AspectInfo aspectInfo) {
2614: DeploymentModel deploymentModel = aspectInfo
2615: .getDeploymentModel();
2616: if (deploymentModel.equals(DeploymentModel.PER_JVM)
2617: || deploymentModel.equals(DeploymentModel.PER_CLASS)) {
2618: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
2619: aspectInfo.getAspectFieldName(), aspectInfo
2620: .getAspectClassSignature());
2621: } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) {
2622: loadJoinPointInstance(cv, isOptimizedJoinPoint,
2623: joinPointIndex);
2624: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2625: aspectInfo.getAspectFieldName(), aspectInfo
2626: .getAspectClassSignature());
2627: } else {
2628: throw new DefinitionException("deployment model ["
2629: + deploymentModel + "] is not supported");
2630: }
2631: }
2632:
2633: /**
2634: * Creates an invocation to Aspects.aspectOf(..).
2635: *
2636: * @param cv
2637: * @param isOptimizedJoinPoint
2638: * @param joinPointIndex
2639: * @param callerIndex
2640: * @param calleeIndex
2641: * @param aspectInfo
2642: */
2643: public void createInvocationToAspectOf(final CodeVisitor cv,
2644: final boolean isOptimizedJoinPoint,
2645: final int joinPointIndex, final int callerIndex,
2646: final int calleeIndex, final AspectInfo aspectInfo) {
2647: if (aspectInfo.getDeploymentModel() == DeploymentModel.PER_INSTANCE) {
2648:
2649: //generates code: aspectField = (cast) Aspects.aspect$Of(aspectQN, containerClassName, callee)
2650: loadJoinPointInstance(cv, isOptimizedJoinPoint,
2651: joinPointIndex);
2652: cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
2653: if (calleeIndex >= 0) {
2654: cv.visitVarInsn(ALOAD, calleeIndex);
2655: cv.visitLdcInsn(aspectInfo.getAspectDefinition()
2656: .getContainerClassName());
2657: cv.visitMethodInsn(INVOKESTATIC, ASPECTS_CLASS_NAME,
2658: ASPECT_OF_METHOD_NAME,
2659: ASPECT_OF_PER_INSTANCE_METHOD_SIGNATURE);
2660: } else {
2661: // TODO: should this really happen? we are filtering at early stage now. - REMOVE CODE BLOCK
2662: // fallback to perClass
2663: //aspectField = (cast) Aspects.aspectOf(aspectQN, containerClass, calleeClass)
2664: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
2665: TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2666: cv.visitLdcInsn(aspectInfo.getAspectDefinition()
2667: .getContainerClassName());
2668: cv.visitMethodInsn(INVOKESTATIC, ASPECTS_CLASS_NAME,
2669: ASPECT_OF_METHOD_NAME,
2670: ASPECT_OF_PER_CLASS_METHOD_SIGNATURE);
2671: }
2672: cv
2673: .visitTypeInsn(CHECKCAST, aspectInfo
2674: .getAspectClassName());
2675: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2676: aspectInfo.getAspectFieldName(), aspectInfo
2677: .getAspectClassSignature());
2678: }
2679: }
2680:
2681: /**
2682: * Generates code needed for handling Advisable management for the target class.
2683: *
2684: * @param cv
2685: * @param joinPointInstanceIndex
2686: * @param advisableIndex
2687: */
2688: private void createInitializationForAdvisableManagement(
2689: final CodeVisitor cv, final int joinPointInstanceIndex,
2690: final int advisableIndex) {
2691: // interceptor index
2692: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2693: cv.visitInsn(ICONST_M1);
2694: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2695: INTERCEPTOR_INDEX_FIELD_NAME, I);
2696:
2697: initializeAroundInterceptors(cv, joinPointInstanceIndex,
2698: advisableIndex);
2699: initializeBeforeInterceptors(cv, joinPointInstanceIndex,
2700: advisableIndex);
2701: initializeAfterInterceptors(cv, joinPointInstanceIndex,
2702: advisableIndex);
2703: initializeAfterReturningInterceptors(cv,
2704: joinPointInstanceIndex, advisableIndex);
2705: initializeAfterThrowingInterceptors(cv, joinPointInstanceIndex,
2706: advisableIndex);
2707: }
2708:
2709: /**
2710: * Handle the around interceptor init.
2711: *
2712: * @param cv
2713: * @param joinPointInstanceIndex
2714: * @param advisableIndex
2715: */
2716: private void initializeAroundInterceptors(final CodeVisitor cv,
2717: final int joinPointInstanceIndex, final int advisableIndex) {
2718: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2719: cv.visitVarInsn(ALOAD, advisableIndex);
2720: cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2721: cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2722: cv.visitMethodInsn(INVOKEINTERFACE, ADVISABLE_CLASS_NAME,
2723: GET_AROUND_ADVICE_METHOD_NAME,
2724: GET_AROUND_ADVICE_METHOD_SIGNATURE);
2725: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2726: AROUND_INTERCEPTORS_FIELD_NAME,
2727: AROUND_ADVICE_ARRAY_CLASS_SIGNATURE);
2728:
2729: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2730: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2731: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2732: AROUND_INTERCEPTORS_FIELD_NAME,
2733: AROUND_ADVICE_ARRAY_CLASS_SIGNATURE);
2734: cv.visitInsn(ARRAYLENGTH);
2735: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2736: NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2737: }
2738:
2739: /**
2740: * Handle the before interceptor init.
2741: *
2742: * @param cv
2743: * @param joinPointInstanceIndex
2744: * @param advisableIndex
2745: */
2746: private void initializeBeforeInterceptors(final CodeVisitor cv,
2747: final int joinPointInstanceIndex, final int advisableIndex) {
2748: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2749: cv.visitVarInsn(ALOAD, advisableIndex);
2750: cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2751: cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2752: cv.visitMethodInsn(INVOKEINTERFACE, ADVISABLE_CLASS_NAME,
2753: GET_BEFORE_ADVICE_METHOD_NAME,
2754: GET_BEFORE_ADVICE_METHOD_SIGNATURE);
2755: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2756: BEFORE_INTERCEPTORS_FIELD_NAME,
2757: BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE);
2758:
2759: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2760: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2761: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2762: BEFORE_INTERCEPTORS_FIELD_NAME,
2763: BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE);
2764: cv.visitInsn(ARRAYLENGTH);
2765: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2766: NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2767: }
2768:
2769: /**
2770: * Handle the after finally interceptor init.
2771: *
2772: * @param cv
2773: * @param joinPointInstanceIndex
2774: * @param advisableIndex
2775: */
2776: private void initializeAfterInterceptors(final CodeVisitor cv,
2777: final int joinPointInstanceIndex, final int advisableIndex) {
2778: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2779: cv.visitVarInsn(ALOAD, advisableIndex);
2780: cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2781: cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2782: cv.visitMethodInsn(INVOKEINTERFACE, ADVISABLE_CLASS_NAME,
2783: GET_AFTER_ADVICE_METHOD_NAME,
2784: GET_AFTER_ADVICE_METHOD_SIGNATURE);
2785: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2786: AFTER_INTERCEPTORS_FIELD_NAME,
2787: AFTER_ADVICE_ARRAY_CLASS_SIGNATURE);
2788:
2789: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2790: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2791: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2792: AFTER_INTERCEPTORS_FIELD_NAME,
2793: AFTER_ADVICE_ARRAY_CLASS_SIGNATURE);
2794: cv.visitInsn(ARRAYLENGTH);
2795: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2796: NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2797: }
2798:
2799: /**
2800: * Handle the after returning interceptor init.
2801: *
2802: * @param cv
2803: * @param joinPointInstanceIndex
2804: * @param advisableIndex
2805: */
2806: private void initializeAfterReturningInterceptors(
2807: final CodeVisitor cv, final int joinPointInstanceIndex,
2808: final int advisableIndex) {
2809: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2810: cv.visitVarInsn(ALOAD, advisableIndex);
2811: cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2812: cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2813: cv.visitMethodInsn(INVOKEINTERFACE, ADVISABLE_CLASS_NAME,
2814: GET_AFTER_RETURNING_ADVICE_METHOD_NAME,
2815: GET_AFTER_RETURNING_ADVICE_METHOD_SIGNATURE);
2816: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2817: AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2818: AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE);
2819:
2820: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2821: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2822: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2823: AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2824: AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE);
2825: cv.visitInsn(ARRAYLENGTH);
2826: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2827: NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2828: }
2829:
2830: /**
2831: * Handle the after throwing interceptor init.
2832: *
2833: * @param cv
2834: * @param joinPointInstanceIndex
2835: * @param advisableIndex
2836: */
2837: private void initializeAfterThrowingInterceptors(
2838: final CodeVisitor cv, final int joinPointInstanceIndex,
2839: final int advisableIndex) {
2840: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2841: cv.visitVarInsn(ALOAD, advisableIndex);
2842: cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2843: cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2844: cv.visitMethodInsn(INVOKEINTERFACE, ADVISABLE_CLASS_NAME,
2845: GET_AFTER_THROWING_ADVICE_METHOD_NAME,
2846: GET_AFTER_THROWING_ADVICE_METHOD_SIGNATURE);
2847: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2848: AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2849: AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE);
2850:
2851: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2852: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2853: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2854: AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2855: AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE);
2856: cv.visitInsn(ARRAYLENGTH);
2857: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2858: NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2859: }
2860:
2861: /**
2862: * Handles the around interceptor invocations.
2863: *
2864: * @param cv
2865: */
2866: private void createAroundInterceptorInvocations(final CodeVisitor cv) {
2867: cv.visitVarInsn(ALOAD, 0);
2868: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2869: INTERCEPTOR_INDEX_FIELD_NAME, I);
2870: cv.visitInsn(ICONST_M1);
2871: Label ifStatementLabel = new Label();
2872: cv.visitJumpInsn(IF_ICMPEQ, ifStatementLabel);
2873: cv.visitVarInsn(ALOAD, 0);
2874: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2875: INTERCEPTOR_INDEX_FIELD_NAME, I);
2876: cv.visitVarInsn(ALOAD, 0);
2877: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2878: NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2879: cv.visitJumpInsn(IF_ICMPGE, ifStatementLabel);
2880: cv.visitVarInsn(ALOAD, 0);
2881: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2882: AROUND_INTERCEPTORS_FIELD_NAME,
2883: AROUND_ADVICE_ARRAY_CLASS_SIGNATURE);
2884: cv.visitVarInsn(ALOAD, 0);
2885: cv.visitInsn(DUP);
2886: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2887: INTERCEPTOR_INDEX_FIELD_NAME, I);
2888: cv.visitInsn(DUP_X1);
2889: cv.visitInsn(ICONST_1);
2890: cv.visitInsn(IADD);
2891: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2892: INTERCEPTOR_INDEX_FIELD_NAME, I);
2893: cv.visitInsn(AALOAD);
2894: cv.visitVarInsn(ALOAD, 0);
2895: cv.visitMethodInsn(INVOKEINTERFACE, AROUND_ADVICE_CLASS_NAME,
2896: INTERCEPT_INVOKE_METHOD_NAME,
2897: AROUND_ADVICE_INVOKE_METHOD_SIGNATURE);
2898: cv.visitInsn(ARETURN);
2899: cv.visitLabel(ifStatementLabel);
2900: }
2901:
2902: /**
2903: * Creates invocations fo the before interceptors.
2904: *
2905: * @param cv
2906: * @param joinPointInstanceIndex
2907: * @param registerDepth
2908: */
2909: private void createBeforeInterceptorInvocations(
2910: final CodeVisitor cv, final int joinPointInstanceIndex,
2911: final int registerDepth) {
2912: final int loopIndex = registerDepth + 1;
2913: cv.visitInsn(ICONST_0);
2914: cv.visitVarInsn(ISTORE, loopIndex);
2915: Label loopStartLabel = new Label();
2916: cv.visitLabel(loopStartLabel);
2917: cv.visitVarInsn(ILOAD, loopIndex);
2918: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2919: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2920: NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2921: Label loopCheckCondLabel = new Label();
2922: cv.visitJumpInsn(IF_ICMPGE, loopCheckCondLabel);
2923: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2924: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2925: BEFORE_INTERCEPTORS_FIELD_NAME,
2926: BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE);
2927: cv.visitVarInsn(ILOAD, loopIndex);
2928: cv.visitInsn(AALOAD);
2929: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2930: cv.visitMethodInsn(INVOKEINTERFACE, BEFORE_ADVICE_CLASS_NAME,
2931: INTERCEPT_INVOKE_METHOD_NAME,
2932: BEFORE_ADVICE_INVOKE_METHOD_SIGNATURE);
2933: cv.visitIincInsn(loopIndex, 1);
2934: cv.visitJumpInsn(GOTO, loopStartLabel);
2935: cv.visitLabel(loopCheckCondLabel);
2936: }
2937:
2938: /**
2939: * Creates invocations fo the after finally interceptors.
2940: *
2941: * @param cv
2942: * @param joinPointInstanceIndex
2943: * @param registerDepth
2944: */
2945: private void createAfterInterceptorInvocations(
2946: final CodeVisitor cv, final int joinPointInstanceIndex,
2947: final int registerDepth) {
2948: final int loopIndex = registerDepth + 1;
2949: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2950: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2951: NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2952: cv.visitInsn(ICONST_1);
2953: cv.visitInsn(ISUB);
2954: cv.visitVarInsn(ISTORE, loopIndex);
2955: Label loopLabel1 = new Label();
2956: cv.visitLabel(loopLabel1);
2957: cv.visitVarInsn(ILOAD, loopIndex);
2958: Label loopLabel2 = new Label();
2959: cv.visitJumpInsn(IFLT, loopLabel2);
2960: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2961: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2962: AFTER_INTERCEPTORS_FIELD_NAME,
2963: AFTER_ADVICE_ARRAY_CLASS_SIGNATURE);
2964: cv.visitVarInsn(ILOAD, loopIndex);
2965: cv.visitInsn(AALOAD);
2966: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2967: cv.visitMethodInsn(INVOKEINTERFACE, AFTER_ADVICE_CLASS_NAME,
2968: INTERCEPT_INVOKE_METHOD_NAME,
2969: AFTER_ADVICE_INVOKE_METHOD_SIGNATURE);
2970: cv.visitIincInsn(loopIndex, -1);
2971: cv.visitJumpInsn(GOTO, loopLabel1);
2972: cv.visitLabel(loopLabel2);
2973: }
2974:
2975: /**
2976: * Creates invocations fo the after returning interceptors.
2977: *
2978: * @param cv
2979: * @param joinPointInstanceIndex
2980: * @param returnValueInstanceIndex
2981: */
2982: private void createAfterReturningInterceptorInvocations(
2983: final CodeVisitor cv, final int joinPointInstanceIndex,
2984: final int returnValueInstanceIndex) {
2985: final int loopIndex = returnValueInstanceIndex + 1;
2986: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2987: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2988: NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2989: cv.visitInsn(ICONST_1);
2990: cv.visitInsn(ISUB);
2991: cv.visitVarInsn(ISTORE, loopIndex);
2992: Label loopLabel1 = new Label();
2993: cv.visitLabel(loopLabel1);
2994: cv.visitVarInsn(ILOAD, loopIndex);
2995: Label loopLabel2 = new Label();
2996: cv.visitJumpInsn(IFLT, loopLabel2);
2997: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2998: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2999: AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
3000: AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE);
3001: cv.visitVarInsn(ILOAD, loopIndex);
3002: cv.visitInsn(AALOAD);
3003: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
3004: cv.visitVarInsn(ALOAD, returnValueInstanceIndex);
3005: cv.visitMethodInsn(INVOKEINTERFACE,
3006: AFTER_RETURNING_ADVICE_CLASS_NAME,
3007: INTERCEPT_INVOKE_METHOD_NAME,
3008: AFTER_RETURNING_ADVICE_INVOKE_METHOD_SIGNATURE);
3009: cv.visitIincInsn(loopIndex, -1);
3010: cv.visitJumpInsn(GOTO, loopLabel1);
3011: cv.visitLabel(loopLabel2);
3012: }
3013:
3014: /**
3015: * Creates invocations fo the after returning interceptors.
3016: *
3017: * @param cv
3018: * @param joinPointInstanceIndex
3019: * @param exceptionInstanceIndex
3020: */
3021: private void createAfterThrowingInterceptorInvocations(
3022: final CodeVisitor cv, final int joinPointInstanceIndex,
3023: final int exceptionInstanceIndex) {
3024: final int loopIndex = exceptionInstanceIndex + 1;
3025: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
3026: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
3027: NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
3028: cv.visitInsn(ICONST_1);
3029: cv.visitInsn(ISUB);
3030: cv.visitVarInsn(ISTORE, loopIndex);
3031: Label loopLabel1 = new Label();
3032: cv.visitLabel(loopLabel1);
3033: cv.visitVarInsn(ILOAD, loopIndex);
3034: Label loopLabel2 = new Label();
3035: cv.visitJumpInsn(IFLT, loopLabel2);
3036: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
3037: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
3038: AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
3039: AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE);
3040: cv.visitVarInsn(ILOAD, loopIndex);
3041: cv.visitInsn(AALOAD);
3042: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
3043: cv.visitVarInsn(ALOAD, exceptionInstanceIndex);
3044: cv.visitMethodInsn(INVOKEINTERFACE,
3045: AFTER_THROWING_ADVICE_CLASS_NAME,
3046: INTERCEPT_INVOKE_METHOD_NAME,
3047: AFTER_THROWING_ADVICE_INVOKE_METHOD_SIGNATURE);
3048: cv.visitIincInsn(loopIndex, -1);
3049: cv.visitJumpInsn(GOTO, loopLabel1);
3050: cv.visitLabel(loopLabel2);
3051: }
3052:
3053: /**
3054: * Checks if the join point requires a proceed() method.
3055: *
3056: * @return
3057: */
3058: protected boolean requiresProceedMethod() {
3059: return m_hasAroundAdvices || m_isThisAdvisable;
3060: }
3061:
3062: private static class CustomProceedMethodStruct {
3063: MethodInfo customProceed;
3064: int[] adviceToTargetArgs;
3065:
3066: public CustomProceedMethodStruct(MethodInfo customProceed,
3067: int[] adviceToTargetArgs) {
3068: this.customProceed = customProceed;
3069: this.adviceToTargetArgs = adviceToTargetArgs;
3070: }
3071: }
3072: }
|