KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > transform > inlining > compiler > AbstractJoinPointCompiler


1 /**************************************************************************************
2  * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
3  * http://aspectwerkz.codehaus.org *
4  * ---------------------------------------------------------------------------------- *
5  * The software in this package is published under the terms of the LGPL license *
6  * a copy of which has been included with this distribution in the license.txt file. *
7  **************************************************************************************/

8 package org.codehaus.aspectwerkz.transform.inlining.compiler;
9
10 import org.objectweb.asm.ClassWriter;
11 import org.objectweb.asm.CodeVisitor;
12 import org.objectweb.asm.Constants;
13 import org.objectweb.asm.Label;
14 import org.objectweb.asm.Type;
15
16 import org.codehaus.aspectwerkz.DeploymentModel;
17 import org.codehaus.aspectwerkz.cflow.CflowCompiler;
18 import org.codehaus.aspectwerkz.reflect.ClassInfo;
19 import org.codehaus.aspectwerkz.reflect.ClassInfoHelper;
20 import org.codehaus.aspectwerkz.reflect.MethodInfo;
21 import org.codehaus.aspectwerkz.reflect.ReflectionInfo;
22 import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo;
23 import org.codehaus.aspectwerkz.aspect.AdviceInfo;
24 import org.codehaus.aspectwerkz.exception.DefinitionException;
25 import org.codehaus.aspectwerkz.aspect.AdviceType;
26 import org.codehaus.aspectwerkz.definition.AspectDefinition;
27 import org.codehaus.aspectwerkz.transform.Compiler;
28 import org.codehaus.aspectwerkz.transform.TransformationConstants;
29 import org.codehaus.aspectwerkz.transform.inlining.EmittedJoinPoint;
30 import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
31 import org.codehaus.aspectwerkz.transform.inlining.AdviceMethodInfo;
32 import org.codehaus.aspectwerkz.transform.inlining.AspectInfo;
33 import org.codehaus.aspectwerkz.transform.inlining.AspectModelManager;
34 import org.codehaus.aspectwerkz.transform.inlining.spi.AspectModel;
35 import org.codehaus.aspectwerkz.joinpoint.management.JoinPointType;
36 import org.codehaus.aspectwerkz.joinpoint.management.AdviceInfoContainer;
37
38 import java.lang.reflect.InvocationTargetException JavaDoc;
39 import java.lang.reflect.Modifier JavaDoc;
40 import java.util.Iterator JavaDoc;
41 import java.util.ArrayList JavaDoc;
42 import java.util.List JavaDoc;
43 import java.util.Set JavaDoc;
44 import java.util.HashSet JavaDoc;
45 import java.util.HashMap JavaDoc;
46 import java.util.Map JavaDoc;
47
48 /**
49  * Abstract base class for the different join point compiler implementations.
50  * <p/>
51  * Compiles/generates a class that represents a specific join point, a class which invokes the advices
52  * and the target join point statically.
53  * <p/>
54  * FIXME: depending on hotswap needs, remove the implements StaticJP or JP decision
55  * FIXME: remove isOptimizedJP and put it global
56  *
57  * @author <a HREF="mailto:jboner@codehaus.org">Jonas BonŽr </a>
58  * @author <a HREF="mailto:alex AT gnilux DOT com">Alexandre Vasseur </a>
59  * @author <a HREF="mailto:the_mindstorm@evolva.ro">Alex Popescu</a>
60  */

61 public abstract class AbstractJoinPointCompiler implements Compiler JavaDoc, TransformationConstants {
62
63     protected static final String JavaDoc TARGET_CLASS_FIELD_NAME = "TARGET_CLASS";
64     protected static final String JavaDoc THIS_CLASS_FIELD_NAME = "THIS_CLASS";
65
66     // FIXME define these two using VM option - if dump dir specified then dump
67
public static final boolean DUMP_JIT_CLASSES = false;
68     protected static final String JavaDoc DUMP_DIR = "_dump";
69
70     protected final String JavaDoc m_callerClassName;
71     protected final String JavaDoc m_calleeClassName;
72     protected final String JavaDoc m_callerClassSignature;
73     protected final String JavaDoc m_calleeClassSignature;
74     protected final String JavaDoc m_joinPointClassName;
75     protected final int m_joinPointType;
76     protected final int m_joinPointHash;
77     protected final String JavaDoc m_callerMethodName;
78     protected final String JavaDoc m_callerMethodDesc;
79     protected final int m_callerMethodModifiers;
80     protected final String JavaDoc m_calleeMemberName;
81     protected final String JavaDoc m_calleeMemberDesc;
82     protected final int m_calleeMemberModifiers;
83
84     protected ClassWriter m_cw;
85     protected AspectInfo[] m_aspectInfos;
86     protected AspectModel[] m_aspectModels;
87     protected AdviceMethodInfo[] m_aroundAdviceMethodInfos;
88     protected AdviceMethodInfo[] m_beforeAdviceMethodInfos;
89     protected AdviceMethodInfo[] m_afterFinallyAdviceMethodInfos;
90     protected AdviceMethodInfo[] m_afterReturningAdviceMethodInfos;
91     protected AdviceMethodInfo[] m_afterThrowingAdviceMethodInfos;
92     protected final List JavaDoc m_customProceedMethodStructs = new ArrayList JavaDoc();
93
94     protected boolean m_hasAroundAdvices = false;
95     protected boolean m_requiresThisOrTarget = false;
96     protected boolean m_requiresJoinPoint = false;
97
98     protected String JavaDoc[] m_fieldNames;
99     protected Type[] m_argumentTypes;
100     protected Type m_returnType;
101     protected boolean m_isThisAdvisable = false;
102
103     /**
104      * Creates a new join point compiler instance.
105      *
106      * @param model the compilation model
107      */

108     public AbstractJoinPointCompiler(final CompilationInfo.Model model) {
109         m_joinPointClassName = model.getJoinPointClassName();
110
111         final EmittedJoinPoint emittedJoinPoint = model.getEmittedJoinPoint();
112
113         m_joinPointHash = emittedJoinPoint.getJoinPointHash();
114         m_joinPointType = emittedJoinPoint.getJoinPointType();
115
116         m_callerMethodName = emittedJoinPoint.getCallerMethodName();
117         m_callerMethodDesc = emittedJoinPoint.getCallerMethodDesc();
118         m_callerMethodModifiers = emittedJoinPoint.getCallerMethodModifiers();
119
120         m_calleeMemberName = emittedJoinPoint.getCalleeMemberName();
121         m_calleeMemberDesc = emittedJoinPoint.getCalleeMemberDesc();
122         m_calleeMemberModifiers = emittedJoinPoint.getCalleeMemberModifiers();
123
124         // NOTE: internal compiler class name format is ALWAYS using '/'
125
m_callerClassName = emittedJoinPoint.getCallerClassName().replace('.', '/');
126         m_calleeClassName = emittedJoinPoint.getCalleeClassName().replace('.', '/');
127         m_callerClassSignature = L + emittedJoinPoint.getCallerClassName().replace('.', '/') + SEMICOLON;
128         m_calleeClassSignature = L + emittedJoinPoint.getCalleeClassName().replace('.', '/') + SEMICOLON;
129
130         m_argumentTypes = getJoinPointArgumentTypes();
131         m_returnType = getJoinPointReturnType();
132
133         initialize(model);
134     }
135
136     /**
137      * Initializes the the join point compiler.
138      *
139      * @param model the compilation model
140      */

141     private synchronized void initialize(final CompilationInfo.Model model) {
142         // check if 'target' is Advisable, e.g. can handle runtime per instance deployment
143
checkIfThisIsAdvisable(model);
144
145         // create the aspect fields
146
final AdviceInfoContainer advices = model.getAdviceInfoContainer();
147
148         collectAdviceInfo(advices);
149         collectCustomProceedMethods(model, advices);
150
151         // compute the optimization we can use
152
m_hasAroundAdvices = m_aroundAdviceMethodInfos.length > 0;
153         m_requiresThisOrTarget = requiresThisOrTarget();
154         m_requiresJoinPoint = requiresJoinPoint();
155
156         // setup models at the end so that they can override m_requiresJoinPoint
157
setupReferencedAspectModels();
158
159         m_cw = AsmHelper.newClassWriter(true);
160     }
161
162     /**
163      * Collects the advice info.
164      *
165      * @param advices
166      */

167     private void collectAdviceInfo(final AdviceInfoContainer advices) {
168         final List JavaDoc aspectQualifiedNames = new ArrayList JavaDoc();// in fact a Set but we need indexOf
169
final Set JavaDoc aspectInfos = new HashSet JavaDoc();
170         m_beforeAdviceMethodInfos = getAdviceMethodInfos(
171                 aspectQualifiedNames, aspectInfos, advices.getBeforeAdviceInfos()
172         );
173         m_aroundAdviceMethodInfos = getAdviceMethodInfos(
174                 aspectQualifiedNames, aspectInfos, advices.getAroundAdviceInfos()
175         );
176         m_afterReturningAdviceMethodInfos = getAdviceMethodInfos(
177                 aspectQualifiedNames, aspectInfos, advices.getAfterReturningAdviceInfos()
178         );
179         m_afterFinallyAdviceMethodInfos = getAdviceMethodInfos(
180                 aspectQualifiedNames, aspectInfos, advices.getAfterFinallyAdviceInfos()
181         );
182         m_afterThrowingAdviceMethodInfos = getAdviceMethodInfos(
183                 aspectQualifiedNames, aspectInfos, advices.getAfterThrowingAdviceInfos()
184         );
185
186         m_aspectInfos = (AspectInfo[]) aspectInfos.toArray(new AspectInfo[aspectInfos.size()]);
187     }
188
189     /**
190      * Collects the custom proceed methods used in the advice specified.
191      *
192      * @param model
193      * @param advices
194      */

195     private void collectCustomProceedMethods(final CompilationInfo.Model model,
196                                              final AdviceInfoContainer advices) {
197         ClassLoader JavaDoc loader = model.getThisClassInfo().getClassLoader();
198         final AdviceInfo[] beforeAdviceInfos = advices.getBeforeAdviceInfos();
199         for (int i = 0; i < beforeAdviceInfos.length; i++) {
200             collectCustomProceedMethods(beforeAdviceInfos[i], loader);
201         }
202         final AdviceInfo[] aroundAdviceInfos = advices.getAroundAdviceInfos();
203         for (int i = 0; i < aroundAdviceInfos.length; i++) {
204             collectCustomProceedMethods(aroundAdviceInfos[i], loader);
205         }
206         final AdviceInfo[] afterFinallyAdviceInfos = advices.getAfterFinallyAdviceInfos();
207         for (int i = 0; i < afterFinallyAdviceInfos.length; i++) {
208             collectCustomProceedMethods(afterFinallyAdviceInfos[i], loader);
209         }
210         final AdviceInfo[] afterReturningAdviceInfos = advices.getAfterReturningAdviceInfos();
211         for (int i = 0; i < afterReturningAdviceInfos.length; i++) {
212             collectCustomProceedMethods(afterReturningAdviceInfos[i], loader);
213         }
214         final AdviceInfo[] afterThrowingAdviceInfos = advices.getAfterThrowingAdviceInfos();
215         for (int i = 0; i < afterThrowingAdviceInfos.length; i++) {
216             collectCustomProceedMethods(afterThrowingAdviceInfos[i], loader);
217         }
218     }
219
220     /**
221      * Collects the custom proceed methods used in the advice specified.
222      *
223      * @param adviceInfo
224      * @param loader
225      */

226     private void collectCustomProceedMethods(final AdviceInfo adviceInfo, final ClassLoader JavaDoc loader) {
227         final Type[] paramTypes = adviceInfo.getMethodParameterTypes();
228         if (paramTypes.length != 0) {
229             Type firstParam = paramTypes[0];
230             //TODO should we support JP at other positions or lock the other advice models then so that JP..
231
// ..is not there or first only ?
232
// check if first param is an object but not a JP or SJP
233
if (firstParam.getSort() == Type.OBJECT &&
234                 !firstParam.getClassName().equals(JOIN_POINT_JAVA_CLASS_NAME) &&
235                 !firstParam.getClassName().equals(STATIC_JOIN_POINT_JAVA_CLASS_NAME)) {
236                 ClassInfo classInfo = AsmClassInfo.getClassInfo(firstParam.getClassName(), loader);
237                 if (ClassInfoHelper.implementsInterface(classInfo, JOIN_POINT_JAVA_CLASS_NAME) ||
238                     ClassInfoHelper.implementsInterface(classInfo, STATIC_JOIN_POINT_JAVA_CLASS_NAME)) {
239                     // we have ourselves a custom joinpoint
240
MethodInfo[] methods = classInfo.getMethods();
241                     for (int j = 0; j < methods.length; j++) {
242                         MethodInfo method = methods[j];
243                         if (method.getName().equals(PROCEED_METHOD_NAME)) {
244                             // we inherit the binding from the advice that actually use us
245
// for now the first advice sets the rule
246
// it is up to the user to ensure consistency if the custom proceed
247
// is used more than once in different advices.
248
m_customProceedMethodStructs.add(new CustomProceedMethodStruct(
249                                     method,
250                                     adviceInfo.getMethodToArgIndexes()
251                             ));
252                         }
253                     }
254                 }
255             }
256         }
257     }
258
259     /**
260      * Checks if the this class implements the Advisable interface.
261      *
262      * @param model
263      */

264     private void checkIfThisIsAdvisable(final CompilationInfo.Model model) {
265         if (!Modifier.isStatic(m_callerMethodModifiers)) {
266             ClassInfo[] interfaces = model.getThisClassInfo().getInterfaces();
267             for (int i = 0; i < interfaces.length; i++) {
268                 if (interfaces[i].getName().equals(ADVISABLE_CLASS_JAVA_NAME)) {
269                     m_isThisAdvisable = true;
270                     break;
271                 }
272             }
273         }
274     }
275
276     /**
277      * Retrives and sets the aspect models that are referenced in this compilation phase.
278      */

279     private void setupReferencedAspectModels() {
280         Map JavaDoc aspectModelMap = new HashMap JavaDoc();
281         for (int i = 0; i < m_aspectInfos.length; i++) {
282             AspectDefinition aspectDef = m_aspectInfos[i].getAspectDefinition();
283             if (aspectDef.isAspectWerkzAspect()) {
284                 continue; // AW Aspect Model not managed by AspectModelManager
285
}
286             String JavaDoc type = aspectDef.getAspectModel();
287             AspectModel aspectModel = AspectModelManager.getModelFor(type);
288             aspectModelMap.put(type, aspectModel);
289             if (aspectModel.requiresReflectiveInfo()) {
290                 m_requiresJoinPoint = true; // if at least one model requries RTTI then build it
291
}
292         }
293         m_aspectModels = (AspectModel[]) aspectModelMap.values().toArray(new AspectModel[aspectModelMap.size()]);
294     }
295
296     /**
297      * Returns the join point interface class name.
298      *
299      * @return
300      */

301     private String JavaDoc getJoinPointInterface() {
302         String JavaDoc joinPointInterface;
303         if (requiresProceedMethod() || m_requiresJoinPoint) {
304             joinPointInterface = JOIN_POINT_CLASS_NAME;
305         } else {
306             joinPointInterface = STATIC_JOIN_POINT_CLASS_NAME;
307         }
308         return joinPointInterface;
309     }
310
311     /**
312      * Retrieves the advice method infos.
313      *
314      * @param aspectQualifiedNames
315      * @param aspectInfos
316      * @param adviceInfos
317      * @return
318      */

319     protected AdviceMethodInfo[] getAdviceMethodInfos(final List JavaDoc aspectQualifiedNames,
320                                                       final Set JavaDoc aspectInfos,
321                                                       final AdviceInfo[] adviceInfos) {
322         List JavaDoc adviceMethodInfosSet = new ArrayList JavaDoc();
323         for (int i = 0; i < adviceInfos.length; i++) {
324             AdviceInfo adviceInfo = adviceInfos[i];
325
326             // if we have a perinstance deployed aspect and a static member CALLER -> skip and go on
327
DeploymentModel deploymentModel = adviceInfo.getAdviceDefinition().getAspectDefinition()
328                     .getDeploymentModel();
329             if (deploymentModel.equals(DeploymentModel.PER_INSTANCE) &&
330                 Modifier.isStatic(m_callerMethodModifiers)) {
331                 continue;
332             }
333
334             final String JavaDoc aspectClassName = adviceInfo.getAspectClassName().replace('.', '/');
335
336             if (!aspectQualifiedNames.contains(adviceInfo.getAspectQualifiedName())) {
337                 aspectQualifiedNames.add(adviceInfo.getAspectQualifiedName());
338             }
339             int aspectIndex = aspectQualifiedNames.indexOf(adviceInfo.getAspectQualifiedName());
340             AdviceMethodInfo adviceMethodInfo = new AdviceMethodInfo(
341                     adviceInfo,
342                     ASPECT_FIELD_PREFIX + aspectIndex,
343                     aspectClassName,
344                     L + aspectClassName + SEMICOLON,
345                     m_callerClassSignature,
346                     m_calleeClassSignature,
347                     m_joinPointClassName,
348                     m_calleeMemberDesc
349             );
350             adviceMethodInfosSet.add(adviceMethodInfo);
351             aspectInfos.add(adviceMethodInfo.getAspectInfo());
352         }
353         return (AdviceMethodInfo[]) adviceMethodInfosSet.toArray(new AdviceMethodInfo[adviceMethodInfosSet.size()]);
354     }
355
356     /**
357      * Creates join point specific fields.
358      */

359     protected abstract void createJoinPointSpecificFields();
360
361     /**
362      * Creates the signature for the join point.
363      *
364      * @param cv
365      */

366     protected abstract void createSignature(final CodeVisitor cv);
367
368     /**
369      * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
370      * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
371      * exists.
372      *
373      * @param cv
374      * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or not)
375      */

376     protected abstract void createInlinedJoinPointInvocation(final CodeVisitor cv,
377                                                              final boolean isOptimizedJoinPoint,
378                                                              final int argStartIndex,
379                                                              final int joinPointIndex);
380
381     /**
382      * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
383      * local join point instance.
384      *
385      * @param cv
386      */

387     protected abstract void createJoinPointInvocation(final CodeVisitor cv);
388
389     /**
390      * Returns the join points return type.
391      *
392      * @return
393      */

394     protected abstract Type getJoinPointReturnType();
395
396     /**
397      * Returns the join points argument type(s).
398      *
399      * @return
400      */

401     protected abstract Type[] getJoinPointArgumentTypes();
402
403     /**
404      * Creates the getRtti method
405      */

406     protected abstract void createGetRttiMethod();
407
408     /**
409      * Creates the getSignature method
410      */

411     protected abstract void createGetSignatureMethod();
412
413     /**
414      * Compiles a join point class, one specific class for each distinct join point. The compiled join point class
415      * inherits the base join point class.
416      *
417      * @return the generated, compiled and loaded join point class
418      */

419     public byte[] compile() {
420         try {
421             // TODO: INNER CLASS OR NOT?
422
// flag it as a public static inner class
423
// Note: if <init> changes, we will need to pass the containing instance as arg0 and add a syntetic field
424
// int innerIndex = m_joinPointClassName.lastIndexOf('$');
425
// m_cw.visitInnerClass(m_joinPointClassName,
426
// m_joinPointClassName.substring(0, innerIndex),
427
// m_joinPointClassName.substring(innerIndex + 1, m_joinPointClassName.length()),
428
// ACC_PUBLIC + ACC_STATIC);
429

430             createClassHeader();
431             createMandatoryMethodInAspectModels();
432             createFieldsCommonToAllJoinPoints();
433             createJoinPointSpecificFields();
434             createStaticInitializer();
435             createClinit();
436             createInit();
437             createUtilityMethods();
438             createCopyMethod();
439             createGetSignatureMethod();
440             createInvokeMethod();
441             if (requiresProceedMethod()) {
442                 createProceedMethod();
443             }
444             if (m_requiresJoinPoint) {
445                 createGetRttiMethod();
446             }
447             createCustomProceedMethods();
448             m_cw.visitEnd();
449
450             if (DUMP_JIT_CLASSES) {
451                 AsmHelper.dumpClass(DUMP_DIR, m_joinPointClassName, m_cw);
452             }
453             return m_cw.toByteArray();
454
455         } catch (Exception JavaDoc e) {
456             e.printStackTrace();
457             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
458             buf.append("could not compile join point instance for join point with hash [");
459             buf.append(m_joinPointHash);
460             buf.append("] and declaring class [");
461             buf.append(m_callerClassName);
462             buf.append("] due to: ");
463             if (e instanceof InvocationTargetException JavaDoc) {
464                 buf.append(((InvocationTargetException JavaDoc) e).getTargetException().toString());
465             } else {
466                 buf.append(e.toString());
467             }
468             throw new RuntimeException JavaDoc(buf.toString());
469         }
470     }
471
472     /**
473      * Creates join point specific fields.
474      */

475     protected void createFieldsCommonToAllJoinPoints() {
476         if (m_returnType.getSort() != Type.VOID) {
477             m_cw.visitField(ACC_PRIVATE, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor(), null, null);
478         }
479         m_cw.visitField(
480                 ACC_PRIVATE + ACC_STATIC,
481                 TARGET_CLASS_FIELD_NAME,
482                 CLASS_CLASS_SIGNATURE,
483                 null,
484                 null
485         );
486         
487         m_cw.visitField(
488                 ACC_PRIVATE + ACC_STATIC + ACC_FINAL,
489                 THIS_CLASS_FIELD_NAME,
490                 CLASS_CLASS_SIGNATURE,
491                 null,
492                 null
493         );
494         
495         m_cw.visitField(
496                 ACC_PRIVATE + ACC_STATIC + ACC_FINAL,
497                 ENCLOSING_SJP_FIELD_NAME,
498                 ENCLOSING_SJP_FIELD_CLASS_SIGNATURE,
499                 null,
500                 null
501         );
502         
503         m_cw.visitField(ACC_PRIVATE + ACC_STATIC, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE, null, null);
504         m_cw.visitField(
505                 ACC_PRIVATE + ACC_STATIC,
506                 OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME,
507                 L + m_joinPointClassName + SEMICOLON,
508                 null, null
509         );
510         m_cw.visitField(ACC_PRIVATE, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature, null, null);
511         m_cw.visitField(ACC_PRIVATE, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature, null, null);
512         m_cw.visitField(ACC_PRIVATE, STACK_FRAME_COUNTER_FIELD_NAME, I, null, null);
513
514         if (m_isThisAdvisable) {
515             m_cw.visitField(ACC_PRIVATE, INTERCEPTOR_INDEX_FIELD_NAME, I, null, null);
516
517             m_cw.visitField(
518                     ACC_PRIVATE, AROUND_INTERCEPTORS_FIELD_NAME,
519                     AROUND_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
520             );
521             m_cw.visitField(ACC_PRIVATE, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I, null, null);
522
523             m_cw.visitField(
524                     ACC_PRIVATE, BEFORE_INTERCEPTORS_FIELD_NAME,
525                     BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
526             );
527             m_cw.visitField(ACC_PRIVATE, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I, null, null);
528
529             m_cw.visitField(
530                     ACC_PRIVATE, AFTER_INTERCEPTORS_FIELD_NAME,
531                     AFTER_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
532             );
533             m_cw.visitField(ACC_PRIVATE, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I, null, null);
534
535             m_cw.visitField(
536                     ACC_PRIVATE, AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
537                     AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
538             );
539             m_cw.visitField(ACC_PRIVATE, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I, null, null);
540
541             m_cw.visitField(
542                     ACC_PRIVATE, AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
543                     AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
544             );
545             m_cw.visitField(ACC_PRIVATE, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I, null, null);
546         }
547     }
548
549     /**
550      * Creates the clinit method for the join point.
551      */

552     protected void createClinit() {
553         CodeVisitor cv = m_cw.visitMethod(ACC_STATIC, CLINIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE, null, null);
554         cv.visitMethodInsn(
555                 INVOKESTATIC, m_joinPointClassName,
556                 STATIC_INITIALIZATION_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE
557         );
558         cv.visitInsn(RETURN);
559         cv.visitMaxs(0, 0);
560     }
561
562     /**
563      * Creates the init method for the join point.
564      */

565     protected void createInit() {
566         CodeVisitor cv = m_cw.visitMethod(ACC_PRIVATE, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE, null, null);
567         cv.visitVarInsn(ALOAD, 0);
568
569         boolean hasAroundClosureBaseClass = false;
570         AspectModel aspectModel = null;
571
572         for (int i = 0; i < m_aspectModels.length; i++) {
573             aspectModel = m_aspectModels[i];
574             if (aspectModel.getAroundClosureClassInfo().getSuperClassName() != null) {
575                 hasAroundClosureBaseClass = true;
576                 break;
577             }
578         }
579
580         if (hasAroundClosureBaseClass) {
581             // invoke the super class constructor
582
aspectModel.createInvocationOfAroundClosureSuperClass(cv);
583         } else {
584             // invoke the constructor of java.lang.Object
585
cv.visitMethodInsn(INVOKESPECIAL, OBJECT_CLASS_NAME, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
586         }
587
588         resetStackFrameCounter(cv);
589
590         cv.visitInsn(RETURN);
591         cv.visitMaxs(0, 0);
592     }
593
594     /**
595      * Creates the class header for the join point.
596      */

597     private void createClassHeader() {
598
599         Set JavaDoc interfaces = new HashSet JavaDoc();
600         String JavaDoc baseClass = OBJECT_CLASS_NAME;
601
602         // get the different aspect models required interfaces
603
for (int i = 0; i < m_aspectModels.length; i++) {
604             AspectModel aspectModel = m_aspectModels[i];
605             AspectModel.AroundClosureClassInfo closureClassInfo = aspectModel.getAroundClosureClassInfo();
606             final String JavaDoc superClassName = closureClassInfo.getSuperClassName();
607             final String JavaDoc[] interfaceNames = closureClassInfo.getInterfaceNames();
608             if (superClassName != null) {
609                 if (!baseClass.equals(OBJECT_CLASS_NAME)) {
610                     throw new RuntimeException JavaDoc(
611                             "compiled join point can only subclass one around closure base class but more than registered aspect model requires a closure base class"
612                     );
613                 }
614                 baseClass = superClassName;
615             }
616             if (interfaceNames.length != 0) {
617                 for (int j = 0; j < interfaceNames.length; j++) {
618                     interfaces.add(interfaceNames[j]);
619                 }
620             }
621         }
622
623         // get the custom join point interfaces
624
for (Iterator JavaDoc it = m_customProceedMethodStructs.iterator(); it.hasNext();) {
625             MethodInfo methodInfo = ((CustomProceedMethodStruct) it.next()).customProceed;
626             interfaces.add(methodInfo.getDeclaringType().getName().replace('.', '/'));
627         }
628
629         int i = 1;
630         String JavaDoc[] interfaceArr = new String JavaDoc[interfaces.size() + 1];
631         interfaceArr[0] = getJoinPointInterface();
632         for (Iterator JavaDoc it = interfaces.iterator(); it.hasNext(); i++) {
633             interfaceArr[i] = (String JavaDoc) it.next();
634         }
635
636         m_cw.visit(
637                 AsmHelper.JAVA_VERSION,
638                 ACC_PUBLIC + ACC_SUPER,
639                 m_joinPointClassName,
640                 baseClass,
641                 interfaceArr,
642                 null
643         );
644     }
645
646     /**
647      * Creates the methods that are mandatory methods in the around closure in the different aspect models.
648      */

649     private void createMandatoryMethodInAspectModels() {
650         for (int i = 0; i < m_aspectModels.length; i++) {
651             m_aspectModels[i].createMandatoryMethods(m_cw, m_joinPointClassName);
652         }
653     }
654
655     /**
656      * Creates the custom proceed methods.
657      */

658     private void createCustomProceedMethods() {
659         Set JavaDoc addedMethodSignatures = new HashSet JavaDoc();
660         for (Iterator JavaDoc it = m_customProceedMethodStructs.iterator(); it.hasNext();) {
661             CustomProceedMethodStruct customProceedStruct = (CustomProceedMethodStruct) it.next();
662             MethodInfo methodInfo = customProceedStruct.customProceed;
663             final String JavaDoc desc = methodInfo.getSignature();
664
665             if (addedMethodSignatures.contains(desc)) {
666                 continue;
667             }
668             addedMethodSignatures.add(desc);
669
670             CodeVisitor cv = m_cw.visitMethod(
671                     ACC_PUBLIC | ACC_FINAL,
672                     PROCEED_METHOD_NAME,
673                     desc,
674                     new String JavaDoc[]{
675                         THROWABLE_CLASS_NAME
676                     },
677                     null
678             );
679
680             // update the joinpoint instance with the given values
681
// starts at 1 since first arg is the custom join point by convention
682
//TODO see JoinPointManage for this custom jp is first convention
683
int argStackIndex = 1;
684             for (int i = 1; i < customProceedStruct.adviceToTargetArgs.length; i++) {
685                 int targetArg = customProceedStruct.adviceToTargetArgs[i];
686                 if (targetArg >= 0) {
687                     // regular arg
688
String JavaDoc fieldName = m_fieldNames[targetArg];
689                     cv.visitVarInsn(ALOAD, 0);
690                     Type type = m_argumentTypes[targetArg];
691                     argStackIndex = AsmHelper.loadType(cv, argStackIndex, type);
692                     cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, fieldName, type.getDescriptor());
693                 } else if (targetArg == AdviceInfo.TARGET_ARG) {
694                     cv.visitVarInsn(ALOAD, 0);
695                     argStackIndex = AsmHelper.loadType(cv, argStackIndex, Type.getType(m_calleeClassSignature));
696                     cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
697                 } else if (targetArg == AdviceInfo.THIS_ARG) {
698                     cv.visitVarInsn(ALOAD, 0);
699                     argStackIndex = AsmHelper.loadType(cv, argStackIndex, Type.getType(m_callerClassSignature));
700                     cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
701                 } else {
702                     ;//skip it
703
}
704             }
705
706             // call proceed()
707
// and handles unwrapping for returning primitive
708
Type returnType = Type.getType(customProceedStruct.customProceed.getReturnType().getSignature());
709             if (AsmHelper.isPrimitive(returnType)) {
710                 cv.visitVarInsn(ALOAD, 0);
711                 cv.visitMethodInsn(
712                         INVOKESPECIAL,
713                         m_joinPointClassName,
714                         PROCEED_METHOD_NAME,
715                         PROCEED_METHOD_SIGNATURE
716                 );
717                 AsmHelper.unwrapType(cv, returnType);
718             } else {
719                 cv.visitVarInsn(ALOAD, 0);
720                 cv.visitMethodInsn(
721                         INVOKESPECIAL,
722                         m_joinPointClassName,
723                         PROCEED_METHOD_NAME,
724                         PROCEED_METHOD_SIGNATURE
725                 );
726                 if (!returnType.getClassName().equals(OBJECT_CLASS_SIGNATURE)) {
727                     cv.visitTypeInsn(CHECKCAST, returnType.getInternalName());
728                 }
729             }
730             AsmHelper.addReturnStatement(cv, returnType);
731             cv.visitMaxs(0, 0);
732         }
733     }
734
735     /**
736      * Creates the static initialization method (not clinit) for the join point.
737      */

738     protected void createStaticInitializer() {
739         CodeVisitor cv = m_cw.visitMethod(
740                 ACC_STATIC | ACC_PUBLIC,
741                 STATIC_INITIALIZATION_METHOD_NAME,
742                 NO_PARAM_RETURN_VOID_SIGNATURE,
743                 null, null
744         );
745
746         Label tryLabel = new Label();
747         cv.visitLabel(tryLabel);
748         cv.visitLdcInsn(m_calleeClassName.replace('/', '.'));
749         cv.visitMethodInsn(INVOKESTATIC, CLASS_CLASS, FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
750         cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
751
752         cv.visitLdcInsn(m_callerClassName.replace('/', '.'));
753         cv.visitMethodInsn(INVOKESTATIC, CLASS_CLASS, FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
754         cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
755         
756         Label finallyLabel = new Label();
757         cv.visitLabel(finallyLabel);
758
759         Label gotoFinallyLabel = new Label();
760         cv.visitJumpInsn(GOTO, gotoFinallyLabel);
761
762         Label catchLabel = new Label();
763         cv.visitLabel(catchLabel);
764         cv.visitVarInsn(ASTORE, 0);
765
766         cv.visitVarInsn(ALOAD, 0);
767         cv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Throwable", "printStackTrace", "()V");
768
769         cv.visitTypeInsn(NEW, RUNTIME_EXCEPTION_CLASS_NAME);
770         cv.visitInsn(DUP);
771         cv.visitLdcInsn("could not load target class using Class.forName() in generated join point base class "
772                         + m_joinPointClassName);
773
774         cv.visitMethodInsn(
775                 INVOKESPECIAL,
776                 RUNTIME_EXCEPTION_CLASS_NAME,
777                 INIT_METHOD_NAME,
778                 RUNTIME_EXCEPTION_INIT_METHOD_SIGNATURE
779         );
780
781         cv.visitInsn(ATHROW);
782         cv.visitLabel(gotoFinallyLabel);
783
784         // create the enclosing static joinpoint
785
createEnclosingStaticJoinPoint(cv);
786         
787         // create the metadata map
788
cv.visitTypeInsn(NEW, HASH_MAP_CLASS_NAME);
789         cv.visitInsn(DUP);
790         cv.visitMethodInsn(INVOKESPECIAL, HASH_MAP_CLASS_NAME, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
791         cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
792
793         // create the Signature instance
794
createSignature(cv);
795
796         // create the static JoinPoint instance
797
cv.visitTypeInsn(NEW, m_joinPointClassName);
798         cv.visitInsn(DUP);
799         cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
800         cv.visitFieldInsn(
801                 PUTSTATIC,
802                 m_joinPointClassName,
803                 OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME,
804                 L + m_joinPointClassName + SEMICOLON
805         );
806
807         // create and initialize the aspect fields
808
for (int i = 0; i < m_aspectInfos.length; i++) {
809             createAndInitializeAspectField(m_aspectInfos[i], cv);
810         }
811
812         cv.visitInsn(RETURN);
813         cv.visitTryCatchBlock(tryLabel, finallyLabel, catchLabel, CLASS_NOT_FOUND_EXCEPTION_CLASS_NAME);
814         cv.visitMaxs(0, 0);
815     }
816
817     /**
818      * Add and initialize the static field for enclosing joint point static part
819      *
820      * @param cv
821      */

822     protected void createEnclosingStaticJoinPoint(CodeVisitor cv) {
823         cv.visitFieldInsn(GETSTATIC,
824                 m_joinPointClassName,
825                 THIS_CLASS_FIELD_NAME,
826                 CLASS_CLASS_SIGNATURE);
827         cv.visitLdcInsn(m_callerMethodName);
828         cv.visitLdcInsn(m_callerMethodDesc);
829
830         cv.visitMethodInsn(INVOKESTATIC,
831                 SIGNATURE_FACTORY_CLASS,
832                 NEW_ENCLOSING_SJP_METHOD_NAME,
833                 NEW_ENCLOSING_SJP_METHOD_SIGNATURE);
834         cv.visitFieldInsn(
835                 PUTSTATIC,
836                 m_joinPointClassName,
837                 ENCLOSING_SJP_FIELD_NAME,
838                 ENCLOSING_SJP_FIELD_CLASS_SIGNATURE);
839     }
840     
841     /**
842      * Create and initialize the aspect field for a specific aspect (qualified since it depends
843      * on the param, deployment model, container etc).
844      *
845      * @param aspectInfo
846      * @param cv
847      */

848     protected boolean createAndInitializeAspectField(final AspectInfo aspectInfo, final CodeVisitor cv) {
849         if (aspectInfo.getAspectDefinition().isAspectWerkzAspect()) {
850             // AW aspect
851
// create the field to host the aspect and retrieve the aspect to set it to the field
852
createAspectReferenceField(m_cw, aspectInfo);
853             createAspectInstantiation(cv, aspectInfo, m_joinPointClassName);
854         } else {
855             // non-AW aspect
856
final String JavaDoc type = aspectInfo.getAspectDefinition().getAspectModel();
857             final AspectModel aspectModel = AspectModelManager.getModelFor(type);
858             aspectModel.createAspectReferenceField(m_cw, aspectInfo, m_joinPointClassName);
859             aspectModel.createAspectInstantiation(cv, aspectInfo, m_joinPointClassName);
860         }
861
862         return false;
863     }
864
865     /**
866      * Creates aspect reference field (static or non static field).
867      *
868      * @param cw
869      * @param aspectInfo
870      */

871     public static void createAspectReferenceField(final ClassWriter cw,
872                                                   final AspectInfo aspectInfo) {
873         String JavaDoc aspectClassSignature = aspectInfo.getAspectClassSignature();
874
875         // create a field depending on the aspect deployment model
876
DeploymentModel deploymentModel = aspectInfo.getDeploymentModel();
877         if (deploymentModel.equals(DeploymentModel.PER_JVM) ||
878             deploymentModel.equals(DeploymentModel.PER_CLASS)) {
879             // add the aspect static field
880
cw.visitField(ACC_PRIVATE + ACC_STATIC, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null);
881         } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) {
882             // add the aspect field as a non static field
883
//TODO - may bee skip the aspect and all its advice is target is static, or ctor call
884
//that is no instance available
885
cw.visitField(ACC_PRIVATE, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null);
886         } else {
887             throw new UnsupportedOperationException JavaDoc(
888                     "unsupported deployment model - " +
889                     aspectInfo.getAspectClassName() + " " +
890                     deploymentModel
891             );
892         }
893     }
894
895     /**
896      * Creates instantiation of aspects using the Aspects.aspectOf() methods which uses the AspectContainer impls.
897      * We are using the THIS_CLASS classloader since the aspect can be visible from that one only f.e. for get/set/call
898      *
899      * @param cv
900      * @param aspectInfo
901      * @param joinPointClassName
902      */

903     public static void createAspectInstantiation(final CodeVisitor cv,
904                                                  final AspectInfo aspectInfo,
905                                                  final String JavaDoc joinPointClassName) {
906         String JavaDoc aspectClassSignature = aspectInfo.getAspectClassSignature();
907         String JavaDoc aspectClassName = aspectInfo.getAspectClassName();
908         // retrieve the aspect set it to the field
909
DeploymentModel deploymentModel = aspectInfo.getDeploymentModel();
910         if (CflowCompiler.isCflowClass(aspectClassName)) {
911             // handle Cflow native aspectOf
912
cv.visitMethodInsn(
913                     INVOKESTATIC,
914                     aspectClassName,
915                     CflowCompiler.CFLOW_ASPECTOF_METHOD_NAME,
916                     "()"+aspectClassSignature
917             );
918             cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature);
919         } else if (deploymentModel.equals(DeploymentModel.PER_JVM)) {
920             // AW-355, AW-415 we need a ClassLoader here
921
cv.visitFieldInsn(GETSTATIC, joinPointClassName, THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
922             cv.visitMethodInsn(
923                     INVOKEVIRTUAL, CLASS_CLASS, GETCLASSLOADER_METHOD_NAME,
924                     CLASS_CLASS_GETCLASSLOADER_METHOD_SIGNATURE
925             );
926             cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
927             cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
928             cv.visitMethodInsn(
929                     INVOKESTATIC,
930                     ASPECTS_CLASS_NAME,
931                     ASPECT_OF_METHOD_NAME,
932                     ASPECT_OF_PER_JVM_METHOD_SIGNATURE
933             );
934             cv.visitTypeInsn(CHECKCAST, aspectClassName);
935             cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature);
936         } else if (deploymentModel.equals(DeploymentModel.PER_CLASS)) {
937             cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
938             cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
939             cv.visitFieldInsn(GETSTATIC, joinPointClassName, THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
940             cv.visitMethodInsn(
941                     INVOKESTATIC,
942                     ASPECTS_CLASS_NAME,
943                     ASPECT_OF_METHOD_NAME,
944                     ASPECT_OF_PER_CLASS_METHOD_SIGNATURE
945             );
946             cv.visitTypeInsn(CHECKCAST, aspectClassName);
947             cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature);
948         } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) {
949         } else {
950             throw new UnsupportedOperationException JavaDoc(
951                     "unsupported deployment model - " +
952                     aspectInfo.getAspectClassName() + " " +
953                     deploymentModel
954             );
955         }
956     }
957
958     /**
959      * Creates the 'invoke' method. If possible delegates to the target join point directly, e.g. does not invoke the
960      * 'proceed' method (Used when a join point has zero around advice).
961      */

962     protected void createInvokeMethod() {
963
964         final String JavaDoc invokeDesc = buildInvokeMethodSignature();
965
966         // create the method
967
CodeVisitor cv = m_cw.visitMethod(
968                 ACC_PUBLIC + ACC_FINAL + ACC_STATIC,
969                 INVOKE_METHOD_NAME,
970                 invokeDesc,
971                 new String JavaDoc[]{
972                     THROWABLE_CLASS_NAME
973                 },
974                 null
975         );
976
977         // compute the callee and caller index from the invoke(..) signature
978
int calleeIndex = INDEX_NOTAVAILABLE;
979         int argStartIndex = 0;
980         if (!Modifier.isStatic(m_calleeMemberModifiers) &&
981             m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT &&
982             m_joinPointType != JoinPointType.HANDLER_INT) {
983             calleeIndex = 0;
984             argStartIndex++;
985         } else {
986             calleeIndex = INDEX_NOTAVAILABLE;// no callee in the invoke(..) parameters
987
}
988         int callerIndex = argStartIndex + AsmHelper.getRegisterDepth(m_argumentTypes);
989
990         // custom logic overrides for handler jp
991
if (m_joinPointType == JoinPointType.HANDLER_INT) {
992             calleeIndex = 0;
993             callerIndex = 2;
994             argStartIndex = 1;
995         }
996
997         // do we need to keep track of CALLEE, ARGS etc, if not then completely skip it
998
// and make use of the optimized join point instance
999
// while not using its fields (does not support reentrancy and thread safety)
1000
final boolean isOptimizedJoinPoint = !m_requiresJoinPoint && !requiresProceedMethod();
1001        int joinPointIndex = INDEX_NOTAVAILABLE;
1002
1003        if (!isOptimizedJoinPoint) {
1004            // create a new JP and makes use of it
1005
joinPointIndex = callerIndex + 1;
1006            createInvocationLocalJoinPointInstance(cv, argStartIndex, joinPointIndex, callerIndex, calleeIndex);
1007        }
1008
1009        // initialize the instance level aspects (perInstance)
1010
initializeInstanceLevelAspects(cv, isOptimizedJoinPoint, joinPointIndex, callerIndex, calleeIndex);
1011
1012        // before advices
1013
createBeforeAdviceInvocations(
1014                cv, isOptimizedJoinPoint, argStartIndex, joinPointIndex, callerIndex, calleeIndex
1015        );
1016
1017        // handle different combinations of after advice (finally/throwing/returning)
1018
if (m_afterFinallyAdviceMethodInfos.length == 0 &&
1019            m_afterThrowingAdviceMethodInfos.length == 0 &&
1020            !m_isThisAdvisable) {
1021            createPartOfInvokeMethodWithoutAfterFinallyAndAfterThrowingAdviceTypes(
1022                    cv, isOptimizedJoinPoint, joinPointIndex, argStartIndex, callerIndex, calleeIndex
1023            );
1024        } else if (m_afterThrowingAdviceMethodInfos.length == 0 &&
1025                   !m_isThisAdvisable) {
1026            createPartOfInvokeMethodWithoutAfterThrowingAdviceTypes(
1027                    cv, isOptimizedJoinPoint, joinPointIndex, argStartIndex, callerIndex, calleeIndex
1028            );
1029        } else {
1030            createPartOfInvokeMethodWithAllAdviceTypes(
1031                    cv, OPTIMIZED_JOIN_POINT, joinPointIndex, argStartIndex, callerIndex, calleeIndex
1032            );
1033        }
1034
1035        cv.visitMaxs(0, 0);
1036    }
1037
1038    /**
1039     * Initializes instance level aspects, retrieves them from the target instance through the
1040     * <code>HasInstanceLevelAspect</code> interfaces.
1041     * <p/>
1042     * Use by 'perInstance', 'perThis' and 'perTarget' deployment models.
1043     *
1044     * @param cv
1045     * @param isOptimizedJoinPoint
1046     * @param joinPointIndex
1047     * @param callerIndex
1048     * @param calleeIndex
1049     */

1050    protected void initializeInstanceLevelAspects(final CodeVisitor cv,
1051                                                  final boolean isOptimizedJoinPoint,
1052                                                  final int joinPointIndex,
1053                                                  final int callerIndex,
1054                                                  final int calleeIndex) {
1055        for (int i = 0; i < m_aspectInfos.length; i++) {
1056            AspectInfo aspectInfo = m_aspectInfos[i];
1057            if (aspectInfo.getDeploymentModel() == DeploymentModel.PER_INSTANCE) {
1058                // gen code: aspectField = (<TYPE>)((HasInstanceLocalAspect)CALLER).aw$getAspect(className, qualifiedName, containerClassName)
1059
loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
1060                if (callerIndex >= 0) {
1061                    cv.visitVarInsn(ALOAD, callerIndex);
1062                } else {
1063                    // caller instance not available - skipping
1064
//TODO clean up should not occur
1065
}
1066                cv.visitLdcInsn(aspectInfo.getAspectClassName().replace('/', '.'));
1067                cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
1068                cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
1069                cv.visitMethodInsn(
1070                        INVOKEINTERFACE,
1071                        HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME,
1072                        GET_INSTANCE_LEVEL_ASPECT_METHOD_NAME,
1073                        GET_INSTANCE_LEVEL_ASPECT_METHOD_SIGNATURE
1074                );
1075                cv.visitTypeInsn(CHECKCAST, aspectInfo.getAspectClassName());
1076                cv.visitFieldInsn(
1077                        PUTFIELD,
1078                        m_joinPointClassName,
1079                        aspectInfo.getAspectFieldName(),
1080                        aspectInfo.getAspectClassSignature()
1081                );
1082            }
1083        }
1084    }
1085
1086    /**
1087     * @param cv
1088     * @param isOptimizedJoinPoint
1089     * @param joinPointInstanceIndex
1090     * @param argStartIndex
1091     * @param callerIndex
1092     * @param calleeIndex
1093     */

1094    protected void createPartOfInvokeMethodWithAllAdviceTypes(final CodeVisitor cv,
1095                                                              final boolean isOptimizedJoinPoint,
1096                                                              final int joinPointInstanceIndex,
1097                                                              final int argStartIndex,
1098                                                              final int callerIndex,
1099                                                              final int calleeIndex) {
1100        final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1101                                     (joinPointInstanceIndex + 1) : callerIndex + 1;
1102        final int exceptionIndex1 = returnValueIndex + 1;
1103        final int exceptionIndex2 = returnValueIndex + 2;
1104
1105        cv.visitInsn(ACONST_NULL);
1106        cv.visitVarInsn(ASTORE, returnValueIndex);
1107
1108        Label tryLabel = new Label();
1109        cv.visitLabel(tryLabel);
1110        if (!requiresProceedMethod()) {
1111            // if no around advice then optimize by invoking the target JP directly and no call to proceed()
1112
createInlinedJoinPointInvocation(cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex);
1113            int stackIndex = returnValueIndex;//use another int since storeType will update it
1114
AsmHelper.storeType(cv, stackIndex, m_returnType);
1115            addReturnedValueToJoinPoint(cv, returnValueIndex, joinPointInstanceIndex, false);
1116        } else {
1117            createInvocationToProceedMethod(cv, joinPointInstanceIndex, returnValueIndex);
1118        }
1119
1120        createAfterReturningAdviceInvocations(
1121                cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1122                callerIndex, calleeIndex
1123        );
1124
1125        Label finallyLabel1 = new Label();
1126        cv.visitLabel(finallyLabel1);
1127
1128        if (m_isThisAdvisable) {
1129            final int registerDepth = callerIndex + 2; // caller is using last register + possible return value
1130
createAfterInterceptorInvocations(cv, joinPointInstanceIndex, registerDepth);
1131        }
1132        createAfterFinallyAdviceInvocations(
1133                cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1134                callerIndex, calleeIndex
1135        );
1136
1137        Label gotoFinallyLabel = new Label();
1138        cv.visitJumpInsn(GOTO, gotoFinallyLabel);
1139
1140        Label catchLabel = new Label();
1141        cv.visitLabel(catchLabel);
1142
1143        // store the exception
1144
cv.visitVarInsn(ASTORE, exceptionIndex1);
1145
1146        if (m_isThisAdvisable) {
1147            createAfterThrowingInterceptorInvocations(cv, joinPointInstanceIndex, exceptionIndex1);
1148        }
1149
1150        // loop over the after throwing advices
1151
for (int i = m_afterThrowingAdviceMethodInfos.length - 1; i >= 0; i--) {
1152            AdviceMethodInfo advice = m_afterThrowingAdviceMethodInfos[i];
1153
1154            // set the exception argument index
1155
advice.setSpecialArgumentIndex(exceptionIndex1);
1156
1157            // if (e instanceof TYPE) {...}
1158
cv.visitVarInsn(ALOAD, exceptionIndex1);
1159
1160            final String JavaDoc specialArgTypeName = advice.getSpecialArgumentTypeName();
1161            if (specialArgTypeName != null) {
1162                // after throwing <TYPE>
1163
cv.visitTypeInsn(INSTANCEOF, specialArgTypeName);
1164
1165                Label ifInstanceOfLabel = new Label();
1166                cv.visitJumpInsn(IFEQ, ifInstanceOfLabel);
1167
1168                // after throwing advice invocation
1169
createAfterAdviceInvocation(
1170                        cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex,
1171                        argStartIndex, callerIndex, calleeIndex, exceptionIndex1
1172                );
1173
1174                cv.visitLabel(ifInstanceOfLabel);
1175            } else {
1176                // after throwing
1177
createAfterAdviceInvocation(
1178                        cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex,
1179                        argStartIndex, callerIndex, calleeIndex, INDEX_NOTAVAILABLE
1180                );
1181            }
1182        }
1183
1184        // rethrow exception
1185
cv.visitVarInsn(ALOAD, exceptionIndex1);
1186        cv.visitInsn(ATHROW);
1187
1188        // store exception
1189
Label exceptionLabel = new Label();
1190        cv.visitLabel(exceptionLabel);
1191        cv.visitVarInsn(ASTORE, exceptionIndex2);
1192
1193        // after finally advice invocation
1194
Label finallyLabel2 = new Label();
1195        cv.visitLabel(finallyLabel2);
1196
1197        if (m_isThisAdvisable) {
1198            final int registerDepth = callerIndex + 2; // caller is using last register + possible return value
1199
createAfterInterceptorInvocations(cv, joinPointInstanceIndex, registerDepth);
1200        }
1201        createAfterFinallyAdviceInvocations(
1202                cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1203                callerIndex, calleeIndex
1204        );
1205
1206        // rethrow exception
1207
cv.visitVarInsn(ALOAD, exceptionIndex2);
1208        cv.visitInsn(ATHROW);
1209        cv.visitLabel(gotoFinallyLabel);
1210
1211        // unwrap if around advice and return in all cases
1212
if (m_returnType.getSort() != Type.VOID) {
1213            if (requiresProceedMethod()) {
1214                cv.visitVarInsn(ALOAD, returnValueIndex);
1215                AsmHelper.unwrapType(cv, m_returnType);
1216            } else {
1217                AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1218            }
1219        }
1220
1221        AsmHelper.addReturnStatement(cv, m_returnType);
1222
1223        // build up the exception table
1224
cv.visitTryCatchBlock(tryLabel, finallyLabel1, catchLabel, THROWABLE_CLASS_NAME);
1225        cv.visitTryCatchBlock(tryLabel, finallyLabel1, exceptionLabel, null);
1226        cv.visitTryCatchBlock(catchLabel, finallyLabel2, exceptionLabel, null);
1227    }
1228
1229    /**
1230     * @param cv
1231     * @param isOptimizedJoinPoint
1232     * @param joinPointInstanceIndex
1233     * @param argStartIndex
1234     * @param callerIndex
1235     * @param calleeIndex
1236     */

1237    protected void createPartOfInvokeMethodWithoutAfterThrowingAdviceTypes(final CodeVisitor cv,
1238                                                                           final boolean isOptimizedJoinPoint,
1239                                                                           final int joinPointInstanceIndex,
1240                                                                           final int argStartIndex,
1241                                                                           final int callerIndex,
1242                                                                           final int calleeIndex) {
1243        final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1244                                     (joinPointInstanceIndex + 1) : callerIndex + 1;
1245        final int exceptionIndex = returnValueIndex + 1;
1246
1247        cv.visitInsn(ACONST_NULL);
1248        cv.visitVarInsn(ASTORE, returnValueIndex);
1249
1250        Label tryLabel = new Label();
1251        cv.visitLabel(tryLabel);
1252        if (!requiresProceedMethod()) {
1253            // if no around advice then optimize by invoking the target JP directly and no call to proceed()
1254
createInlinedJoinPointInvocation(cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex);
1255            int stackIndex = returnValueIndex;//use another int since storeType will update it
1256
AsmHelper.storeType(cv, stackIndex, m_returnType);
1257            addReturnedValueToJoinPoint(cv, returnValueIndex, joinPointInstanceIndex, false);
1258        } else {
1259            createInvocationToProceedMethod(cv, joinPointInstanceIndex, returnValueIndex);
1260        }
1261
1262        createAfterReturningAdviceInvocations(
1263                cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1264                callerIndex, calleeIndex
1265        );
1266
1267        Label finallyLabel1 = new Label();
1268        cv.visitLabel(finallyLabel1);
1269
1270        createAfterFinallyAdviceInvocations(
1271                cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1272                callerIndex, calleeIndex
1273        );
1274
1275        Label gotoFinallyLabel = new Label();
1276        cv.visitJumpInsn(GOTO, gotoFinallyLabel);
1277
1278        Label exceptionLabel = new Label();
1279        cv.visitLabel(exceptionLabel);
1280        cv.visitVarInsn(ASTORE, exceptionIndex);
1281
1282        Label finallyLabel2 = new Label();
1283        cv.visitLabel(finallyLabel2);
1284
1285        createAfterFinallyAdviceInvocations(
1286                cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1287                callerIndex, calleeIndex
1288        );
1289
1290        cv.visitVarInsn(ALOAD, exceptionIndex);
1291        cv.visitInsn(ATHROW);
1292
1293        cv.visitLabel(gotoFinallyLabel);
1294
1295        // unwrap if around advice and return in all cases
1296
if (m_returnType.getSort() != Type.VOID) {
1297            if (requiresProceedMethod()) {
1298                cv.visitVarInsn(ALOAD, returnValueIndex);
1299                AsmHelper.unwrapType(cv, m_returnType);
1300            } else {
1301                AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1302            }
1303        }
1304
1305        AsmHelper.addReturnStatement(cv, m_returnType);
1306
1307        cv.visitTryCatchBlock(tryLabel, finallyLabel1, exceptionLabel, null);
1308        cv.visitTryCatchBlock(exceptionLabel, finallyLabel2, exceptionLabel, null);
1309    }
1310
1311    /**
1312     * @param cv
1313     * @param isOptimizedJoinPoint
1314     * @param joinPointInstanceIndex
1315     * @param argStartIndex
1316     * @param callerIndex
1317     * @param calleeIndex
1318     */

1319    protected void createPartOfInvokeMethodWithoutAfterFinallyAndAfterThrowingAdviceTypes(final CodeVisitor cv,
1320                                                                                          final boolean isOptimizedJoinPoint,
1321                                                                                          final int joinPointInstanceIndex,
1322                                                                                          final int argStartIndex,
1323                                                                                          final int callerIndex,
1324                                                                                          final int calleeIndex) {
1325
1326        final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1327                                     (joinPointInstanceIndex + 1) : callerIndex + 1;
1328        if (!requiresProceedMethod()) {
1329            // if no around advice then optimize by invoking the target JP directly and no call to proceed()
1330
createInlinedJoinPointInvocation(cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex);
1331            int stackIndex = returnValueIndex;//use another int since storeType will update it
1332
AsmHelper.storeType(cv, stackIndex, m_returnType);
1333            addReturnedValueToJoinPoint(cv, returnValueIndex, joinPointInstanceIndex, false);
1334        } else {
1335            createInvocationToProceedMethod(cv, joinPointInstanceIndex, returnValueIndex);
1336        }
1337
1338
1339        // after returning advice invocations
1340
createAfterReturningAdviceInvocations(
1341                cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1342                callerIndex, calleeIndex
1343        );
1344
1345        // unwrap if around advice and return in all cases
1346
if (m_returnType.getSort() != Type.VOID) {
1347            if (requiresProceedMethod()) {
1348                cv.visitVarInsn(ALOAD, returnValueIndex);
1349                AsmHelper.unwrapType(cv, m_returnType);
1350            } else {
1351                AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1352            }
1353        }
1354
1355        AsmHelper.addReturnStatement(cv, m_returnType);
1356    }
1357
1358    /**
1359     * Creates an invocation to the proceed method.
1360     *
1361     * @param cv
1362     * @param joinPointInstanceIndex
1363     * @param returnValueIndex
1364     */

1365    protected void createInvocationToProceedMethod(final CodeVisitor cv,
1366                                                   final int joinPointInstanceIndex,
1367                                                   final int returnValueIndex) {
1368        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1369        cv.visitMethodInsn(INVOKEVIRTUAL, m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1370        cv.visitVarInsn(ASTORE, returnValueIndex);
1371    }
1372
1373    /**
1374     * Creates an "invocation local" join point instance, e.g. one join point per invocation. Needed for thread-safety
1375     * when invoking around advice.
1376     *
1377     * @param cv
1378     * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or
1379     * not)
1380     * @param joinPointInstanceIndex
1381     * @param callerIndex
1382     * @param calleeIndex
1383     */

1384    protected void createInvocationLocalJoinPointInstance(final CodeVisitor cv,
1385                                                          final int argStartIndex,
1386                                                          final int joinPointInstanceIndex,
1387                                                          final int callerIndex,
1388                                                          final int calleeIndex) {
1389        // create the join point instance
1390
cv.visitTypeInsn(NEW, m_joinPointClassName);
1391        cv.visitInsn(DUP);
1392        cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
1393
1394        // store the jp on the stack
1395
cv.visitVarInsn(ASTORE, joinPointInstanceIndex);
1396
1397        // set the argument fields in the join point instance (jp.m_arg<i> = <arg_i>)
1398
int argStackIndex = argStartIndex;
1399        for (int i = 0; i < m_fieldNames.length; i++) {
1400            String JavaDoc fieldName = m_fieldNames[i];
1401            cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1402            Type type = m_argumentTypes[i];
1403            argStackIndex = AsmHelper.loadType(cv, argStackIndex, type);
1404            cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, fieldName, type.getDescriptor());
1405        }
1406
1407        // caller (can be assigned to null)
1408
cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1409        cv.visitVarInsn(ALOAD, callerIndex);
1410        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1411
1412        // callee (can be not available)
1413
cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1414        if (calleeIndex != INDEX_NOTAVAILABLE) {
1415            cv.visitVarInsn(ALOAD, 0);
1416        } else {
1417            cv.visitInsn(ACONST_NULL);
1418        }
1419        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1420
1421        if (m_isThisAdvisable) {
1422            createInitializationForAdvisableManagement(cv, joinPointInstanceIndex, callerIndex);
1423        }
1424    }
1425
1426    /**
1427     * Create the proceed() method.
1428     */

1429    protected void createProceedMethod() {
1430
1431        CodeVisitor cv = m_cw.visitMethod(
1432                ACC_PUBLIC | ACC_FINAL,
1433                PROCEED_METHOD_NAME,
1434                PROCEED_METHOD_SIGNATURE,
1435                new String JavaDoc[]{
1436                    THROWABLE_CLASS_NAME
1437                },
1438                null
1439        );
1440
1441        if (m_isThisAdvisable) {
1442            createAroundInterceptorInvocations(cv);
1443        }
1444
1445        incrementStackFrameCounter(cv);
1446
1447        // set up the labels
1448
Label tryLabel = new Label();
1449        Label defaultCaseLabel = new Label();
1450        Label gotoLabel = new Label();
1451        Label handlerLabel = new Label();
1452        Label endLabel = new Label();
1453
1454        int nrOfCases = m_aroundAdviceMethodInfos.length;
1455        if (m_isThisAdvisable) {
1456            nrOfCases++;
1457        }
1458
1459        Label[] caseLabels = new Label[nrOfCases];
1460        Label[] returnLabels = new Label[nrOfCases];
1461        int[] caseNumbers = new int[nrOfCases];
1462        for (int i = 0; i < caseLabels.length; i++) {
1463            caseLabels[i] = new Label();
1464            caseNumbers[i] = i;
1465        }
1466        for (int i = 0; i < returnLabels.length; i++) {
1467            returnLabels[i] = new Label();
1468        }
1469
1470        // start try-catch block
1471
cv.visitLabel(tryLabel);
1472
1473        // start the switch block and set the stackframe as the param to the switch
1474
cv.visitVarInsn(ALOAD, 0);
1475        cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1476        cv.visitLookupSwitchInsn(defaultCaseLabel, caseNumbers, caseLabels);
1477
1478        // add one case for each around advice invocation
1479
for (int i = 0; i < m_aroundAdviceMethodInfos.length; i++) {
1480            cv.visitLabel(caseLabels[i]);
1481
1482            // gather advice info
1483
AdviceMethodInfo adviceInfo = m_aroundAdviceMethodInfos[i];
1484
1485            Label endInstanceOflabel = beginRuntimeCheck(cv, false, 0, adviceInfo.getAdviceInfo(), -1);
1486
1487            // get the aspect instance
1488
loadAspect(cv, NON_OPTIMIZED_JOIN_POINT, 0, adviceInfo.getAspectInfo());
1489
1490            // load the arguments to the advice from the join point instance plus build up the
1491
// advice method signature
1492
int[] argIndexes = adviceInfo.getAdviceMethodArgIndexes();
1493            for (int j = 0; j < argIndexes.length; j++) {
1494                int argIndex = argIndexes[j];
1495                if (argIndex >= 0) {
1496                    Type argumentType = m_argumentTypes[argIndex];
1497                    cv.visitVarInsn(ALOAD, 0);
1498                    cv.visitFieldInsn(
1499                            GETFIELD,
1500                            m_joinPointClassName,
1501                            ARGUMENT_FIELD + argIndex,
1502                            argumentType.getDescriptor()
1503                    );
1504                } else if (argIndex == AdviceInfo.JOINPOINT_ARG ||
1505                           argIndex == AdviceInfo.STATIC_JOINPOINT_ARG ||
1506                           argIndex == AdviceInfo.VALID_NON_AW_AROUND_CLOSURE_TYPE ||
1507                           argIndex == AdviceInfo.CUSTOM_JOIN_POINT_ARG) {
1508                    cv.visitVarInsn(ALOAD, 0);
1509                } else if (argIndex == AdviceInfo.TARGET_ARG) {
1510                    loadCallee(cv, NON_OPTIMIZED_JOIN_POINT, 0, INDEX_NOTAVAILABLE);
1511                    // add a cast if runtime check was used
1512
if (adviceInfo.getAdviceInfo().hasTargetWithRuntimeCheck()) {
1513                        cv.visitTypeInsn(
1514                                CHECKCAST, adviceInfo.getAdviceInfo().getMethodParameterTypes()[j].getInternalName()
1515                        );
1516                    }
1517                } else if (argIndex == AdviceInfo.THIS_ARG) {
1518                    loadCaller(cv, NON_OPTIMIZED_JOIN_POINT, 0, INDEX_NOTAVAILABLE);
1519                } else {
1520                    throw new Error JavaDoc("advice method argument index type is not supported: " + argIndex);
1521                }
1522            }
1523
1524            // invoke the advice method
1525
cv.visitMethodInsn(
1526                    INVOKEVIRTUAL,
1527                    adviceInfo.getAspectInfo().getAspectClassName(),
1528                    adviceInfo.getAdviceInfo().getMethodName(),
1529                    adviceInfo.getAdviceInfo().getMethodSignature()
1530            );
1531            cv.visitVarInsn(ASTORE, 1);
1532
1533            // we need to handle the case when the advice was skipped due to runtime check
1534
// that is : if (runtimeCheck) { ret = advice() } else { ret = proceed() }
1535
if (endInstanceOflabel != null) {
1536                Label elseInstanceOfLabel = new Label();
1537                cv.visitJumpInsn(GOTO, elseInstanceOfLabel);
1538                endRuntimeCheck(cv, adviceInfo.getAdviceInfo(), endInstanceOflabel);
1539                cv.visitVarInsn(ALOAD, 0);
1540                cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1541                cv.visitVarInsn(ASTORE, 1);
1542                cv.visitLabel(elseInstanceOfLabel);
1543            }
1544
1545            cv.visitLabel(returnLabels[i]);
1546
1547            cv.visitVarInsn(ALOAD, 1);
1548            cv.visitInsn(ARETURN);
1549        }
1550
1551        if (m_isThisAdvisable) {
1552            int delegationCaseIndex = caseLabels.length - 1;
1553            cv.visitLabel(caseLabels[delegationCaseIndex]);
1554            cv.visitVarInsn(ALOAD, 0);
1555            cv.visitInsn(ICONST_0);
1556            cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
1557            cv.visitVarInsn(ALOAD, 0);
1558            cv.visitMethodInsn(INVOKEVIRTUAL, m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1559
1560            cv.visitLabel(returnLabels[delegationCaseIndex]);
1561
1562            cv.visitInsn(ARETURN);
1563        }
1564
1565        // invoke the target join point in the default case
1566
cv.visitLabel(defaultCaseLabel);
1567
1568        AsmHelper.prepareWrappingOfPrimitiveType(cv, Type.getReturnType(m_calleeMemberDesc));
1569
1570        createJoinPointInvocation(cv);
1571
1572        Type m_returnType = null;
1573        if (m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT) {
1574            m_returnType = Type.getReturnType(m_calleeMemberDesc);
1575        } else {
1576            m_returnType = Type.getType(m_calleeClassSignature);
1577        }
1578        AsmHelper.wrapPrimitiveType(cv, m_returnType);
1579        cv.visitVarInsn(ASTORE, 1);
1580
1581        // store it in Rtti return value
1582
addReturnedValueToJoinPoint(cv, 1, 0, true);
1583
1584        // set it as the CALLEE instance for ctor call - TODO refactor somewhere else
1585
if (m_joinPointType == JoinPointType.CONSTRUCTOR_CALL_INT) {
1586            cv.visitVarInsn(ALOAD, 0);
1587            cv.visitVarInsn(ALOAD, 1);
1588            cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1589        }
1590
1591        cv.visitLabel(gotoLabel);
1592
1593        cv.visitVarInsn(ALOAD, 1);
1594        cv.visitInsn(ARETURN);
1595
1596        // finally clause
1597
cv.visitLabel(handlerLabel);
1598        cv.visitVarInsn(ASTORE, 2);
1599        cv.visitLabel(endLabel);
1600
1601        cv.visitVarInsn(ALOAD, 2);
1602        cv.visitInsn(ATHROW);
1603
1604        // set up the label table
1605
cv.visitTryCatchBlock(tryLabel, returnLabels[0], handlerLabel, null);
1606        for (int i = 1; i < caseLabels.length; i++) {
1607            Label caseLabel = caseLabels[i];
1608            Label returnLabel = returnLabels[i];
1609            cv.visitTryCatchBlock(caseLabel, returnLabel, handlerLabel, null);
1610        }
1611        cv.visitTryCatchBlock(defaultCaseLabel, gotoLabel, handlerLabel, null);
1612        cv.visitTryCatchBlock(handlerLabel, endLabel, handlerLabel, null);
1613        cv.visitMaxs(0, 0);
1614    }
1615
1616    /**
1617     * Adds before advice invocations.
1618     *
1619     * @param cv
1620     * @param isOptimizedJoinPoint
1621     * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or
1622     * not)
1623     * @param joinPointInstanceIndex >= 0 if STATIC_JOIN_POINT is NOT to be used (around advice)
1624     * @param callerIndex
1625     * @param calleeIndex
1626     */

1627    protected void createBeforeAdviceInvocations(final CodeVisitor cv,
1628                                                 final boolean isOptimizedJoinPoint,
1629                                                 final int argStartIndex,
1630                                                 final int joinPointInstanceIndex, //FIXME redundant -1 with isStaticJP
1631
final int callerIndex,
1632                                                 final int calleeIndex) {
1633        for (int i = 0; i < m_beforeAdviceMethodInfos.length; i++) {
1634            AdviceMethodInfo adviceMethodInfo = m_beforeAdviceMethodInfos[i];
1635
1636            // runtime check for target() etc
1637
Label endInstanceOflabel = beginRuntimeCheck(
1638                    cv, isOptimizedJoinPoint, joinPointInstanceIndex, adviceMethodInfo.getAdviceInfo(), calleeIndex
1639            );
1640
1641            //get the aspect instance
1642
loadAspect(cv, isOptimizedJoinPoint, joinPointInstanceIndex, adviceMethodInfo.getAspectInfo());
1643
1644            AspectDefinition aspectDef = adviceMethodInfo.getAdviceInfo().getAdviceDefinition().getAspectDefinition();
1645            if (aspectDef.isAspectWerkzAspect()) {
1646                // AW aspect
1647
int[] argIndexes = adviceMethodInfo.getAdviceMethodArgIndexes();
1648                // if empty, we consider for now that we have to push JoinPoint for old advice with JoinPoint as sole arg
1649
for (int j = 0; j < argIndexes.length; j++) {
1650                    int argIndex = argIndexes[j];
1651                    if (argIndex >= 0) {
1652                        Type argumentType = m_argumentTypes[argIndex];
1653                        int argStackIndex = AsmHelper.getRegisterIndexOf(m_argumentTypes, argIndex) + argStartIndex;
1654                        AsmHelper.loadType(cv, argStackIndex, argumentType);
1655                    } else if (argIndex == AdviceInfo.JOINPOINT_ARG || argIndex == AdviceInfo.STATIC_JOINPOINT_ARG) {
1656                        loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointInstanceIndex);
1657                    } else if (argIndex == AdviceInfo.TARGET_ARG) {
1658                        loadCallee(cv, isOptimizedJoinPoint, joinPointInstanceIndex, calleeIndex);
1659                        // add a cast if runtime check was used
1660
if (adviceMethodInfo.getAdviceInfo().hasTargetWithRuntimeCheck()) {
1661                            cv.visitTypeInsn(
1662                                    CHECKCAST,
1663                                    adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j].getInternalName()
1664                            );
1665                        }
1666                    } else if (argIndex == AdviceInfo.THIS_ARG) {
1667                        loadCaller(cv, isOptimizedJoinPoint, joinPointInstanceIndex, callerIndex);
1668                    } else {
1669                        throw new Error JavaDoc("special argument index is not supported: " + argIndex);
1670                    }
1671                }
1672            } else {
1673                // non-AW aspect
1674
adviceMethodInfo.setJoinPointIndex(joinPointInstanceIndex);
1675                for (int j = 0; j < m_aspectModels.length; j++) {
1676                    AspectModel aspectModel = m_aspectModels[j];
1677                    if (aspectDef.getAspectModel().equals(aspectModel.getAspectModelType())) {
1678                        aspectModel.createBeforeAdviceArgumentHandling(cv, adviceMethodInfo);
1679                    }
1680                }
1681            }
1682
1683            cv.visitMethodInsn(
1684                    INVOKEVIRTUAL,
1685                    adviceMethodInfo.getAspectInfo().getAspectClassName(),
1686                    adviceMethodInfo.getAdviceInfo().getMethodName(),
1687                    adviceMethodInfo.getAdviceInfo().getMethodSignature()
1688            );
1689
1690            // end label of runtime checks
1691
endRuntimeCheck(cv, adviceMethodInfo.getAdviceInfo(), endInstanceOflabel);
1692        }
1693
1694        if (m_isThisAdvisable) {
1695            createBeforeInterceptorInvocations(cv, joinPointInstanceIndex, callerIndex + 1);
1696        }
1697    }
1698
1699    /**
1700     * Adds after advice invocations.
1701     *
1702     * @param cv
1703     * @param isOptimizedJoinPoint
1704     * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or
1705     * not)
1706     * @param joinPointInstanceIndex >= 0 if STATIC_JOIN_POINT is NOT to be used (around advice)
1707     * @param callerIndex
1708     * @param calleeIndex
1709     */

1710    protected void createAfterFinallyAdviceInvocations(final CodeVisitor cv,
1711                                                       final boolean isOptimizedJoinPoint,
1712                                                       final int argStartIndex,
1713                                                       final int joinPointInstanceIndex,
1714                                                       final int callerIndex,
1715                                                       final int calleeIndex) {
1716        // add after advice in reverse order
1717
for (int i = m_afterFinallyAdviceMethodInfos.length - 1; i >= 0; i--) {
1718            AdviceMethodInfo advice = m_afterFinallyAdviceMethodInfos[i];
1719            createAfterAdviceInvocation(
1720                    cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex, argStartIndex,
1721                    callerIndex, calleeIndex, INDEX_NOTAVAILABLE
1722            );
1723        }
1724    }
1725
1726    /**
1727     * Adds after returning advice invocations.
1728     *
1729     * @param cv
1730     * @param isOptimizedJoinPoint
1731     * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or
1732     * not)
1733     * @param joinPointInstanceIndex >= 0 if STATIC_JOIN_POINT is NOT to be used (around advice)
1734     * @param callerIndex
1735     * @param calleeIndex
1736     */

1737    protected void createAfterReturningAdviceInvocations(final CodeVisitor cv,
1738                                                         final boolean isOptimizedJoinPoint,
1739                                                         final int argStartIndex,
1740                                                         final int joinPointInstanceIndex,
1741                                                         final int callerIndex,
1742                                                         final int calleeIndex) {
1743
1744        final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1745                                     (joinPointInstanceIndex + 1) : callerIndex + 1;
1746
1747        if (m_isThisAdvisable) {
1748            createAfterReturningInterceptorInvocations(cv, joinPointInstanceIndex, returnValueIndex);
1749        }
1750
1751        boolean hasPoppedReturnValueFromStack = false;
1752        for (int i = m_afterReturningAdviceMethodInfos.length - 1; i >= 0; i--) {
1753            AdviceMethodInfo advice = m_afterReturningAdviceMethodInfos[i];
1754
1755            // set the return value index that will be used as arg to advice
1756
advice.setSpecialArgumentIndex(returnValueIndex);
1757
1758            String JavaDoc specialArgDesc = advice.getSpecialArgumentTypeDesc();
1759            if (specialArgDesc == null) {
1760                // after returning
1761
createAfterAdviceInvocation(
1762                        cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex, argStartIndex,
1763                        callerIndex, calleeIndex, INDEX_NOTAVAILABLE
1764                );
1765            } else {
1766                // after returning <TYPE>
1767
if (AsmHelper.isPrimitive(m_returnType)) {
1768                    if (m_returnType.getDescriptor().equals(specialArgDesc)) {
1769                        createAfterAdviceInvocation(
1770                                cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex, argStartIndex,
1771                                callerIndex, calleeIndex, returnValueIndex
1772                        );
1773                    }
1774                } else {
1775                    cv.visitVarInsn(ALOAD, returnValueIndex);
1776
1777                    cv.visitTypeInsn(INSTANCEOF, advice.getSpecialArgumentTypeName());
1778
1779                    Label label = new Label();
1780                    cv.visitJumpInsn(IFEQ, label);
1781
1782                    createAfterAdviceInvocation(
1783                            cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex, argStartIndex,
1784                            callerIndex, calleeIndex, returnValueIndex
1785                    );
1786
1787                    cv.visitLabel(label);
1788                }
1789            }
1790        }
1791
1792        // need the return value in return operation
1793
if (!requiresProceedMethod() && hasPoppedReturnValueFromStack) {
1794            cv.visitVarInsn(ALOAD, returnValueIndex);
1795        }
1796    }
1797
1798    /**
1799     * Adds a single generic after advice invocation.
1800     *
1801     * @param cv
1802     * @param isOptimizedJoinPoint
1803     * @param adviceMethodInfo
1804     * @param joinPointInstanceIndex
1805     * @param argStartIndex
1806     * @param callerIndex
1807     * @param calleeIndex
1808     * @param specialArgIndex for afterReturning / Throwing when binding is used
1809     */

1810    protected void createAfterAdviceInvocation(final CodeVisitor cv,
1811                                               final boolean isOptimizedJoinPoint,
1812                                               final AdviceMethodInfo adviceMethodInfo,
1813                                               final int joinPointInstanceIndex,
1814                                               final int argStartIndex,
1815                                               final int callerIndex,
1816                                               final int calleeIndex,
1817                                               final int specialArgIndex) {
1818        // runtime check for target() etc
1819
Label endInstanceOflabel = beginRuntimeCheck(
1820                cv, isOptimizedJoinPoint, joinPointInstanceIndex,
1821                adviceMethodInfo.getAdviceInfo(), calleeIndex
1822        );
1823
1824        // get the aspect instance
1825
loadAspect(cv, isOptimizedJoinPoint, joinPointInstanceIndex, adviceMethodInfo.getAspectInfo());
1826
1827        AspectDefinition aspectDef = adviceMethodInfo.getAdviceInfo().getAdviceDefinition().getAspectDefinition();
1828        if (aspectDef.isAspectWerkzAspect()) {
1829            // AW aspect
1830
// load the arguments that should be passed to the advice
1831
int[] argIndexes = adviceMethodInfo.getAdviceMethodArgIndexes();
1832            for (int j = 0; j < argIndexes.length; j++) {
1833                int argIndex = argIndexes[j];
1834                if (argIndex >= 0) {
1835                    Type argumentType = m_argumentTypes[argIndex];
1836                    int argStackIndex = AsmHelper.getRegisterIndexOf(m_argumentTypes, argIndex) + argStartIndex;
1837                    AsmHelper.loadType(cv, argStackIndex, argumentType);
1838                } else if (argIndex == AdviceInfo.JOINPOINT_ARG || argIndex == AdviceInfo.STATIC_JOINPOINT_ARG) {
1839                    loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointInstanceIndex);
1840                } else if (argIndex == AdviceInfo.TARGET_ARG) {
1841                    loadCallee(cv, isOptimizedJoinPoint, joinPointInstanceIndex, calleeIndex);
1842                    // add a cast if runtime check was used
1843
if (adviceMethodInfo.getAdviceInfo().hasTargetWithRuntimeCheck()) {
1844                        cv.visitTypeInsn(
1845                                CHECKCAST,
1846                                adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j].getInternalName()
1847                        );
1848                    }
1849                } else if (argIndex == AdviceInfo.THIS_ARG) {
1850                    loadCaller(cv, isOptimizedJoinPoint, joinPointInstanceIndex, callerIndex);
1851                } else if (argIndex == AdviceInfo.SPECIAL_ARGUMENT && specialArgIndex != INDEX_NOTAVAILABLE) {
1852                    Type argumentType = adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j];
1853                    AsmHelper.loadType(cv, specialArgIndex, argumentType);
1854                    if (adviceMethodInfo.getAdviceInfo().getAdviceDefinition().getType().equals(
1855                            AdviceType.AFTER_THROWING
1856                    )) {
1857                        cv.visitTypeInsn(CHECKCAST, argumentType.getInternalName());
1858                    }
1859                } else {
1860                    throw new Error JavaDoc("magic index is not supported: " + argIndex);
1861                }
1862            }
1863        } else {
1864            // non-AW aspect
1865
adviceMethodInfo.setJoinPointIndex(joinPointInstanceIndex);
1866            for (int i = 0; i < m_aspectModels.length; i++) {
1867                AspectModel aspectModel = m_aspectModels[i];
1868                if (aspectDef.getAspectModel().equals(aspectModel.getAspectModelType())) {
1869                    aspectModel.createAfterAdviceArgumentHandling(cv, adviceMethodInfo);
1870                }
1871            }
1872        }
1873
1874        cv.visitMethodInsn(
1875                INVOKEVIRTUAL,
1876                adviceMethodInfo.getAspectInfo().getAspectClassName(),
1877                adviceMethodInfo.getAdviceInfo().getMethodName(),
1878                adviceMethodInfo.getAdviceInfo().getMethodSignature()
1879        );
1880
1881        // end label of runtime checks
1882
endRuntimeCheck(cv, adviceMethodInfo.getAdviceInfo(), endInstanceOflabel);
1883    }
1884
1885    /**
1886     * Adds the return value to the RETURNED field.
1887     *
1888     * @param cv
1889     * @param returnValueIndex
1890     * @param joinPointInstanceIndex
1891     * @param unwrap set to true if already wrapped on the stack (within proceed() code)
1892     */

1893    protected void addReturnedValueToJoinPoint(final CodeVisitor cv,
1894                                               final int returnValueIndex,
1895                                               final int joinPointInstanceIndex,
1896                                               final boolean unwrap) {
1897        if (m_requiresJoinPoint && m_returnType.getSort() != Type.VOID) {
1898            if (m_joinPointType == JoinPointType.METHOD_EXECUTION_INT
1899                || m_joinPointType == JoinPointType.METHOD_CALL_INT
1900                || m_joinPointType == JoinPointType.CONSTRUCTOR_CALL_INT) {
1901                //TODO should we do something for field get / set
1902
loadJoinPointInstance(cv, NON_OPTIMIZED_JOIN_POINT, joinPointInstanceIndex);
1903                if (unwrap && AsmHelper.isPrimitive(m_returnType)) {
1904                    cv.visitVarInsn(ALOAD, returnValueIndex);
1905                    AsmHelper.unwrapType(cv, m_returnType);
1906                } else {
1907                    AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1908                }
1909                cv.visitFieldInsn(
1910                        PUTFIELD, m_joinPointClassName,
1911                        RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor()
1912                );
1913            }
1914        }
1915    }
1916
1917    /**
1918     * Loads the join point instance, takes static/non-static join point access into account.
1919     *
1920     * @param cv
1921     * @param isOptimizedJoinPoint
1922     * @param joinPointInstanceIndex
1923     */

1924    protected void loadJoinPointInstance(final CodeVisitor cv,
1925                                         final boolean isOptimizedJoinPoint,
1926                                         final int joinPointInstanceIndex) {
1927        if (isOptimizedJoinPoint) {
1928            cv.visitFieldInsn(
1929                    GETSTATIC, m_joinPointClassName,
1930                    OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME,
1931                    L + m_joinPointClassName + SEMICOLON
1932            );
1933        } else {
1934            cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1935        }
1936    }
1937
1938    /**
1939     * Loads the argument member fields.
1940     *
1941     * @param cv
1942     * @param argStartIndex
1943     */

1944    protected void loadArgumentMemberFields(final CodeVisitor cv, final int argStartIndex) {
1945        int argStackIndex = argStartIndex;
1946        for (int index = 0; index < m_argumentTypes.length; index++) {
1947            Type argumentType = m_argumentTypes[index];
1948            argStackIndex = AsmHelper.loadType(cv, argStackIndex, argumentType);
1949        }
1950    }
1951
1952    /**
1953     * Loads the arguments.
1954     *
1955     * @param cv
1956     */

1957    protected void loadArguments(final CodeVisitor cv) {
1958        for (int i = 0; i < m_fieldNames.length; i++) {
1959            String JavaDoc fieldName = m_fieldNames[i];
1960            Type argumentType = m_argumentTypes[i];
1961            cv.visitVarInsn(ALOAD, 0);
1962            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, fieldName, argumentType.getDescriptor());
1963        }
1964    }
1965
1966    /**
1967     * Resets the stack frame counter.
1968     *
1969     * @param cv
1970     */

1971    protected void resetStackFrameCounter(final CodeVisitor cv) {
1972        cv.visitVarInsn(ALOAD, 0);
1973        cv.visitInsn(ICONST_M1);
1974        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1975    }
1976
1977    /**
1978     * Handles the incrementation of the stack frame.
1979     *
1980     * @param cv
1981     */

1982    protected void incrementStackFrameCounter(final CodeVisitor cv) {
1983        cv.visitVarInsn(ALOAD, 0);
1984        cv.visitInsn(DUP);
1985        cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1986        cv.visitInsn(ICONST_1);
1987        cv.visitInsn(IADD);
1988        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1989    }
1990
1991    /**
1992     * Create and load a structure (f.e. array of Object) where args are stored, before setting the Rtti
1993     * with it (See addParametersToRttiInstance). The structure is stored at the given stackFreeIndex.
1994     * <p/>
1995     * We provide here a default implementation that is suitable for method and constructor call and execution.
1996     * See createParameterWrappedAt for field get/set and handler compiler (no array of argument needed)
1997     *
1998     * @param cv
1999     * @param stackFreeIndex
2000     */

2001    protected final void createArgumentArrayAt(final CodeVisitor cv, final int stackFreeIndex) {
2002        AsmHelper.loadIntegerConstant(cv, m_fieldNames.length);
2003        cv.visitTypeInsn(ANEWARRAY, OBJECT_CLASS_NAME);
2004        cv.visitVarInsn(ASTORE, stackFreeIndex);
2005
2006        for (int i = 0; i < m_argumentTypes.length; i++) {
2007            cv.visitVarInsn(ALOAD, stackFreeIndex);
2008            AsmHelper.loadIntegerConstant(cv, i);
2009            AsmHelper.prepareWrappingOfPrimitiveType(cv, m_argumentTypes[i]);
2010            cv.visitVarInsn(ALOAD, 0);
2011            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, ARGUMENT_FIELD + i, m_argumentTypes[i].getDescriptor());
2012            AsmHelper.wrapPrimitiveType(cv, m_argumentTypes[i]);
2013            cv.visitInsn(AASTORE);
2014        }
2015    }
2016
2017    /**
2018     * Creates utility methods for the join point (getter, setters etc.).
2019     */

2020    protected void createUtilityMethods() {
2021        CodeVisitor cv;
2022
2023        // addMetaData
2024
{
2025            cv = m_cw.visitMethod(ACC_PUBLIC, ADD_META_DATA_METHOD_NAME, ADD_META_DATA_METHOD_SIGNATURE, null, null);
2026            cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
2027            cv.visitVarInsn(ALOAD, 1);
2028            cv.visitVarInsn(ALOAD, 2);
2029            cv.visitMethodInsn(
2030                    INVOKEINTERFACE,
2031                    MAP_CLASS_NAME,
2032                    PUT_METHOD_NAME,
2033                    PUT_METHOD_SIGNATURE
2034            );
2035            cv.visitInsn(POP);
2036            cv.visitInsn(RETURN);
2037            cv.visitMaxs(0, 0);
2038        }
2039
2040        // getMetaData
2041
{
2042            cv = m_cw.visitMethod(ACC_PUBLIC, GET_META_DATA_METHOD_NAME, GET_META_DATA_METHOD_SIGNATURE, null, null);
2043            cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
2044            cv.visitVarInsn(ALOAD, 1);
2045            cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME, GET_METHOD_NAME, GET_METHOD_SIGNATURE);
2046            cv.visitInsn(ARETURN);
2047            cv.visitMaxs(0, 0);
2048        }
2049
2050        // getCallee
2051
{
2052            cv = m_cw.visitMethod(
2053                    ACC_PUBLIC,
2054                    GET_CALLEE_METHOD_NAME,
2055                    NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
2056                    null, null
2057            );
2058            cv.visitVarInsn(ALOAD, 0);
2059            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2060            cv.visitInsn(ARETURN);
2061            cv.visitMaxs(0, 0);
2062        }
2063
2064        // getCaller
2065
{
2066            cv = m_cw.visitMethod(
2067                    ACC_PUBLIC,
2068                    GET_CALLER_METHOD_NAME,
2069                    NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
2070                    null, null
2071            );
2072            cv.visitVarInsn(ALOAD, 0);
2073            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2074            cv.visitInsn(ARETURN);
2075            cv.visitMaxs(0, 0);
2076        }
2077
2078        // getTarget
2079
{
2080            cv = m_cw.visitMethod(
2081                    ACC_PUBLIC,
2082                    GET_TARGET_METHOD_NAME,
2083                    NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
2084                    null, null
2085            );
2086            cv.visitVarInsn(ALOAD, 0);
2087            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2088            cv.visitInsn(ARETURN);
2089            cv.visitMaxs(0, 0);
2090        }
2091
2092        // getThis
2093
{
2094            cv = m_cw.visitMethod(
2095                    ACC_PUBLIC,
2096                    GET_THIS_METHOD_NAME,
2097                    NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
2098                    null, null
2099            );
2100            cv.visitVarInsn(ALOAD, 0);
2101            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2102            cv.visitInsn(ARETURN);
2103            cv.visitMaxs(0, 0);
2104        }
2105
2106        // getCallerClass
2107
{
2108            cv =
2109            m_cw.visitMethod(
2110                    ACC_PUBLIC,
2111                    GET_CALLER_CLASS_METHOD_NAME,
2112                    GET_CALLER_CLASS_METHOD_SIGNATURE,
2113                    null,
2114                    null
2115            );
2116            cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2117            cv.visitInsn(ARETURN);
2118            cv.visitMaxs(0, 0);
2119        }
2120
2121        // getCalleeClass
2122
{
2123            cv =
2124            m_cw.visitMethod(
2125                    ACC_PUBLIC,
2126                    GET_CALLEE_CLASS_METHOD_NAME,
2127                    GET_CALLEE_CLASS_METHOD_SIGNATURE,
2128                    null,
2129                    null
2130            );
2131            cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2132            cv.visitInsn(ARETURN);
2133            cv.visitMaxs(0, 0);
2134        }
2135
2136        // getTargetClass, deprecated but still there
2137
{
2138            cv =
2139            m_cw.visitMethod(
2140                    ACC_PUBLIC,
2141                    GET_TARGET_CLASS_METHOD_NAME,
2142                    GET_TARGET_CLASS_METHOD_SIGNATURE,
2143                    null,
2144                    null
2145            );
2146            cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2147            cv.visitInsn(ARETURN);
2148            cv.visitMaxs(0, 0);
2149        }
2150
2151        // getType
2152
{
2153            cv = m_cw.visitMethod(ACC_PUBLIC, GET_TYPE_METHOD_NAME, GET_TYPE_METHOD_SIGNATURE, null, null);
2154            AsmHelper.loadIntegerConstant(cv, m_joinPointType);
2155            cv.visitMethodInsn(
2156                    INVOKESTATIC, Type.getType(JoinPointType.class).getInternalName(), "fromInt",
2157                    "(I)" + Type.getType(JoinPointType.class).getDescriptor()
2158            );
2159            cv.visitInsn(ARETURN);
2160            cv.visitMaxs(0, 0);
2161        }
2162        
2163        // getEnclosingStaticJoinPoint
2164
{
2165            cv = m_cw.visitMethod(
2166                    ACC_PUBLIC,
2167                    GET_ENCLOSING_SJP_METHOD_NAME,
2168                    GET_ENCLOSING_SJP_METHOD_SIGNATURE,
2169                    null,
2170                    null
2171            );
2172            cv.visitVarInsn(ALOAD, 0);
2173            cv.visitFieldInsn(GETSTATIC,
2174                    m_joinPointClassName,
2175                    ENCLOSING_SJP_FIELD_NAME,
2176                    ENCLOSING_SJP_FIELD_CLASS_SIGNATURE
2177            );
2178            cv.visitInsn(ARETURN);
2179            cv.visitMaxs(0, 0);
2180        }
2181
2182    }
2183
2184    /**
2185     * Creates the copy method.
2186     * <p/>
2187     * TODO refactor and put in subclasses
2188     */

2189    protected void createCopyMethod() {
2190
2191        CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC, COPY_METHOD_NAME, COPY_METHOD_SIGNATURE, null, null);
2192
2193        // create a new join point instance
2194
cv.visitTypeInsn(NEW, m_joinPointClassName);
2195        cv.visitInsn(DUP);
2196        int joinPointCloneIndex = 1;
2197        cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
2198        cv.visitVarInsn(ASTORE, joinPointCloneIndex);
2199
2200        // set stack frame index
2201
cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2202        cv.visitVarInsn(ALOAD, 0);
2203        cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
2204        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
2205
2206        if (m_isThisAdvisable) {
2207            // set interceptor index
2208
cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2209            cv.visitVarInsn(ALOAD, 0);
2210            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2211            cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2212
2213            // set array length fields
2214
cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2215            cv.visitVarInsn(ALOAD, 0);
2216            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2217            cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2218            cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2219            cv.visitVarInsn(ALOAD, 0);
2220            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2221            cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2222            cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2223            cv.visitVarInsn(ALOAD, 0);
2224            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2225            cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2226            cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2227            cv.visitVarInsn(ALOAD, 0);
2228            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2229            cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2230            cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2231            cv.visitVarInsn(ALOAD, 0);
2232            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2233            cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2234
2235            // set arrays
2236
cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2237            cv.visitVarInsn(ALOAD, 0);
2238            cv.visitFieldInsn(
2239                    GETFIELD, m_joinPointClassName, BEFORE_INTERCEPTORS_FIELD_NAME,
2240                    BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2241            );
2242            cv.visitFieldInsn(
2243                    PUTFIELD, m_joinPointClassName, BEFORE_INTERCEPTORS_FIELD_NAME,
2244                    BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2245            );
2246            cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2247            cv.visitVarInsn(ALOAD, 0);
2248            cv.visitFieldInsn(
2249                    GETFIELD, m_joinPointClassName, AROUND_INTERCEPTORS_FIELD_NAME,
2250                    AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2251            );
2252            cv.visitFieldInsn(
2253                    PUTFIELD, m_joinPointClassName, AROUND_INTERCEPTORS_FIELD_NAME,
2254                    AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2255            );
2256            cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2257            cv.visitVarInsn(ALOAD, 0);
2258            cv.visitFieldInsn(
2259                    GETFIELD, m_joinPointClassName, AFTER_INTERCEPTORS_FIELD_NAME, AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2260            );
2261            cv.visitFieldInsn(
2262                    PUTFIELD, m_joinPointClassName, AFTER_INTERCEPTORS_FIELD_NAME, AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2263            );
2264            cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2265            cv.visitVarInsn(ALOAD, 0);
2266            cv.visitFieldInsn(
2267                    GETFIELD, m_joinPointClassName, AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2268                    AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2269            );
2270            cv.visitFieldInsn(
2271                    PUTFIELD, m_joinPointClassName, AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2272                    AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2273            );
2274            cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2275            cv.visitVarInsn(ALOAD, 0);
2276            cv.visitFieldInsn(
2277                    GETFIELD, m_joinPointClassName, AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2278                    AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2279            );
2280            cv.visitFieldInsn(
2281                    PUTFIELD, m_joinPointClassName, AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2282                    AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2283            );
2284        }
2285
2286        // set callee
2287
cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2288        cv.visitVarInsn(ALOAD, 0);
2289        cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2290        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2291
2292        // set caller
2293
cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2294        cv.visitVarInsn(ALOAD, 0);
2295        cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2296        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2297
2298        // set the arguments
2299
for (int i = 0; i < m_fieldNames.length; i++) {
2300            String JavaDoc fieldName = m_fieldNames[i];
2301            cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2302            cv.visitVarInsn(ALOAD, 0);
2303            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, fieldName, m_argumentTypes[i].getDescriptor());
2304            cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, fieldName, m_argumentTypes[i].getDescriptor());
2305        }
2306
2307        // set the returned field if any
2308
if (m_returnType.getSort() != Type.VOID) {
2309            cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2310            cv.visitVarInsn(ALOAD, 0);
2311            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
2312            cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
2313        }
2314
2315        cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2316        cv.visitInsn(ARETURN);
2317        cv.visitMaxs(0, 0);
2318    }
2319
2320    /**
2321     * Build up the signature of the 'invoke' methods.
2322     *
2323     * @return
2324     */

2325    protected String JavaDoc buildInvokeMethodSignature() {
2326        StringBuffer JavaDoc invokeDescBuf = new StringBuffer JavaDoc();
2327        invokeDescBuf.append('(');
2328        if (m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT) {
2329            if (!Modifier.isStatic(m_calleeMemberModifiers)) {
2330                // callee
2331
invokeDescBuf.append(m_calleeClassSignature);
2332            }
2333        }
2334        // args
2335
for (int i = 0; i < m_argumentTypes.length; i++) {
2336            Type type = m_argumentTypes[i];
2337            invokeDescBuf.append(type.getDescriptor());
2338        }
2339        // caller
2340
invokeDescBuf.append(m_callerClassSignature);
2341        invokeDescBuf.append(')');
2342        invokeDescBuf.append(m_returnType.getDescriptor());
2343        return invokeDescBuf.toString();
2344    }
2345
2346    /**
2347     * Return the number of argument the joinpoint has (excludes JoinPoint, Rtti, this / target) but is only
2348     * the number of argument we will have in the rtti (advised method/ctor args or 1 for field / handler)
2349     *
2350     * @return
2351     */

2352    protected final boolean hasArguments() {
2353        return m_argumentTypes.length > 0;
2354    }
2355
2356    /**
2357     * Checks if at least one advice is using this or target (bounded or runtime check)
2358     *
2359     * @return true if so
2360     */

2361    protected boolean requiresThisOrTarget() {
2362        return m_isThisAdvisable ||
2363               requiresThisOrTarget(m_aroundAdviceMethodInfos) ||
2364               requiresThisOrTarget(m_beforeAdviceMethodInfos) ||
2365               requiresThisOrTarget(m_afterFinallyAdviceMethodInfos) ||
2366               requiresThisOrTarget(m_afterReturningAdviceMethodInfos) ||
2367               requiresThisOrTarget(m_afterThrowingAdviceMethodInfos);
2368    }
2369
2370    /**
2371     * Checks if at least one advice is using the non static JoinPoint explicitly
2372     *
2373     * @return true if so
2374     */

2375    protected boolean requiresJoinPoint() {
2376        return m_isThisAdvisable ||
2377               requiresJoinPoint(m_aroundAdviceMethodInfos) ||
2378               requiresJoinPoint(m_beforeAdviceMethodInfos) ||
2379               requiresJoinPoint(m_afterFinallyAdviceMethodInfos) ||
2380               requiresJoinPoint(m_afterReturningAdviceMethodInfos) ||
2381               requiresJoinPoint(m_afterThrowingAdviceMethodInfos);
2382    }
2383
2384    /**
2385     * Checks if at least one advice is using target or this (bounded or runtime check)
2386     *
2387     * @param adviceMethodInfos
2388     * @return true if so
2389     */

2390    protected boolean requiresThisOrTarget(final AdviceMethodInfo[] adviceMethodInfos) {
2391        for (int i = 0; i < adviceMethodInfos.length; i++) {
2392            if (adviceMethodInfos[i].requiresThisOrTarget()) {
2393                return true;
2394            }
2395        }
2396        return false;
2397    }
2398
2399    /**
2400     * Checks if at least one advice is using non static JoinPoint explicitly
2401     *
2402     * @param adviceMethodInfos
2403     * @return true if so
2404     */

2405    protected boolean requiresJoinPoint(final AdviceMethodInfo[] adviceMethodInfos) {
2406        for (int i = 0; i < adviceMethodInfos.length; i++) {
2407            if (adviceMethodInfos[i].requiresJoinPoint()) {
2408                return true;
2409            }
2410        }
2411        return false;
2412    }
2413
2414    /**
2415     * Handles the if case for runtime check (target instanceof, cflow)
2416     *
2417     * @param cv
2418     * @param isOptimizedJoinPoint
2419     * @param joinPointInstanceIndex
2420     * @param adviceInfo
2421     * @return the label for endIf or null if the adviceInfo did not required runtime check
2422     */

2423    protected Label beginRuntimeCheck(final CodeVisitor cv,
2424                                      final boolean isOptimizedJoinPoint,
2425                                      final int joinPointInstanceIndex,
2426                                      final AdviceInfo adviceInfo,
2427                                      final int calleeIndex) {
2428        Label endRuntimeCheckLabel = null;
2429        if (adviceInfo.hasTargetWithRuntimeCheck() || adviceInfo.getAdviceDefinition().hasCflowOrCflowBelow()) {
2430            endRuntimeCheckLabel = new Label();
2431            // create a specific visitor everytime
2432
RuntimeCheckVisitor runtimeCheckVisitor = new RuntimeCheckVisitor(
2433                    this, cv, adviceInfo.getExpressionInfo(), isOptimizedJoinPoint, joinPointInstanceIndex,
2434                    calleeIndex
2435            );
2436            runtimeCheckVisitor.pushCheckOnStack(adviceInfo.getExpressionContext());
2437            cv.visitJumpInsn(IFEQ, endRuntimeCheckLabel);
2438        }
2439        return endRuntimeCheckLabel;
2440    }
2441
2442    /**
2443     * Ends the ifLabel of a runtime check
2444     *
2445     * @param cv
2446     * @param adviceInfo
2447     * @param label if null, then do nothing (means we did not had a runtime check)
2448     */

2449    protected void endRuntimeCheck(final CodeVisitor cv, final AdviceInfo adviceInfo, final Label label) {
2450        if (adviceInfo.hasTargetWithRuntimeCheck() || adviceInfo.getAdviceDefinition().hasCflowOrCflowBelow()) {
2451            cv.visitLabel(label);
2452        }
2453    }
2454
2455    /**
2456     * Helper method to load the callee on the stack
2457     *
2458     * @param cv
2459     * @param isOptimizedJoinPoint
2460     * @param joinPointIndex
2461     * @param calleeIndex
2462     */

2463    public void loadCallee(final CodeVisitor cv,
2464                           final boolean isOptimizedJoinPoint,
2465                           final int joinPointIndex,
2466                           final int calleeIndex) {
2467        if (isOptimizedJoinPoint) {
2468            // grab the callee from the invoke parameters directly
2469
cv.visitVarInsn(ALOAD, calleeIndex);
2470        } else {
2471            loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
2472            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2473        }
2474    }
2475
2476    /**
2477     * Helper method to load the caller on the stack
2478     *
2479     * @param cv
2480     * @param isOptimizedJoinPoint
2481     * @param joinPointIndex
2482     * @param callerIndex
2483     */

2484    protected void loadCaller(final CodeVisitor cv,
2485                              final boolean isOptimizedJoinPoint,
2486                              final int joinPointIndex,
2487                              final int callerIndex) {
2488        if (isOptimizedJoinPoint) {
2489            // grab the callee from the invoke parameters directly
2490
cv.visitVarInsn(ALOAD, callerIndex);
2491        } else {
2492            loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
2493            cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2494        }
2495    }
2496
2497    /**
2498     * Loads the aspect instance.
2499     *
2500     * @param cv
2501     * @param isOptimizedJoinPoint
2502     * @param joinPointIndex
2503     * @param aspectInfo
2504     */

2505    protected void loadAspect(final CodeVisitor cv,
2506                              final boolean isOptimizedJoinPoint,
2507                              final int joinPointIndex,
2508                              final AspectInfo aspectInfo) {
2509        DeploymentModel deploymentModel = aspectInfo.getDeploymentModel();
2510        if (deploymentModel.equals(DeploymentModel.PER_JVM) ||
2511            deploymentModel.equals(DeploymentModel.PER_CLASS)) {
2512            cv.visitFieldInsn(
2513                    GETSTATIC, m_joinPointClassName, aspectInfo.getAspectFieldName(),
2514                    aspectInfo.getAspectClassSignature()
2515            );
2516        } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) {
2517            loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
2518            cv.visitFieldInsn(
2519                    GETFIELD, m_joinPointClassName, aspectInfo.getAspectFieldName(),
2520                    aspectInfo.getAspectClassSignature()
2521            );
2522        } else {
2523            throw new DefinitionException("deployment model [" + deploymentModel + "] is not supported");
2524        }
2525    }
2526
2527    /**
2528     * Creates an invocation to Aspects.aspectOf(..).
2529     *
2530     * @param cv
2531     * @param isOptimizedJoinPoint
2532     * @param joinPointIndex
2533     * @param callerIndex
2534     * @param calleeIndex
2535     * @param aspectInfo
2536     */

2537    public void createInvocationToAspectOf(final CodeVisitor cv,
2538                                           final boolean isOptimizedJoinPoint,
2539                                           final int joinPointIndex,
2540                                           final int callerIndex,
2541                                           final int calleeIndex,
2542                                           final AspectInfo aspectInfo) {
2543        if (aspectInfo.getDeploymentModel() == DeploymentModel.PER_INSTANCE) {
2544
2545            //generates code: aspectField = (cast) Aspects.aspect$Of(aspectQN, containerClassName, callee)
2546
loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
2547            cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
2548            if (calleeIndex >= 0) {
2549                cv.visitVarInsn(ALOAD, calleeIndex);
2550                cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
2551                cv.visitMethodInsn(
2552                        INVOKESTATIC,
2553                        ASPECTS_CLASS_NAME,
2554                        ASPECT_OF_METHOD_NAME,
2555                        ASPECT_OF_PER_INSTANCE_METHOD_SIGNATURE
2556                );
2557            } else {
2558                // TODO: should this really happen? we are filtering at early stage now. - REMOVE CODE BLOCK
2559
// fallback to perClass
2560
//aspectField = (cast) Aspects.aspectOf(aspectQN, containerClass, calleeClass)
2561
cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2562                cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
2563                cv.visitMethodInsn(
2564                        INVOKESTATIC,
2565                        ASPECTS_CLASS_NAME,
2566                        ASPECT_OF_METHOD_NAME,
2567                        ASPECT_OF_PER_CLASS_METHOD_SIGNATURE
2568                );
2569            }
2570            cv.visitTypeInsn(CHECKCAST, aspectInfo.getAspectClassName());
2571            cv.visitFieldInsn(
2572                    PUTFIELD, m_joinPointClassName, aspectInfo.getAspectFieldName(),
2573                    aspectInfo.getAspectClassSignature()
2574            );
2575        }
2576    }
2577
2578    /**
2579     * Generates code needed for handling Advisable management for the target class.
2580     *
2581     * @param cv
2582     * @param joinPointInstanceIndex
2583     * @param advisableIndex
2584     */

2585    private void createInitializationForAdvisableManagement(final CodeVisitor cv,
2586                                                            final int joinPointInstanceIndex,
2587                                                            final int advisableIndex) {
2588        // interceptor index
2589
cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2590        cv.visitInsn(ICONST_M1);
2591        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2592
2593        initializeAroundInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2594        initializeBeforeInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2595        initializeAfterInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2596        initializeAfterReturningInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2597        initializeAfterThrowingInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2598    }
2599
2600    /**
2601     * Handle the around interceptor init.
2602     *
2603     * @param cv
2604     * @param joinPointInstanceIndex
2605     * @param advisableIndex
2606     */

2607    private void initializeAroundInterceptors(final CodeVisitor cv,
2608                                              final int joinPointInstanceIndex,
2609                                              final int advisableIndex) {
2610        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2611        cv.visitVarInsn(ALOAD, advisableIndex);
2612        cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2613        cv.visitLdcInsn(new Integer JavaDoc(m_joinPointClassName.hashCode()));
2614        cv.visitMethodInsn(
2615                INVOKEINTERFACE,
2616                ADVISABLE_CLASS_NAME,
2617                GET_AROUND_ADVICE_METHOD_NAME,
2618                GET_AROUND_ADVICE_METHOD_SIGNATURE
2619        );
2620        cv.visitFieldInsn(
2621                PUTFIELD,
2622                m_joinPointClassName,
2623                AROUND_INTERCEPTORS_FIELD_NAME,
2624                AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2625        );
2626
2627        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2628        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2629        cv.visitFieldInsn(
2630                GETFIELD,
2631                m_joinPointClassName,
2632                AROUND_INTERCEPTORS_FIELD_NAME,
2633                AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2634        );
2635        cv.visitInsn(ARRAYLENGTH);
2636        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2637    }
2638
2639    /**
2640     * Handle the before interceptor init.
2641     *
2642     * @param cv
2643     * @param joinPointInstanceIndex
2644     * @param advisableIndex
2645     */

2646    private void initializeBeforeInterceptors(final CodeVisitor cv,
2647                                              final int joinPointInstanceIndex,
2648                                              final int advisableIndex) {
2649        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2650        cv.visitVarInsn(ALOAD, advisableIndex);
2651        cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2652        cv.visitLdcInsn(new Integer JavaDoc(m_joinPointClassName.hashCode()));
2653        cv.visitMethodInsn(
2654                INVOKEINTERFACE,
2655                ADVISABLE_CLASS_NAME,
2656                GET_BEFORE_ADVICE_METHOD_NAME,
2657                GET_BEFORE_ADVICE_METHOD_SIGNATURE
2658        );
2659        cv.visitFieldInsn(
2660                PUTFIELD,
2661                m_joinPointClassName,
2662                BEFORE_INTERCEPTORS_FIELD_NAME,
2663                BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2664        );
2665
2666        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2667        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2668        cv.visitFieldInsn(
2669                GETFIELD,
2670                m_joinPointClassName,
2671                BEFORE_INTERCEPTORS_FIELD_NAME,
2672                BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2673        );
2674        cv.visitInsn(ARRAYLENGTH);
2675        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2676    }
2677
2678    /**
2679     * Handle the after finally interceptor init.
2680     *
2681     * @param cv
2682     * @param joinPointInstanceIndex
2683     * @param advisableIndex
2684     */

2685    private void initializeAfterInterceptors(final CodeVisitor cv,
2686                                             final int joinPointInstanceIndex,
2687                                             final int advisableIndex) {
2688        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2689        cv.visitVarInsn(ALOAD, advisableIndex);
2690        cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2691        cv.visitLdcInsn(new Integer JavaDoc(m_joinPointClassName.hashCode()));
2692        cv.visitMethodInsn(
2693                INVOKEINTERFACE,
2694                ADVISABLE_CLASS_NAME,
2695                GET_AFTER_ADVICE_METHOD_NAME,
2696                GET_AFTER_ADVICE_METHOD_SIGNATURE
2697        );
2698        cv.visitFieldInsn(
2699                PUTFIELD,
2700                m_joinPointClassName,
2701                AFTER_INTERCEPTORS_FIELD_NAME,
2702                AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2703        );
2704
2705        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2706        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2707        cv.visitFieldInsn(
2708                GETFIELD,
2709                m_joinPointClassName,
2710                AFTER_INTERCEPTORS_FIELD_NAME,
2711                AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2712        );
2713        cv.visitInsn(ARRAYLENGTH);
2714        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2715    }
2716
2717    /**
2718     * Handle the after returning interceptor init.
2719     *
2720     * @param cv
2721     * @param joinPointInstanceIndex
2722     * @param advisableIndex
2723     */

2724    private void initializeAfterReturningInterceptors(final CodeVisitor cv,
2725                                                      final int joinPointInstanceIndex,
2726                                                      final int advisableIndex) {
2727        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2728        cv.visitVarInsn(ALOAD, advisableIndex);
2729        cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2730        cv.visitLdcInsn(new Integer JavaDoc(m_joinPointClassName.hashCode()));
2731        cv.visitMethodInsn(
2732                INVOKEINTERFACE,
2733                ADVISABLE_CLASS_NAME,
2734                GET_AFTER_RETURNING_ADVICE_METHOD_NAME,
2735                GET_AFTER_RETURNING_ADVICE_METHOD_SIGNATURE
2736        );
2737        cv.visitFieldInsn(
2738                PUTFIELD,
2739                m_joinPointClassName,
2740                AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2741                AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2742        );
2743
2744        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2745        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2746        cv.visitFieldInsn(
2747                GETFIELD,
2748                m_joinPointClassName,
2749                AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2750                AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2751        );
2752        cv.visitInsn(ARRAYLENGTH);
2753        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2754    }
2755
2756    /**
2757     * Handle the after throwing interceptor init.
2758     *
2759     * @param cv
2760     * @param joinPointInstanceIndex
2761     * @param advisableIndex
2762     */

2763    private void initializeAfterThrowingInterceptors(final CodeVisitor cv,
2764                                                     final int joinPointInstanceIndex,
2765                                                     final int advisableIndex) {
2766        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2767        cv.visitVarInsn(ALOAD, advisableIndex);
2768        cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2769        cv.visitLdcInsn(new Integer JavaDoc(m_joinPointClassName.hashCode()));
2770        cv.visitMethodInsn(
2771                INVOKEINTERFACE,
2772                ADVISABLE_CLASS_NAME,
2773                GET_AFTER_THROWING_ADVICE_METHOD_NAME,
2774                GET_AFTER_THROWING_ADVICE_METHOD_SIGNATURE
2775        );
2776        cv.visitFieldInsn(
2777                PUTFIELD,
2778                m_joinPointClassName,
2779                AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2780                AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2781        );
2782
2783        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2784        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2785        cv.visitFieldInsn(
2786                GETFIELD,
2787                m_joinPointClassName,
2788                AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2789                AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2790        );
2791        cv.visitInsn(ARRAYLENGTH);
2792        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2793    }
2794
2795    /**
2796     * Handles the around interceptor invocations.
2797     *
2798     * @param cv
2799     */

2800    private void createAroundInterceptorInvocations(final CodeVisitor cv) {
2801        cv.visitVarInsn(ALOAD, 0);
2802        cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2803        cv.visitInsn(ICONST_M1);
2804        Label ifStatementLabel = new Label();
2805        cv.visitJumpInsn(IF_ICMPEQ, ifStatementLabel);
2806        cv.visitVarInsn(ALOAD, 0);
2807        cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2808        cv.visitVarInsn(ALOAD, 0);
2809        cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2810        cv.visitJumpInsn(IF_ICMPGE, ifStatementLabel);
2811        cv.visitVarInsn(ALOAD, 0);
2812        cv.visitFieldInsn(
2813                GETFIELD,
2814                m_joinPointClassName,
2815                AROUND_INTERCEPTORS_FIELD_NAME,
2816                AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2817        );
2818        cv.visitVarInsn(ALOAD, 0);
2819        cv.visitInsn(DUP);
2820        cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2821        cv.visitInsn(DUP_X1);
2822        cv.visitInsn(ICONST_1);
2823        cv.visitInsn(IADD);
2824        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2825        cv.visitInsn(AALOAD);
2826        cv.visitVarInsn(ALOAD, 0);
2827        cv.visitMethodInsn(
2828                INVOKEINTERFACE,
2829                AROUND_ADVICE_CLASS_NAME,
2830                INTERCEPT_INVOKE_METHOD_NAME,
2831                AROUND_ADVICE_INVOKE_METHOD_SIGNATURE
2832        );
2833        cv.visitInsn(ARETURN);
2834        cv.visitLabel(ifStatementLabel);
2835    }
2836
2837    /**
2838     * Creates invocations fo the before interceptors.
2839     *
2840     * @param cv
2841     * @param joinPointInstanceIndex
2842     * @param registerDepth
2843     */

2844    private void createBeforeInterceptorInvocations(final CodeVisitor cv,
2845                                                    final int joinPointInstanceIndex,
2846                                                    final int registerDepth) {
2847        final int loopIndex = registerDepth + 1;
2848        cv.visitInsn(ICONST_0);
2849        cv.visitVarInsn(ISTORE, loopIndex);
2850        Label loopStartLabel = new Label();
2851        cv.visitLabel(loopStartLabel);
2852        cv.visitVarInsn(ILOAD, loopIndex);
2853        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2854        cv.visitFieldInsn(
2855                GETFIELD,
2856                m_joinPointClassName,
2857                NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME,
2858                I
2859        );
2860        Label loopCheckCondLabel = new Label();
2861        cv.visitJumpInsn(IF_ICMPGE, loopCheckCondLabel);
2862        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2863        cv.visitFieldInsn(
2864                GETFIELD,
2865                m_joinPointClassName,
2866                BEFORE_INTERCEPTORS_FIELD_NAME,
2867                BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2868        );
2869        cv.visitVarInsn(ILOAD, loopIndex);
2870        cv.visitInsn(AALOAD);
2871        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2872        cv.visitMethodInsn(
2873                INVOKEINTERFACE,
2874                BEFORE_ADVICE_CLASS_NAME,
2875                INTERCEPT_INVOKE_METHOD_NAME,
2876                BEFORE_ADVICE_INVOKE_METHOD_SIGNATURE
2877        );
2878        cv.visitIincInsn(loopIndex, 1);
2879        cv.visitJumpInsn(GOTO, loopStartLabel);
2880        cv.visitLabel(loopCheckCondLabel);
2881    }
2882
2883    /**
2884     * Creates invocations fo the after finally interceptors.
2885     *
2886     * @param cv
2887     * @param joinPointInstanceIndex
2888     * @param registerDepth
2889     */

2890    private void createAfterInterceptorInvocations(final CodeVisitor cv,
2891                                                   final int joinPointInstanceIndex,
2892                                                   final int registerDepth) {
2893        final int loopIndex = registerDepth + 1;
2894        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2895        cv.visitFieldInsn(
2896                GETFIELD,
2897                m_joinPointClassName,
2898                NR_OF_AFTER_INTERCEPTORS_FIELD_NAME,
2899                I
2900        );
2901        cv.visitInsn(ICONST_1);
2902        cv.visitInsn(ISUB);
2903        cv.visitVarInsn(ISTORE, loopIndex);
2904        Label loopLabel1 = new Label();
2905        cv.visitLabel(loopLabel1);
2906        cv.visitVarInsn(ILOAD, loopIndex);
2907        Label loopLabel2 = new Label();
2908        cv.visitJumpInsn(IFLT, loopLabel2);
2909        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2910        cv.visitFieldInsn(
2911                GETFIELD,
2912                m_joinPointClassName,
2913                AFTER_INTERCEPTORS_FIELD_NAME,
2914                AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2915        );
2916        cv.visitVarInsn(ILOAD, loopIndex);
2917        cv.visitInsn(AALOAD);
2918        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2919        cv.visitMethodInsn(
2920                INVOKEINTERFACE,
2921                AFTER_ADVICE_CLASS_NAME,
2922                INTERCEPT_INVOKE_METHOD_NAME,
2923                AFTER_ADVICE_INVOKE_METHOD_SIGNATURE
2924        );
2925        cv.visitIincInsn(loopIndex, -1);
2926        cv.visitJumpInsn(GOTO, loopLabel1);
2927        cv.visitLabel(loopLabel2);
2928    }
2929
2930    /**
2931     * Creates invocations fo the after returning interceptors.
2932     *
2933     * @param cv
2934     * @param joinPointInstanceIndex
2935     * @param returnValueInstanceIndex
2936     */

2937    private void createAfterReturningInterceptorInvocations(final CodeVisitor cv,
2938                                                            final int joinPointInstanceIndex,
2939                                                            final int returnValueInstanceIndex) {
2940        final int loopIndex = returnValueInstanceIndex + 1;
2941        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2942        cv.visitFieldInsn(
2943                GETFIELD,
2944                m_joinPointClassName,
2945                NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2946                I
2947        );
2948        cv.visitInsn(ICONST_1);
2949        cv.visitInsn(ISUB);
2950        cv.visitVarInsn(ISTORE, loopIndex);
2951        Label loopLabel1 = new Label();
2952        cv.visitLabel(loopLabel1);
2953        cv.visitVarInsn(ILOAD, loopIndex);
2954        Label loopLabel2 = new Label();
2955        cv.visitJumpInsn(IFLT, loopLabel2);
2956        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2957        cv.visitFieldInsn(
2958                GETFIELD,
2959                m_joinPointClassName,
2960                AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2961                AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2962        );
2963        cv.visitVarInsn(ILOAD, loopIndex);
2964        cv.visitInsn(AALOAD);
2965        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2966        cv.visitVarInsn(ALOAD, returnValueInstanceIndex);
2967        cv.visitMethodInsn(
2968                INVOKEINTERFACE,
2969                AFTER_RETURNING_ADVICE_CLASS_NAME,
2970                INTERCEPT_INVOKE_METHOD_NAME,
2971                AFTER_RETURNING_ADVICE_INVOKE_METHOD_SIGNATURE
2972        );
2973        cv.visitIincInsn(loopIndex, -1);
2974        cv.visitJumpInsn(GOTO, loopLabel1);
2975        cv.visitLabel(loopLabel2);
2976    }
2977
2978    /**
2979     * Creates invocations fo the after returning interceptors.
2980     *
2981     * @param cv
2982     * @param joinPointInstanceIndex
2983     * @param exceptionInstanceIndex
2984     */

2985    private void createAfterThrowingInterceptorInvocations(final CodeVisitor cv,
2986                                                           final int joinPointInstanceIndex,
2987                                                           final int exceptionInstanceIndex) {
2988        final int loopIndex = exceptionInstanceIndex + 1;
2989        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2990        cv.visitFieldInsn(
2991                GETFIELD,
2992                m_joinPointClassName,
2993                NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2994                I
2995        );
2996        cv.visitInsn(ICONST_1);
2997        cv.visitInsn(ISUB);
2998        cv.visitVarInsn(ISTORE, loopIndex);
2999        Label loopLabel1 = new Label();
3000        cv.visitLabel(loopLabel1);
3001        cv.visitVarInsn(ILOAD, loopIndex);
3002        Label loopLabel2 = new Label();
3003        cv.visitJumpInsn(IFLT, loopLabel2);
3004        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
3005        cv.visitFieldInsn(
3006                GETFIELD,
3007                m_joinPointClassName,
3008                AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
3009                AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
3010        );
3011        cv.visitVarInsn(ILOAD, loopIndex);
3012        cv.visitInsn(AALOAD);
3013        cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
3014        cv.visitVarInsn(ALOAD, exceptionInstanceIndex);
3015        cv.visitMethodInsn(
3016                INVOKEINTERFACE,
3017                AFTER_THROWING_ADVICE_CLASS_NAME,
3018                INTERCEPT_INVOKE_METHOD_NAME,
3019                AFTER_THROWING_ADVICE_INVOKE_METHOD_SIGNATURE
3020        );
3021        cv.visitIincInsn(loopIndex, -1);
3022        cv.visitJumpInsn(GOTO, loopLabel1);
3023        cv.visitLabel(loopLabel2);
3024    }
3025
3026    /**
3027     * Checks if the join point requires a proceed() method.
3028     *
3029     * @return
3030     */

3031    protected boolean requiresProceedMethod() {
3032        return m_hasAroundAdvices || m_isThisAdvisable;
3033    }
3034
3035    private static class CustomProceedMethodStruct {
3036        MethodInfo customProceed;
3037        int[] adviceToTargetArgs;
3038
3039        public CustomProceedMethodStruct(MethodInfo customProceed, int[] adviceToTargetArgs) {
3040            this.customProceed = customProceed;
3041            this.adviceToTargetArgs = adviceToTargetArgs;
3042        }
3043    }
3044}
Popular Tags