KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > aspectwerkz > transform > inlining > compiler > AbstractJoinPointCompiler


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.aspectwerkz.transform.inlining.compiler;
5
6 import com.tc.asm.ClassWriter;
7 import com.tc.asm.MethodVisitor;
8 import com.tc.asm.Label;
9 import com.tc.asm.Type;
10
11 import com.tc.aspectwerkz.DeploymentModel;
12 import com.tc.aspectwerkz.reflect.ClassInfo;
13 import com.tc.aspectwerkz.aspect.AdviceInfo;
14 import com.tc.aspectwerkz.aspect.container.AspectFactoryManager;
15 import com.tc.aspectwerkz.definition.AspectDefinition;
16 import com.tc.aspectwerkz.joinpoint.management.AdviceInfoContainer;
17 import com.tc.aspectwerkz.joinpoint.management.JoinPointType;
18 import com.tc.aspectwerkz.transform.JoinPointCompiler;
19 import com.tc.aspectwerkz.transform.Properties;
20 import com.tc.aspectwerkz.transform.TransformationConstants;
21 import com.tc.aspectwerkz.transform.inlining.AdviceMethodInfo;
22 import com.tc.aspectwerkz.transform.inlining.AsmHelper;
23 import com.tc.aspectwerkz.transform.inlining.AspectInfo;
24 import com.tc.aspectwerkz.transform.inlining.AspectModelManager;
25 import com.tc.aspectwerkz.transform.inlining.EmittedJoinPoint;
26 import com.tc.aspectwerkz.transform.inlining.spi.AspectModel;
27
28
29 import java.lang.reflect.InvocationTargetException JavaDoc;
30 import java.lang.reflect.Modifier JavaDoc;
31 import java.util.ArrayList JavaDoc;
32 import java.util.HashMap JavaDoc;
33 import java.util.HashSet JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Map JavaDoc;
37 import java.util.Set JavaDoc;
38
39 /**
40  * Abstract base class for the different join point compiler implementations.
41  * <p/>
42  * Compiles/generates a class that represents a specific join point, a class which invokes the advices
43  * and the target join point statically.
44  * <p/>
45  * FIXME: depending on hotswap needs, remove the implements StaticJP or JP decision
46  *
47  * @author <a HREF="mailto:jboner@codehaus.org">Jonas BonŽr </a>
48  * @author <a HREF="mailto:alex AT gnilux DOT com">Alexandre Vasseur </a>
49  * @author <a HREF="mailto:the_mindstorm@evolva.ro">Alex Popescu</a>
50  */

51 public abstract class AbstractJoinPointCompiler implements JoinPointCompiler, TransformationConstants {
52
53   public static final boolean DUMP_JP_CLASSES = Properties.DUMP_JIT_CLOSURES;
54
55   // FIXME get rid of public fields - re architect!!!!!!!!!!!!
56

57   protected final String JavaDoc m_callerClassName;
58   protected final String JavaDoc m_calleeClassName;
59   public final String JavaDoc m_callerClassSignature;
60   public final String JavaDoc m_calleeClassSignature;
61   public final String JavaDoc m_joinPointClassName;
62
63   protected final int m_joinPointType;
64   protected final int m_joinPointHash;
65   protected final String JavaDoc m_callerMethodName;
66   protected final String JavaDoc m_callerMethodDesc;
67   protected final int m_callerMethodModifiers;
68   protected final String JavaDoc m_calleeMemberName;
69   protected final String JavaDoc m_calleeMemberDesc;
70   protected final int m_calleeMemberModifiers;
71
72   private final CompilationInfo.Model m_model;
73
74   protected ClassWriter m_cw;
75   protected AspectInfo[] m_aspectInfos;
76   protected AspectModel[] m_aspectModels;
77   protected AdviceMethodInfo[] m_aroundAdviceMethodInfos;
78   protected AdviceMethodInfo[] m_beforeAdviceMethodInfos;
79   protected AdviceMethodInfo[] m_afterFinallyAdviceMethodInfos;
80   protected AdviceMethodInfo[] m_afterReturningAdviceMethodInfos;
81   protected AdviceMethodInfo[] m_afterThrowingAdviceMethodInfos;
82
83   protected boolean m_hasAroundAdvices = false;
84   protected boolean m_requiresThisOrTarget = false;
85   protected boolean m_requiresJoinPoint = false;
86   protected boolean m_requiresProceedMethod = false;
87
88   public String JavaDoc[] m_fieldNames;
89   public Type[] m_argumentTypes;
90   protected Type m_returnType;
91   protected boolean m_isThisAdvisable = false;
92
93   private CompilerInput m_input;
94
95   /**
96    * Creates a new join point compiler instance.
97    *
98    * @param model the compilation model
99    */

100   public AbstractJoinPointCompiler(final CompilationInfo.Model model) {
101     m_model = model;
102     m_joinPointClassName = model.getJoinPointClassName();
103
104     final EmittedJoinPoint emittedJoinPoint = model.getEmittedJoinPoint();
105
106     m_joinPointHash = emittedJoinPoint.getJoinPointHash();
107     m_joinPointType = emittedJoinPoint.getJoinPointType();
108
109     m_callerMethodName = emittedJoinPoint.getCallerMethodName();
110     m_callerMethodDesc = emittedJoinPoint.getCallerMethodDesc();
111     m_callerMethodModifiers = emittedJoinPoint.getCallerMethodModifiers();
112
113     m_calleeMemberName = emittedJoinPoint.getCalleeMemberName();
114     m_calleeMemberDesc = emittedJoinPoint.getCalleeMemberDesc();
115     m_calleeMemberModifiers = emittedJoinPoint.getCalleeMemberModifiers();
116
117     // NOTE: internal compiler class name format is ALWAYS using '/'
118
m_callerClassName = emittedJoinPoint.getCallerClassName().replace('.', '/');
119     m_calleeClassName = emittedJoinPoint.getCalleeClassName().replace('.', '/');
120     m_callerClassSignature = L + emittedJoinPoint.getCallerClassName().replace('.', '/') + SEMICOLON;
121     m_calleeClassSignature = L + emittedJoinPoint.getCalleeClassName().replace('.', '/') + SEMICOLON;
122
123     m_argumentTypes = getJoinPointArgumentTypes();
124     m_returnType = getJoinPointReturnType();
125
126     // collect information from the compilation model and setup the aspect model
127
initialize(model);
128
129     // prepare a CompilerInput instance that will host most of the arguments visible to the models
130
initializeCompilerInput();
131   }
132
133   //-- implementation of JoinPointCompiler
134
public String JavaDoc getCallerClassName() {
135     return m_callerClassName;
136   }
137
138   public String JavaDoc getCalleeClassName() {
139     return m_calleeClassName;
140   }
141
142   public String JavaDoc getCallerClassSignature() {
143     return m_callerClassSignature;
144   }
145
146   public String JavaDoc getCalleeClassSignature() {
147     return m_calleeClassSignature;
148   }
149
150   public String JavaDoc getJoinPointClassName() {
151     return m_joinPointClassName;
152   }
153
154   /**
155    * Initializes the the join point compiler.
156    *
157    * @param model the compilation model
158    */

159   private void initialize(final CompilationInfo.Model model) {
160     // collect the advices
161
final AdviceInfoContainer advices = model.getAdviceInfoContainer();
162     collectAdviceInfo(advices);
163
164     // setup models at the end so that they can override m_requiresJoinPoint
165
setupReferencedAspectModels();
166
167     // compute the optimization we can use
168
m_hasAroundAdvices = m_aroundAdviceMethodInfos.length > 0;
169     // check if 'caller'(this) is Advisable, e.g. can handle runtime per instance deployment
170
m_isThisAdvisable = isCallerAdvisable(model);
171     m_requiresThisOrTarget = requiresThisOrTarget();
172     m_requiresJoinPoint = requiresJoinPoint();
173     m_requiresProceedMethod = requiresProceedMethod();
174
175     m_cw = AsmHelper.newClassWriter(true);
176   }
177
178   /**
179    * Compute and store index and common information that can be passed thru the aspect model
180    */

181   private void initializeCompilerInput() {
182     m_input = new CompilerInput();
183
184     // signatures
185
m_input.calleeClassSignature = m_calleeClassSignature;
186     m_input.callerClassSignature = m_callerClassSignature;
187     m_input.joinPointClassName = m_joinPointClassName;
188
189     // compute the callee and caller index from the invoke(..) signature
190
m_input.calleeIndex = INDEX_NOTAVAILABLE;
191     m_input.argStartIndex = 0;
192     if (!Modifier.isStatic(m_calleeMemberModifiers) &&
193             m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT &&
194             m_joinPointType != JoinPointType.HANDLER_INT) {
195       m_input.calleeIndex = 0;
196       m_input.argStartIndex++;
197     } else {
198       // no callee in the invoke(..) parameters for static call/exe/getDefault/set, ctor call and handler jp
199
m_input.calleeIndex = INDEX_NOTAVAILABLE;
200     }
201     // caller is always last
202
m_input.callerIndex = m_input.argStartIndex + AsmHelper.getRegisterDepth(m_argumentTypes);
203
204     // custom logic overrides for handler jp
205
if (m_joinPointType == JoinPointType.HANDLER_INT) {
206       m_input.calleeIndex = 0;
207       m_input.callerIndex = 2;
208       m_input.argStartIndex = 1;
209     }
210
211     // optimization level
212
// do we need to keep track of CALLEE, ARGS etc, if not then completely skip it
213
// and make use of the optimized join point instance
214
// while not using its fields (does not support reentrancy and thread safety)
215
m_input.isOptimizedJoinPoint = !m_requiresJoinPoint && !m_requiresProceedMethod;
216     if (m_input.isOptimizedJoinPoint) {
217       // we will use the static field that host the sole jp shared instance
218
m_input.joinPointInstanceIndex = INDEX_NOTAVAILABLE;
219     } else {
220       // joinpoint will be new() and stored on first local var
221
m_input.joinPointInstanceIndex = m_input.callerIndex + 1;
222     }
223   }
224
225   /**
226    * Collects the advice info.
227    *
228    * @param advices
229    */

230   private void collectAdviceInfo(final AdviceInfoContainer advices) {
231     //final List aspectQualifiedNames = new ArrayList();// in fact a Set but we need indexOf
232
final Map JavaDoc aspectInfoByQualifiedName = new HashMap JavaDoc();
233     m_beforeAdviceMethodInfos = getAdviceMethodInfos(
234             aspectInfoByQualifiedName, advices.getBeforeAdviceInfos()
235     );
236     m_aroundAdviceMethodInfos = getAdviceMethodInfos(
237             aspectInfoByQualifiedName, advices.getAroundAdviceInfos()
238     );
239     m_afterReturningAdviceMethodInfos = getAdviceMethodInfos(
240             aspectInfoByQualifiedName, advices.getAfterReturningAdviceInfos()
241     );
242     m_afterFinallyAdviceMethodInfos = getAdviceMethodInfos(
243             aspectInfoByQualifiedName, advices.getAfterFinallyAdviceInfos()
244     );
245     m_afterThrowingAdviceMethodInfos = getAdviceMethodInfos(
246             aspectInfoByQualifiedName, advices.getAfterThrowingAdviceInfos()
247     );
248
249     m_aspectInfos = (AspectInfo[]) aspectInfoByQualifiedName.values().toArray(new AspectInfo[aspectInfoByQualifiedName.size()]);
250
251     //
252

253   }
254
255   /**
256    * Checks if the caller class implements the Advisable interface.
257    *
258    * @param model
259    */

260   private boolean isCallerAdvisable(final CompilationInfo.Model model) {
261     if (!Modifier.isStatic(m_callerMethodModifiers)) {
262       ClassInfo[] interfaces = model.getThisClassInfo().getInterfaces();
263       for (int i = 0; i < interfaces.length; i++) {
264         if (interfaces[i].getName().equals(ADVISABLE_CLASS_JAVA_NAME)) {
265           return true;
266         }
267       }
268     }
269     return false;
270   }
271
272   /**
273    * Retrieves and sets the aspect models that are referenced in this compilation phase.
274    */

275   private void setupReferencedAspectModels() {
276     Map JavaDoc aspectModelInstanceByType = new HashMap JavaDoc();
277     for (int i = 0; i < m_aspectInfos.length; i++) {
278       AspectDefinition aspectDef = m_aspectInfos[i].getAspectDefinition();
279       if (!aspectModelInstanceByType.containsKey(aspectDef.getAspectModel())) {
280         AspectModel aspectModel = AspectModelManager.getModelFor(aspectDef.getAspectModel()).getInstance(
281                 m_model
282         );
283         aspectModelInstanceByType.put(aspectDef.getAspectModel(), aspectModel);
284       }
285       // set the model for each aspect info for fast access
286
AspectModel aspectModel = (AspectModel) aspectModelInstanceByType.get(aspectDef.getAspectModel());
287       if (aspectModel == null) {
288         throw new Error JavaDoc("Could not find AspectModel " + aspectDef.getAspectModel() + " for " + m_aspectInfos[i].getAspectQualifiedName());
289       }
290       m_aspectInfos[i].setAspectModel(aspectModel);
291     }
292
293     // keep track of the model instance for fast acccess
294
m_aspectModels = (AspectModel[]) aspectModelInstanceByType.values().toArray(new AspectModel[]{});
295   }
296
297   /**
298    * Returns the join point interface class name.
299    *
300    * @return
301    */

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

319   private AdviceMethodInfo[] getAdviceMethodInfos(final Map JavaDoc aspectInfoByQualifiedName,
320                                                   final AdviceInfo[] adviceInfos) {
321     List JavaDoc adviceMethodInfosSet = new ArrayList JavaDoc();
322     for (int i = 0; i < adviceInfos.length; i++) {
323       AdviceInfo adviceInfo = adviceInfos[i];
324
325       // if we have a perinstance deployed aspect and a static member CALLER -> skip and go on
326
DeploymentModel deploymentModel = adviceInfo.getAspectDeploymentModel();
327
328       if (requiresCallerInstance(deploymentModel) && Modifier.isStatic(m_callerMethodModifiers)) {
329         continue;
330       }
331       if (requiresCalleeInstance(deploymentModel) && Modifier.isStatic(m_calleeMemberModifiers)) {
332         continue;
333       }
334
335       final String JavaDoc aspectClassName = adviceInfo.getAspectClassName().replace('.', '/');
336
337       final AspectInfo aspectInfo;
338       if (!aspectInfoByQualifiedName.containsKey(adviceInfo.getAspectQualifiedName())) {
339         aspectInfo = new AspectInfo(
340                 adviceInfo.getAdviceDefinition().getAspectDefinition(),
341                 ASPECT_FIELD_PREFIX + (aspectInfoByQualifiedName.size()),
342                 aspectClassName,
343                 L + aspectClassName + SEMICOLON
344         );
345         aspectInfoByQualifiedName.put(adviceInfo.getAspectQualifiedName(), aspectInfo);
346       } else {
347         aspectInfo = (AspectInfo) aspectInfoByQualifiedName.get(adviceInfo.getAspectQualifiedName());
348       }
349
350       AdviceMethodInfo adviceMethodInfo = new AdviceMethodInfo(
351               aspectInfo,
352               adviceInfo,
353               m_callerClassSignature,
354               m_calleeClassSignature,
355               m_joinPointClassName,
356               m_calleeMemberDesc
357       );
358       adviceMethodInfosSet.add(adviceMethodInfo);
359     }
360     return (AdviceMethodInfo[]) adviceMethodInfosSet.toArray(new AdviceMethodInfo[adviceMethodInfosSet.size()]);
361   }
362
363   /**
364    * Creates join point specific fields.
365    */

366   protected abstract void createJoinPointSpecificFields();
367
368   /**
369    * Creates the signature for the join point.
370    *
371    * @param cv
372    */

373   protected abstract void createSignature(final MethodVisitor cv);
374
375   /**
376    * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
377    * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
378    * exists.
379    *
380    * @param cv
381    * @param input
382    */

383   protected abstract void createInlinedJoinPointInvocation(final MethodVisitor cv,
384                                                            final CompilerInput input);
385
386   /**
387    * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
388    * local join point instance.
389    *
390    * @param cv
391    */

392   protected abstract void createJoinPointInvocation(final MethodVisitor cv);
393
394   /**
395    * Returns the join points return type.
396    *
397    * @return
398    */

399   protected abstract Type getJoinPointReturnType();
400
401   /**
402    * Returns the join points argument type(s).
403    *
404    * @return
405    */

406   protected abstract Type[] getJoinPointArgumentTypes();
407
408   /**
409    * Creates the getRtti method
410    */

411   protected abstract void createGetRttiMethod();
412
413   /**
414    * Creates the getSignature method
415    */

416   protected abstract void createGetSignatureMethod();
417
418   /**
419    * Compiles a join point class, one specific class for each distinct join point. The compiled join point class
420    * inherits the base join point class.
421    *
422    * @return the generated, compiled and loaded join point class
423    */

424   public final byte[] compile() {
425     try {
426       createClassHeader();
427       createFieldsCommonToAllJoinPoints();
428       createJoinPointSpecificFields();
429       createMandatoryMethodInAspectModels();
430       createStaticInitializer();
431       createClinit();
432       createInit();
433       createUtilityMethods();
434       createGetSignatureMethod();
435       createInvokeMethod();
436       if (m_requiresProceedMethod) {
437         // prepare a new CompilerInput since jp index changes when in proceed()
438
createProceedMethod(m_input.getCopyForProceed());
439       }
440       if (m_requiresJoinPoint) {
441         createGetRttiMethod();
442       }
443       m_cw.visitEnd();
444
445       if (DUMP_JP_CLASSES) {
446         AsmHelper.dumpClass(Properties.DUMP_DIR_CLOSURES, m_joinPointClassName, m_cw);
447       }
448       return m_cw.toByteArray();
449
450     } catch (Exception JavaDoc e) {
451       e.printStackTrace();
452       StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
453       buf.append("could not compile join point instance for join point with hash [");
454       buf.append(m_joinPointHash);
455       buf.append("] and declaring class [");
456       buf.append(m_callerClassName);
457       buf.append("] due to: ");
458       if (e instanceof InvocationTargetException JavaDoc) {
459         buf.append(((InvocationTargetException JavaDoc) e).getTargetException().toString());
460       } else {
461         buf.append(e.toString());
462       }
463       throw new RuntimeException JavaDoc(buf.toString());
464     }
465   }
466
467   /**
468    * Creates join point specific fields.
469    */

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

547   private void createClinit() {
548     MethodVisitor cv = m_cw.visitMethod(ACC_STATIC, CLINIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE, null, null);
549     cv.visitMethodInsn(
550             INVOKESTATIC, m_joinPointClassName,
551             STATIC_INITIALIZATION_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE
552     );
553     cv.visitInsn(RETURN);
554     cv.visitMaxs(0, 0);
555   }
556
557   /**
558    * Creates the init method for the join point.
559    */

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

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

639   private void createMandatoryMethodInAspectModels() {
640     for (int i = 0; i < m_aspectModels.length; i++) {
641       m_aspectModels[i].createMandatoryMethods(m_cw, this);
642     }
643   }
644
645   /**
646    * Creates the static initialization method (not clinit) for the join point.
647    */

648   private void createStaticInitializer() {
649     MethodVisitor cv = m_cw.visitMethod(
650             ACC_STATIC | ACC_PUBLIC,
651             STATIC_INITIALIZATION_METHOD_NAME,
652             NO_PARAM_RETURN_VOID_SIGNATURE,
653             null, null
654     );
655
656     Label tryLabel = new Label();
657     cv.visitLabel(tryLabel);
658     cv.visitLdcInsn(m_calleeClassName.replace('/', '.'));
659     cv.visitMethodInsn(INVOKESTATIC, CLASS_CLASS, FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
660     cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
661
662     cv.visitLdcInsn(m_callerClassName.replace('/', '.'));
663     cv.visitMethodInsn(INVOKESTATIC, CLASS_CLASS, FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
664     cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, THIS_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
665
666     Label finallyLabel = new Label();
667     cv.visitLabel(finallyLabel);
668
669     Label gotoFinallyLabel = new Label();
670     cv.visitJumpInsn(GOTO, gotoFinallyLabel);
671
672     Label catchLabel = new Label();
673     cv.visitLabel(catchLabel);
674     cv.visitVarInsn(ASTORE, 0);
675
676     cv.visitVarInsn(ALOAD, 0);
677     cv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Throwable", "printStackTrace", "()V");
678
679     cv.visitTypeInsn(NEW, RUNTIME_EXCEPTION_CLASS_NAME);
680     cv.visitInsn(DUP);
681     cv.visitLdcInsn(
682             "could not load target class using Class.forName() in generated join point base class "
683                     + m_joinPointClassName
684     );
685
686     cv.visitMethodInsn(
687             INVOKESPECIAL,
688             RUNTIME_EXCEPTION_CLASS_NAME,
689             INIT_METHOD_NAME,
690             RUNTIME_EXCEPTION_INIT_METHOD_SIGNATURE
691     );
692
693     cv.visitInsn(ATHROW);
694     cv.visitLabel(gotoFinallyLabel);
695
696     // create the enclosing static joinpoint
697
createEnclosingStaticJoinPoint(cv);
698
699     // create the metadata map
700
cv.visitTypeInsn(NEW, HASH_MAP_CLASS_NAME);
701     cv.visitInsn(DUP);
702     cv.visitMethodInsn(INVOKESPECIAL, HASH_MAP_CLASS_NAME, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
703     cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
704
705     // create the Signature instance
706
createSignature(cv);
707
708     // create the static JoinPoint instance
709
cv.visitTypeInsn(NEW, m_joinPointClassName);
710     cv.visitInsn(DUP);
711     cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
712     cv.visitFieldInsn(
713             PUTSTATIC,
714             m_joinPointClassName,
715             OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME,
716             L + m_joinPointClassName + SEMICOLON
717     );
718
719     // ensure aspect factories are all loaded
720
for (int i = 0; i < m_aspectInfos.length; i++) {
721       AspectInfo m_aspectInfo = m_aspectInfos[i];
722
723       cv.visitLdcInsn(m_aspectInfo.getAspectFactoryClassName());
724       cv.visitLdcInsn(m_aspectInfo.getAspectDefinition().getSystemDefinition().getUuid());
725       cv.visitLdcInsn(m_aspectInfo.getAspectClassName());
726       cv.visitLdcInsn(m_aspectInfo.getAspectQualifiedName());
727       AsmHelper.loadStringConstant(cv, m_aspectInfo.getAspectDefinition().getContainerClassName());
728       //TODO AVF do it once per aspect def
729
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
730       boolean hasOne = false;
731       boolean isFirst = true;
732       for (Iterator JavaDoc iterator = m_aspectInfo.getAspectDefinition().getParameters().entrySet().iterator(); iterator.hasNext();)
733       {
734         Map.Entry JavaDoc entry = (Map.Entry JavaDoc) iterator.next();
735         if (!isFirst) {
736           sb.append(DELIMITER);
737         }
738         isFirst = false;
739         hasOne = true;
740         sb.append(entry.getKey()).append(DELIMITER).append(entry.getValue());
741       }
742       if (hasOne) {
743         cv.visitLdcInsn(sb.toString());
744       } else {
745         cv.visitInsn(ACONST_NULL);
746       }
747       cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, THIS_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
748       cv.visitMethodInsn(INVOKEVIRTUAL, CLASS_CLASS, GETCLASSLOADER_METHOD_NAME, CLASS_CLASS_GETCLASSLOADER_METHOD_SIGNATURE);
749       cv.visitLdcInsn(m_aspectInfo.getDeploymentModel().toString());
750       cv.visitMethodInsn(
751               INVOKESTATIC,
752               Type.getInternalName(AspectFactoryManager.class),
753               "loadAspectFactory",
754               "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)V"
755       );
756     }
757
758     // create and initialize the aspect fields
759
for (int i = 0; i < m_aspectInfos.length; i++) {
760       m_aspectInfos[i].getAspectModel().createAndStoreStaticAspectInstantiation(
761               m_cw,
762               cv,
763               m_aspectInfos[i],
764               m_joinPointClassName
765       );
766     }
767
768     cv.visitInsn(RETURN);
769     cv.visitTryCatchBlock(tryLabel, finallyLabel, catchLabel, CLASS_NOT_FOUND_EXCEPTION_CLASS_NAME);
770     cv.visitMaxs(0, 0);
771   }
772
773   /**
774    * Add and initialize the static field for enclosing joint point static part
775    *
776    * @param cv
777    */

778   private void createEnclosingStaticJoinPoint(MethodVisitor cv) {
779     cv.visitFieldInsn(
780             GETSTATIC,
781             m_joinPointClassName,
782             THIS_CLASS_FIELD_NAME_IN_JP,
783             CLASS_CLASS_SIGNATURE
784     );
785     cv.visitLdcInsn(m_callerMethodName);
786     cv.visitLdcInsn(m_callerMethodDesc);
787
788     cv.visitMethodInsn(
789             INVOKESTATIC,
790             SIGNATURE_FACTORY_CLASS,
791             NEW_ENCLOSING_SJP_METHOD_NAME,
792             NEW_ENCLOSING_SJP_METHOD_SIGNATURE
793     );
794     cv.visitFieldInsn(
795             PUTSTATIC,
796             m_joinPointClassName,
797             ENCLOSING_SJP_FIELD_NAME,
798             ENCLOSING_SJP_FIELD_CLASS_SIGNATURE
799     );
800   }
801
802   /**
803    * Creates the 'invoke' method. If possible delegates to the target join point directly, e.g. does not invoke the
804    * 'proceed' method (Used when a join point has zero around advice).
805    * <p/>
806    * The implementation here is suitable for regular JP but not for delegating JP upon hotswap
807    */

808   protected void createInvokeMethod() {
809
810     final String JavaDoc invokeDesc = buildInvokeMethodSignature();
811
812     // create the method
813
MethodVisitor cv = m_cw.visitMethod(
814             ACC_PUBLIC + ACC_FINAL + ACC_STATIC,
815             INVOKE_METHOD_NAME,
816             invokeDesc,
817             null,
818             new String JavaDoc[]{
819                     THROWABLE_CLASS_NAME
820             }
821     );
822
823     if (!m_input.isOptimizedJoinPoint) {
824       // create a new JP and makes use of it
825
createInvocationLocalJoinPointInstance(cv, m_input);
826     }
827
828     //FIXME: see loadAspect and AssociationScopeTest_2_1456425365_738_9001546___AW_JoinPoint f.e.
829
// there is redundant checks because
830
// the system perObject aspect for a perX aspect will be called *AFTER* the initializeInstanceLevelAspects
831
// and thus the aspects.hasAspect will change in the middle of the invoke method
832
//
833
// flow should be: invoke perObject before aspect, init instance level, invoke all other before aspects
834
// we can wether have a createBeforeBefore(...) that checks for this perObject aspect
835

836     // initialize the instance level aspects (perInstance)
837
initializeInstanceLevelAspects(cv, m_input);
838
839     // before advices
840
createBeforeAdviceInvocations(cv, m_input);
841
842     // handle different combinations of after advice (finally/throwing/returning)
843
if (m_afterFinallyAdviceMethodInfos.length == 0 &&
844             m_afterThrowingAdviceMethodInfos.length == 0 &&
845             !m_isThisAdvisable) {
846       createPartOfInvokeMethodWithoutAfterFinallyAndAfterThrowingAdviceTypes(cv, m_input);
847     } else if (m_afterThrowingAdviceMethodInfos.length == 0 &&
848             !m_isThisAdvisable) {
849       createPartOfInvokeMethodWithoutAfterThrowingAdviceTypes(cv, m_input);
850     } else {
851       createPartOfInvokeMethodWithAllAdviceTypes(cv, m_input);
852     }
853
854     cv.visitMaxs(0, 0);
855   }
856
857   /**
858    * Initializes instance level aspects, retrieves them from the target instance through the
859    * <code>HasInstanceLevelAspect</code> interfaces.
860    * <p/>
861    * Use by 'perInstance', 'perThis' and 'perTarget' deployment models.
862    *
863    * @param cv
864    * @param input
865    */

866   private void initializeInstanceLevelAspects(final MethodVisitor cv, final CompilerInput input) {
867     for (int i = 0; i < m_aspectInfos.length; i++) {
868       m_aspectInfos[i].getAspectModel().createAndStoreRuntimeAspectInstantiation(cv, input, m_aspectInfos[i]);
869     }
870   }
871
872
873   /**
874    * @param cv
875    * @param input
876    */

877   private void createPartOfInvokeMethodWithAllAdviceTypes(final MethodVisitor cv,
878                                                           final CompilerInput input) {
879     final int returnValueIndex = (input.joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
880             (input.joinPointInstanceIndex + 1) : input.callerIndex + 1;
881     final int exceptionIndex1 = returnValueIndex + 1;
882     final int exceptionIndex2 = returnValueIndex + 2;
883
884     cv.visitInsn(ACONST_NULL);
885     cv.visitVarInsn(ASTORE, returnValueIndex);
886
887     Label tryLabel = new Label();
888     cv.visitLabel(tryLabel);
889     if (!m_requiresProceedMethod) {
890       // if no around advice then optimize by invoking the target JP directly and no call to proceed()
891
createInlinedJoinPointInvocation(cv, input);
892       int stackIndex = returnValueIndex;//use another int since storeType will update it
893
AsmHelper.storeType(cv, stackIndex, m_returnType);
894       addReturnedValueToJoinPoint(cv, input, returnValueIndex, false);
895     } else {
896       createInvocationToProceedMethod(cv, input.joinPointInstanceIndex, returnValueIndex);
897     }
898
899     createAfterReturningAdviceInvocations(cv, input);
900
901     Label finallyLabel1 = new Label();
902     cv.visitLabel(finallyLabel1);
903
904     if (m_isThisAdvisable) {
905       final int registerDepth = input.callerIndex + 2; // caller is using last register + possible return value
906
createAfterInterceptorInvocations(cv, input.joinPointInstanceIndex, registerDepth);
907     }
908     createAfterFinallyAdviceInvocations(cv, input);
909
910     Label gotoFinallyLabel = new Label();
911     cv.visitJumpInsn(GOTO, gotoFinallyLabel);
912
913     Label catchLabel = new Label();
914     cv.visitLabel(catchLabel);
915
916     // store the exception
917
cv.visitVarInsn(ASTORE, exceptionIndex1);
918
919     if (m_isThisAdvisable) {
920       createAfterThrowingInterceptorInvocations(cv, input.joinPointInstanceIndex, exceptionIndex1);
921     }
922
923     // loop over the after throwing advices
924
for (int i = m_afterThrowingAdviceMethodInfos.length - 1; i >= 0; i--) {
925       AdviceMethodInfo advice = m_afterThrowingAdviceMethodInfos[i];
926
927       // set the exception argument index
928
advice.setSpecialArgumentIndex(exceptionIndex1);
929
930       // if (e instanceof TYPE) {...}
931
cv.visitVarInsn(ALOAD, exceptionIndex1);
932
933       final String JavaDoc specialArgTypeName = advice.getSpecialArgumentTypeName();
934       if (specialArgTypeName != null) {
935         // after throwing <TYPE>
936
cv.visitTypeInsn(INSTANCEOF, specialArgTypeName);
937
938         Label ifInstanceOfLabel = new Label();
939         cv.visitJumpInsn(IFEQ, ifInstanceOfLabel);
940
941         // after throwing advice invocation
942
createAfterAdviceInvocation(cv, input, advice, exceptionIndex1);
943
944         cv.visitLabel(ifInstanceOfLabel);
945       } else {
946         // after throwing
947
createAfterAdviceInvocation(cv, input, advice, INDEX_NOTAVAILABLE);
948       }
949     }
950
951     // rethrow exception
952
cv.visitVarInsn(ALOAD, exceptionIndex1);
953     cv.visitInsn(ATHROW);
954
955     // store exception
956
Label exceptionLabel = new Label();
957     cv.visitLabel(exceptionLabel);
958     cv.visitVarInsn(ASTORE, exceptionIndex2);
959
960     // after finally advice invocation
961
Label finallyLabel2 = new Label();
962     cv.visitLabel(finallyLabel2);
963
964     if (m_isThisAdvisable) {
965       final int registerDepth = input.callerIndex + 2; // caller is using last register + possible return value
966
createAfterInterceptorInvocations(cv, input.joinPointInstanceIndex, registerDepth);
967     }
968     createAfterFinallyAdviceInvocations(cv, input);
969
970     // rethrow exception
971
cv.visitVarInsn(ALOAD, exceptionIndex2);
972     cv.visitInsn(ATHROW);
973     cv.visitLabel(gotoFinallyLabel);
974
975     // unwrap if around advice and return in all cases
976
if (m_returnType.getSort() != Type.VOID) {
977       if (m_requiresProceedMethod) {
978         cv.visitVarInsn(ALOAD, returnValueIndex);
979         AsmHelper.unwrapType(cv, m_returnType);
980       } else {
981         AsmHelper.loadType(cv, returnValueIndex, m_returnType);
982       }
983     }
984
985     AsmHelper.addReturnStatement(cv, m_returnType);
986
987     // build up the exception table
988
cv.visitTryCatchBlock(tryLabel, finallyLabel1, catchLabel, THROWABLE_CLASS_NAME);
989     cv.visitTryCatchBlock(tryLabel, finallyLabel1, exceptionLabel, null);
990     cv.visitTryCatchBlock(catchLabel, finallyLabel2, exceptionLabel, null);
991   }
992
993   /**
994    * @param cv
995    * @param input
996    */

997   private void createPartOfInvokeMethodWithoutAfterThrowingAdviceTypes(final MethodVisitor cv,
998                                                                        final CompilerInput input) {
999     final int returnValueIndex = (input.joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1000            (input.joinPointInstanceIndex + 1) : input.callerIndex + 1;
1001    final int exceptionIndex = returnValueIndex + 1;
1002
1003    cv.visitInsn(ACONST_NULL);
1004    cv.visitVarInsn(ASTORE, returnValueIndex);
1005
1006    Label tryLabel = new Label();
1007    cv.visitLabel(tryLabel);
1008    if (!m_requiresProceedMethod) {
1009      // if no around advice then optimize by invoking the target JP directly and no call to proceed()
1010
createInlinedJoinPointInvocation(cv, input);
1011      int stackIndex = returnValueIndex;//use another int since storeType will update it
1012
AsmHelper.storeType(cv, stackIndex, m_returnType);
1013      addReturnedValueToJoinPoint(cv, input, returnValueIndex, false);
1014    } else {
1015      createInvocationToProceedMethod(cv, input.joinPointInstanceIndex, returnValueIndex);
1016    }
1017
1018    createAfterReturningAdviceInvocations(cv, input);
1019
1020    Label finallyLabel1 = new Label();
1021    cv.visitLabel(finallyLabel1);
1022
1023    createAfterFinallyAdviceInvocations(cv, input);
1024
1025    Label gotoFinallyLabel = new Label();
1026    cv.visitJumpInsn(GOTO, gotoFinallyLabel);
1027
1028    Label exceptionLabel = new Label();
1029    cv.visitLabel(exceptionLabel);
1030    cv.visitVarInsn(ASTORE, exceptionIndex);
1031
1032    Label finallyLabel2 = new Label();
1033    cv.visitLabel(finallyLabel2);
1034
1035    createAfterFinallyAdviceInvocations(cv, input);
1036
1037    cv.visitVarInsn(ALOAD, exceptionIndex);
1038    cv.visitInsn(ATHROW);
1039
1040    cv.visitLabel(gotoFinallyLabel);
1041
1042    // unwrap if around advice and return in all cases
1043
if (m_returnType.getSort() != Type.VOID) {
1044      if (m_requiresProceedMethod) {
1045        cv.visitVarInsn(ALOAD, returnValueIndex);
1046        AsmHelper.unwrapType(cv, m_returnType);
1047      } else {
1048        AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1049      }
1050    }
1051
1052    AsmHelper.addReturnStatement(cv, m_returnType);
1053
1054    cv.visitTryCatchBlock(tryLabel, finallyLabel1, exceptionLabel, null);
1055    cv.visitTryCatchBlock(exceptionLabel, finallyLabel2, exceptionLabel, null);
1056  }
1057
1058  /**
1059   * @param cv
1060   * @param input
1061   */

1062  private void createPartOfInvokeMethodWithoutAfterFinallyAndAfterThrowingAdviceTypes(final MethodVisitor cv,
1063                                                                                      final CompilerInput input) {
1064
1065    final int returnValueIndex = (input.joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1066            (input.joinPointInstanceIndex + 1) : input.callerIndex + 1;
1067    if (!m_requiresProceedMethod) {
1068      // if no around advice then optimize by invoking the target JP directly and no call to proceed()
1069
createInlinedJoinPointInvocation(cv, input);
1070      int stackIndex = returnValueIndex;//use another int since storeType will update it
1071
AsmHelper.storeType(cv, stackIndex, m_returnType);
1072      addReturnedValueToJoinPoint(cv, input, returnValueIndex, false);
1073    } else {
1074      createInvocationToProceedMethod(cv, input.joinPointInstanceIndex, returnValueIndex);
1075    }
1076
1077    // after returning advice invocations
1078
createAfterReturningAdviceInvocations(cv, input);
1079
1080    // unwrap if around advice and return in all cases
1081
if (m_returnType.getSort() != Type.VOID) {
1082      if (m_requiresProceedMethod) {
1083        cv.visitVarInsn(ALOAD, returnValueIndex);
1084        AsmHelper.unwrapType(cv, m_returnType);
1085      } else {
1086        AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1087      }
1088    }
1089
1090    AsmHelper.addReturnStatement(cv, m_returnType);
1091  }
1092
1093  /**
1094   * Creates an invocation to the proceed method.
1095   *
1096   * @param cv
1097   * @param joinPointInstanceIndex
1098   * @param returnValueIndex
1099   */

1100  private void createInvocationToProceedMethod(final MethodVisitor cv,
1101                                               final int joinPointInstanceIndex,
1102                                               final int returnValueIndex) {
1103    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1104    cv.visitMethodInsn(INVOKEVIRTUAL, m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1105    cv.visitVarInsn(ASTORE, returnValueIndex);
1106  }
1107
1108  /**
1109   * Creates an "invocation local" join point instance, e.g. one join point per invocation. Needed for thread-safety
1110   * when invoking around advice.
1111   *
1112   * @param cv
1113   * @param input
1114   */

1115  private void createInvocationLocalJoinPointInstance(final MethodVisitor cv, final CompilerInput input) {
1116    // create the join point instance
1117
cv.visitTypeInsn(NEW, m_joinPointClassName);
1118    cv.visitInsn(DUP);
1119    cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
1120
1121    // store the jp on the stack
1122
cv.visitVarInsn(ASTORE, input.joinPointInstanceIndex);
1123
1124    // set the argument fields in the join point instance (jp.m_arg<i> = <arg_i>)
1125
int argStackIndex = input.argStartIndex;
1126    for (int i = 0; i < m_fieldNames.length; i++) {
1127      String JavaDoc fieldName = m_fieldNames[i];
1128      cv.visitVarInsn(ALOAD, input.joinPointInstanceIndex);
1129      Type type = m_argumentTypes[i];
1130      argStackIndex = AsmHelper.loadType(cv, argStackIndex, type);
1131      cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, fieldName, type.getDescriptor());
1132    }
1133
1134    // caller (can be assigned to null)
1135
cv.visitVarInsn(ALOAD, input.joinPointInstanceIndex);
1136    cv.visitVarInsn(ALOAD, input.callerIndex);
1137    cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1138
1139    // callee (can be not available)
1140
cv.visitVarInsn(ALOAD, input.joinPointInstanceIndex);
1141    if (input.calleeIndex != INDEX_NOTAVAILABLE) {
1142      cv.visitVarInsn(ALOAD, 0);
1143    } else {
1144      cv.visitInsn(ACONST_NULL);
1145    }
1146    cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1147
1148    if (m_isThisAdvisable) {
1149      createInitializationForAdvisableManagement(cv, input.joinPointInstanceIndex, input.callerIndex);
1150    }
1151  }
1152
1153  /**
1154   * Create the proceed() method.
1155   *
1156   * @param input a slightly different CompilerInput since jp index, is changed and caller and callee are meaningless
1157   * in the proceed() method.
1158   */

1159  private void createProceedMethod(CompilerInput input) {
1160
1161    MethodVisitor cv = m_cw.visitMethod(
1162            ACC_PUBLIC | ACC_FINAL,
1163            PROCEED_METHOD_NAME,
1164            PROCEED_METHOD_SIGNATURE,
1165            null,
1166            new String JavaDoc[]{
1167                    THROWABLE_CLASS_NAME
1168            }
1169    );
1170
1171    if (m_isThisAdvisable) {
1172      createAroundInterceptorInvocations(cv);
1173    }
1174
1175    incrementStackFrameCounter(cv);
1176
1177    // set up the labels
1178
Label tryLabel = new Label();
1179    Label defaultCaseLabel = new Label();
1180    Label gotoLabel = new Label();
1181    Label handlerLabel = new Label();
1182    Label endLabel = new Label();
1183
1184    int nrOfCases = m_aroundAdviceMethodInfos.length;
1185    if (m_isThisAdvisable) {
1186      nrOfCases++;
1187    }
1188
1189    Label[] caseLabels = new Label[nrOfCases];
1190    Label[] returnLabels = new Label[nrOfCases];
1191    int[] caseNumbers = new int[nrOfCases];
1192    for (int i = 0; i < caseLabels.length; i++) {
1193      caseLabels[i] = new Label();
1194      caseNumbers[i] = i;
1195    }
1196    for (int i = 0; i < returnLabels.length; i++) {
1197      returnLabels[i] = new Label();
1198    }
1199
1200    // start try-catch block
1201
cv.visitLabel(tryLabel);
1202
1203    // start the switch block and set the stackframe as the param to the switch
1204
cv.visitVarInsn(ALOAD, 0);
1205    cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1206    cv.visitLookupSwitchInsn(defaultCaseLabel, caseNumbers, caseLabels);
1207
1208    // add one case for each around advice invocation
1209
for (int i = 0; i < m_aroundAdviceMethodInfos.length; i++) {
1210      cv.visitLabel(caseLabels[i]);
1211
1212      // gather advice info
1213
AdviceMethodInfo adviceInfo = m_aroundAdviceMethodInfos[i];
1214
1215      Label endInstanceOflabel = beginRuntimeCheck(cv, input, adviceInfo.getAdviceInfo());
1216
1217      // getDefault the aspect instance
1218
adviceInfo.getAspectInfo().getAspectModel().loadAspect(cv, input, adviceInfo.getAspectInfo());
1219
1220      // load the arguments to the advice
1221
adviceInfo.getAspectInfo().getAspectModel().createAroundAdviceArgumentHandling(
1222              cv,
1223              input,
1224              m_argumentTypes,
1225              adviceInfo
1226      );
1227
1228      // invoke the advice method
1229
cv.visitMethodInsn(
1230              INVOKEVIRTUAL,
1231              adviceInfo.getAspectInfo().getAspectClassName(),
1232              adviceInfo.getAdviceInfo().getMethodName(),
1233              adviceInfo.getAdviceInfo().getMethodSignature()
1234      );
1235      cv.visitVarInsn(ASTORE, 1);
1236
1237      // we need to handle the case when the advice was skipped due to runtime check
1238
// that is : if (runtimeCheck) { ret = advice() } else { ret = proceed() }
1239
if (endInstanceOflabel != null) {
1240        Label elseInstanceOfLabel = new Label();
1241        cv.visitJumpInsn(GOTO, elseInstanceOfLabel);
1242        endRuntimeCheck(cv, adviceInfo.getAdviceInfo(), endInstanceOflabel);
1243        cv.visitVarInsn(ALOAD, 0);
1244        cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1245        cv.visitVarInsn(ASTORE, 1);
1246        cv.visitLabel(elseInstanceOfLabel);
1247      }
1248
1249      cv.visitLabel(returnLabels[i]);
1250
1251      cv.visitVarInsn(ALOAD, 1);
1252      cv.visitInsn(ARETURN);
1253    }
1254
1255    if (m_isThisAdvisable) {
1256      int delegationCaseIndex = caseLabels.length - 1;
1257      cv.visitLabel(caseLabels[delegationCaseIndex]);
1258      cv.visitVarInsn(ALOAD, 0);
1259      cv.visitInsn(ICONST_0);
1260      cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
1261      cv.visitVarInsn(ALOAD, 0);
1262      cv.visitMethodInsn(INVOKEVIRTUAL, m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1263
1264      cv.visitLabel(returnLabels[delegationCaseIndex]);
1265
1266      cv.visitInsn(ARETURN);
1267    }
1268
1269    // invoke the target join point in the default case
1270
cv.visitLabel(defaultCaseLabel);
1271
1272    AsmHelper.prepareWrappingOfPrimitiveType(cv, Type.getReturnType(m_calleeMemberDesc));
1273
1274    createJoinPointInvocation(cv);
1275
1276    Type m_returnType = null;
1277    if (m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT) {
1278      m_returnType = Type.getReturnType(m_calleeMemberDesc);
1279    } else {
1280      m_returnType = Type.getType(m_calleeClassSignature);
1281    }
1282    AsmHelper.wrapPrimitiveType(cv, m_returnType);
1283    cv.visitVarInsn(ASTORE, 1);
1284
1285    // store it in Rtti return value
1286
addReturnedValueToJoinPoint(cv, input, 1, true);
1287
1288    // set it as the CALLEE instance for ctor call - TODO refactor somewhere else
1289
if (m_joinPointType == JoinPointType.CONSTRUCTOR_CALL_INT) {
1290      cv.visitVarInsn(ALOAD, 0);
1291      cv.visitVarInsn(ALOAD, 1);
1292      cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1293    }
1294
1295    cv.visitLabel(gotoLabel);
1296
1297    cv.visitVarInsn(ALOAD, 1);
1298    cv.visitInsn(ARETURN);
1299
1300    // finally clause
1301
cv.visitLabel(handlerLabel);
1302    cv.visitVarInsn(ASTORE, 2);
1303    cv.visitLabel(endLabel);
1304
1305    cv.visitVarInsn(ALOAD, 2);
1306    cv.visitInsn(ATHROW);
1307
1308    // set up the label table
1309
cv.visitTryCatchBlock(tryLabel, returnLabels[0], handlerLabel, null);
1310    for (int i = 1; i < caseLabels.length; i++) {
1311      Label caseLabel = caseLabels[i];
1312      Label returnLabel = returnLabels[i];
1313      cv.visitTryCatchBlock(caseLabel, returnLabel, handlerLabel, null);
1314    }
1315    cv.visitTryCatchBlock(defaultCaseLabel, gotoLabel, handlerLabel, null);
1316    cv.visitTryCatchBlock(handlerLabel, endLabel, handlerLabel, null);
1317    cv.visitMaxs(0, 0);
1318  }
1319
1320  /**
1321   * Adds before advice invocations.
1322   *
1323   * @param cv
1324   */

1325  private void createBeforeAdviceInvocations(final MethodVisitor cv, CompilerInput input) {
1326    for (int i = 0; i < m_beforeAdviceMethodInfos.length; i++) {
1327      AdviceMethodInfo adviceMethodInfo = m_beforeAdviceMethodInfos[i];
1328      AspectInfo aspectInfo = adviceMethodInfo.getAspectInfo();
1329
1330      if (requiresCallerInstance(aspectInfo.getDeploymentModel())
1331              && input.callerIndex < 0) {
1332        continue;
1333      }
1334      if (requiresCalleeInstance(aspectInfo.getDeploymentModel())
1335              && input.calleeIndex < 0) {
1336        continue;
1337      }
1338
1339      // runtime check for target() etc
1340
Label endInstanceOflabel = beginRuntimeCheck(cv, input, adviceMethodInfo.getAdviceInfo());
1341
1342      //getDefault the aspect instance
1343
final AspectModel aspectModel = adviceMethodInfo.getAspectInfo().getAspectModel();
1344      aspectModel.loadAspect(cv, input, adviceMethodInfo.getAspectInfo());
1345
1346      // push any needed arguments for the advice invocation
1347
aspectModel.createBeforeOrAfterAdviceArgumentHandling(
1348              cv, input, m_argumentTypes, adviceMethodInfo, INDEX_NOTAVAILABLE
1349      );
1350
1351      // invoke the advice
1352
cv.visitMethodInsn(
1353              INVOKEVIRTUAL,
1354              adviceMethodInfo.getAspectInfo().getAspectClassName(),
1355              adviceMethodInfo.getAdviceInfo().getMethodName(),
1356              adviceMethodInfo.getAdviceInfo().getMethodSignature()
1357      );
1358
1359      // end label of runtime checks
1360
endRuntimeCheck(cv, adviceMethodInfo.getAdviceInfo(), endInstanceOflabel);
1361    }
1362
1363    if (m_isThisAdvisable) {
1364      createBeforeInterceptorInvocations(
1365              cv,
1366              input.joinPointInstanceIndex,
1367              input.callerIndex + 1
1368      );
1369    }
1370  }
1371
1372  /**
1373   * Adds after advice invocations.
1374   *
1375   * @param cv
1376   * @param input
1377   */

1378  private void createAfterFinallyAdviceInvocations(final MethodVisitor cv,
1379                                                   final CompilerInput input) {
1380    // add after advice in reverse order
1381
for (int i = m_afterFinallyAdviceMethodInfos.length - 1; i >= 0; i--) {
1382      AdviceMethodInfo advice = m_afterFinallyAdviceMethodInfos[i];
1383      createAfterAdviceInvocation(cv, input, advice, INDEX_NOTAVAILABLE);
1384    }
1385  }
1386
1387  /**
1388   * Adds after returning advice invocations.
1389   *
1390   * @param cv
1391   * @param input
1392   */

1393  private void createAfterReturningAdviceInvocations(final MethodVisitor cv,
1394                                                     final CompilerInput input) {
1395    final int returnValueIndex = (input.joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1396            (input.joinPointInstanceIndex + 1) : input.callerIndex + 1;
1397
1398    if (m_isThisAdvisable) {
1399      createAfterReturningInterceptorInvocations(cv, input.joinPointInstanceIndex, returnValueIndex);
1400    }
1401
1402    boolean hasPoppedReturnValueFromStack = false;
1403    for (int i = m_afterReturningAdviceMethodInfos.length - 1; i >= 0; i--) {
1404      AdviceMethodInfo advice = m_afterReturningAdviceMethodInfos[i];
1405
1406      // set the return value index that will be used as arg to advice
1407
advice.setSpecialArgumentIndex(returnValueIndex);
1408
1409      String JavaDoc specialArgDesc = advice.getSpecialArgumentTypeDesc();
1410      if (specialArgDesc == null) {
1411        // after returning
1412
createAfterAdviceInvocation(cv, input, advice, INDEX_NOTAVAILABLE);
1413      } else {
1414        // after returning <TYPE>
1415
if (AsmHelper.isPrimitive(m_returnType)) {
1416          if (m_returnType.getDescriptor().equals(specialArgDesc)) {
1417            createAfterAdviceInvocation(cv, input, advice, returnValueIndex);
1418          }
1419        } else {
1420          cv.visitVarInsn(ALOAD, returnValueIndex);
1421
1422          cv.visitTypeInsn(INSTANCEOF, advice.getSpecialArgumentTypeName());
1423
1424          Label label = new Label();
1425          cv.visitJumpInsn(IFEQ, label);
1426
1427          createAfterAdviceInvocation(cv, input, advice, returnValueIndex);
1428
1429          cv.visitLabel(label);
1430        }
1431      }
1432    }
1433
1434    // need the return value in return operation
1435
if (!m_requiresProceedMethod && hasPoppedReturnValueFromStack) {
1436      cv.visitVarInsn(ALOAD, returnValueIndex);
1437    }
1438  }
1439
1440  /**
1441   * Adds a single generic after advice invocation.
1442   *
1443   * @param cv
1444   * @param input
1445   * @param adviceMethodInfo
1446   * @param specialArgIndex for afterReturning / Throwing when binding is used
1447   */

1448  private void createAfterAdviceInvocation(final MethodVisitor cv,
1449                                           final CompilerInput input,
1450                                           final AdviceMethodInfo adviceMethodInfo,
1451                                           final int specialArgIndex) {
1452    AspectInfo aspectInfo = adviceMethodInfo.getAspectInfo();
1453
1454    if (requiresCallerInstance(aspectInfo.getDeploymentModel())
1455            && input.callerIndex < 0) {
1456      return; // without callER instance we cannot load a PER_THIS aspect instance
1457
}
1458    if (requiresCalleeInstance(aspectInfo.getDeploymentModel())
1459            && input.calleeIndex < 0) {
1460      return;
1461    }
1462    // runtime check for target() etc
1463
Label endInstanceOflabel = beginRuntimeCheck(cv, input, adviceMethodInfo.getAdviceInfo());
1464
1465    // getDefault the aspect instance
1466
final AspectModel aspectModel = adviceMethodInfo.getAspectInfo().getAspectModel();
1467    aspectModel.loadAspect(cv, input, aspectInfo);
1468
1469    aspectModel.createBeforeOrAfterAdviceArgumentHandling(
1470            cv, input, m_argumentTypes, adviceMethodInfo, specialArgIndex
1471    );
1472
1473    cv.visitMethodInsn(
1474            INVOKEVIRTUAL,
1475            adviceMethodInfo.getAspectInfo().getAspectClassName(),
1476            adviceMethodInfo.getAdviceInfo().getMethodName(),
1477            adviceMethodInfo.getAdviceInfo().getMethodSignature()
1478    );
1479
1480    // end label of runtime checks
1481
endRuntimeCheck(cv, adviceMethodInfo.getAdviceInfo(), endInstanceOflabel);
1482  }
1483
1484  /**
1485   * Adds the return value to the RETURNED field.
1486   *
1487   * @param cv
1488   * @param input
1489   * @param returnValueIndex
1490   * @param unwrap set to true if already wrapped on the stack (within proceed() code)
1491   */

1492  private void addReturnedValueToJoinPoint(final MethodVisitor cv,
1493                                           final CompilerInput input,
1494                                           final int returnValueIndex,
1495                                           final boolean unwrap) {
1496    if (m_requiresJoinPoint && m_returnType.getSort() != Type.VOID) {
1497      if (m_joinPointType == JoinPointType.METHOD_EXECUTION_INT
1498              || m_joinPointType == JoinPointType.METHOD_CALL_INT
1499              || m_joinPointType == JoinPointType.CONSTRUCTOR_CALL_INT) {
1500        //TODO should we do something for field getDefault / set
1501
loadJoinPointInstance(cv, input);
1502        if (unwrap && AsmHelper.isPrimitive(m_returnType)) {
1503          cv.visitVarInsn(ALOAD, returnValueIndex);
1504          AsmHelper.unwrapType(cv, m_returnType);
1505        } else {
1506          AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1507        }
1508        cv.visitFieldInsn(
1509                PUTFIELD, m_joinPointClassName,
1510                RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor()
1511        );
1512      }
1513    }
1514  }
1515
1516  /**
1517   * Loads the join point instance, takes static/non-static join point access into account.
1518   *
1519   * @param cv
1520   * @param input
1521   */

1522  public static void loadJoinPointInstance(final MethodVisitor cv,
1523                                           final CompilerInput input) {
1524    if (input.isOptimizedJoinPoint) {
1525      cv.visitFieldInsn(
1526              GETSTATIC, input.joinPointClassName,
1527              OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME,
1528              L + input.joinPointClassName + SEMICOLON
1529      );
1530    } else {
1531      cv.visitVarInsn(ALOAD, input.joinPointInstanceIndex);
1532    }
1533  }
1534
1535  /**
1536   * Loads the argument member fields.
1537   *
1538   * @param cv
1539   * @param argStartIndex
1540   */

1541  protected final void loadArgumentMemberFields(final MethodVisitor cv, final int argStartIndex) {
1542    int argStackIndex = argStartIndex;
1543    for (int index = 0; index < m_argumentTypes.length; index++) {
1544      Type argumentType = m_argumentTypes[index];
1545      argStackIndex = AsmHelper.loadType(cv, argStackIndex, argumentType);
1546    }
1547  }
1548
1549  /**
1550   * Loads the arguments.
1551   *
1552   * @param cv
1553   */

1554  protected final void loadArguments(final MethodVisitor cv) {
1555    for (int i = 0; i < m_fieldNames.length; i++) {
1556      String JavaDoc fieldName = m_fieldNames[i];
1557      Type argumentType = m_argumentTypes[i];
1558      cv.visitVarInsn(ALOAD, 0);
1559      cv.visitFieldInsn(GETFIELD, m_joinPointClassName, fieldName, argumentType.getDescriptor());
1560    }
1561  }
1562
1563  /**
1564   * Resets the stack frame counter.
1565   *
1566   * @param cv
1567   */

1568  private void resetStackFrameCounter(final MethodVisitor cv) {
1569    cv.visitVarInsn(ALOAD, 0);
1570    cv.visitInsn(ICONST_M1);
1571    cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1572  }
1573
1574  /**
1575   * Handles the incrementation of the stack frame.
1576   *
1577   * @param cv
1578   */

1579  private void incrementStackFrameCounter(final MethodVisitor cv) {
1580    cv.visitVarInsn(ALOAD, 0);
1581    cv.visitInsn(DUP);
1582    cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1583    cv.visitInsn(ICONST_1);
1584    cv.visitInsn(IADD);
1585    cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1586  }
1587
1588  /**
1589   * Create and load a structure (f.e. array of Object) where args are stored, before setting the Rtti
1590   * with it (See addParametersToRttiInstance). The structure is stored at the given stackFreeIndex.
1591   * <p/>
1592   * Note: public for createMandatoryMethods in the models
1593   *
1594   * @param cv
1595   * @param stackFreeIndex
1596   */

1597  public final void createArgumentArrayAt(final MethodVisitor cv, final int stackFreeIndex) {
1598    AsmHelper.loadIntegerConstant(cv, m_fieldNames.length);
1599    cv.visitTypeInsn(ANEWARRAY, OBJECT_CLASS_NAME);
1600    cv.visitVarInsn(ASTORE, stackFreeIndex);
1601
1602    for (int i = 0; i < m_argumentTypes.length; i++) {
1603      cv.visitVarInsn(ALOAD, stackFreeIndex);
1604      AsmHelper.loadIntegerConstant(cv, i);
1605      AsmHelper.prepareWrappingOfPrimitiveType(cv, m_argumentTypes[i]);
1606      cv.visitVarInsn(ALOAD, 0);
1607      cv.visitFieldInsn(GETFIELD, m_joinPointClassName, ARGUMENT_FIELD + i, m_argumentTypes[i].getDescriptor());
1608      AsmHelper.wrapPrimitiveType(cv, m_argumentTypes[i]);
1609      cv.visitInsn(AASTORE);
1610    }
1611  }
1612
1613  /**
1614   * Creates utility methods for the join point (getter, setters etc.).
1615   */

1616  private void createUtilityMethods() {
1617    MethodVisitor cv;
1618
1619    // addMetaData
1620
{
1621      cv = m_cw.visitMethod(ACC_PUBLIC, ADD_META_DATA_METHOD_NAME, ADD_META_DATA_METHOD_SIGNATURE, null, null);
1622      cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
1623      cv.visitVarInsn(ALOAD, 1);
1624      cv.visitVarInsn(ALOAD, 2);
1625      cv.visitMethodInsn(
1626              INVOKEINTERFACE,
1627              MAP_CLASS_NAME,
1628              PUT_METHOD_NAME,
1629              PUT_METHOD_SIGNATURE
1630      );
1631      cv.visitInsn(POP);
1632      cv.visitInsn(RETURN);
1633      cv.visitMaxs(0, 0);
1634    }
1635
1636    // getMetaData
1637
{
1638      cv = m_cw.visitMethod(ACC_PUBLIC, GET_META_DATA_METHOD_NAME, GET_META_DATA_METHOD_SIGNATURE, null, null);
1639      cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
1640      cv.visitVarInsn(ALOAD, 1);
1641      cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME, GET_METHOD_NAME, GET_METHOD_SIGNATURE);
1642      cv.visitInsn(ARETURN);
1643      cv.visitMaxs(0, 0);
1644    }
1645
1646    // getCallee
1647
{
1648      cv = m_cw.visitMethod(
1649              ACC_PUBLIC,
1650              GET_CALLEE_METHOD_NAME,
1651              NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
1652              null, null
1653      );
1654      cv.visitVarInsn(ALOAD, 0);
1655      cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1656      cv.visitInsn(ARETURN);
1657      cv.visitMaxs(0, 0);
1658    }
1659
1660    // getCaller
1661
{
1662      cv = m_cw.visitMethod(
1663              ACC_PUBLIC,
1664              GET_CALLER_METHOD_NAME,
1665              NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
1666              null, null
1667      );
1668      cv.visitVarInsn(ALOAD, 0);
1669      cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1670      cv.visitInsn(ARETURN);
1671      cv.visitMaxs(0, 0);
1672    }
1673
1674    // getTarget
1675
{
1676      cv = m_cw.visitMethod(
1677              ACC_PUBLIC,
1678              GET_TARGET_METHOD_NAME,
1679              NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
1680              null, null
1681      );
1682      cv.visitVarInsn(ALOAD, 0);
1683      cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1684      cv.visitInsn(ARETURN);
1685      cv.visitMaxs(0, 0);
1686    }
1687
1688    // getThis
1689
{
1690      cv = m_cw.visitMethod(
1691              ACC_PUBLIC,
1692              GET_THIS_METHOD_NAME,
1693              NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
1694              null, null
1695      );
1696      cv.visitVarInsn(ALOAD, 0);
1697      cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1698      cv.visitInsn(ARETURN);
1699      cv.visitMaxs(0, 0);
1700    }
1701
1702    // getCallerClass
1703
{
1704      cv =
1705              m_cw.visitMethod(
1706                      ACC_PUBLIC,
1707                      GET_CALLER_CLASS_METHOD_NAME,
1708                      GET_CALLER_CLASS_METHOD_SIGNATURE,
1709                      null,
1710                      null
1711              );
1712      cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, THIS_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
1713      cv.visitInsn(ARETURN);
1714      cv.visitMaxs(0, 0);
1715    }
1716
1717    // getCalleeClass
1718
{
1719      cv =
1720              m_cw.visitMethod(
1721                      ACC_PUBLIC,
1722                      GET_CALLEE_CLASS_METHOD_NAME,
1723                      GET_CALLEE_CLASS_METHOD_SIGNATURE,
1724                      null,
1725                      null
1726              );
1727      cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
1728      cv.visitInsn(ARETURN);
1729      cv.visitMaxs(0, 0);
1730    }
1731
1732    // getTargetClass, deprecated but still there
1733
{
1734      cv =
1735              m_cw.visitMethod(
1736                      ACC_PUBLIC,
1737                      GET_TARGET_CLASS_METHOD_NAME,
1738                      GET_TARGET_CLASS_METHOD_SIGNATURE,
1739                      null,
1740                      null
1741              );
1742      cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
1743      cv.visitInsn(ARETURN);
1744      cv.visitMaxs(0, 0);
1745    }
1746
1747    // getType
1748
{
1749      cv = m_cw.visitMethod(ACC_PUBLIC, GET_TYPE_METHOD_NAME, GET_TYPE_METHOD_SIGNATURE, null, null);
1750      AsmHelper.loadIntegerConstant(cv, m_joinPointType);
1751      cv.visitMethodInsn(
1752              INVOKESTATIC, Type.getType(JoinPointType.class).getInternalName(), "fromInt",
1753              "(I)" + Type.getType(JoinPointType.class).getDescriptor()
1754      );
1755      cv.visitInsn(ARETURN);
1756      cv.visitMaxs(0, 0);
1757    }
1758
1759    // getEnclosingStaticJoinPoint
1760
{
1761      cv = m_cw.visitMethod(
1762              ACC_PUBLIC,
1763              GET_ENCLOSING_SJP_METHOD_NAME,
1764              GET_ENCLOSING_SJP_METHOD_SIGNATURE,
1765              null,
1766              null
1767      );
1768      cv.visitVarInsn(ALOAD, 0);
1769      cv.visitFieldInsn(
1770              GETSTATIC,
1771              m_joinPointClassName,
1772              ENCLOSING_SJP_FIELD_NAME,
1773              ENCLOSING_SJP_FIELD_CLASS_SIGNATURE
1774      );
1775      cv.visitInsn(ARETURN);
1776      cv.visitMaxs(0, 0);
1777    }
1778
1779  }
1780
1781  // TODO might be a use-case now in Uber Container, keep code for now
1782
// /**
1783
// * Creates the copy method.
1784
// * <p/>
1785
// * TODO refactor and put in subclasses
1786
// */
1787
// protected void createCopyMethod() {
1788
//
1789
// MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC, COPY_METHOD_NAME, COPY_METHOD_SIGNATURE, null, null);
1790
//
1791
// // create a new join point instance
1792
// cv.visitTypeInsn(NEW, m_joinPointClassName);
1793
// cv.visitInsn(DUP);
1794
// int joinPointCloneIndex = 1;
1795
// cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
1796
// cv.visitVarInsn(ASTORE, joinPointCloneIndex);
1797
//
1798
// // set stack frame index
1799
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1800
// cv.visitVarInsn(ALOAD, 0);
1801
// cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1802
// cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1803
//
1804
// if (m_isThisAdvisable) {
1805
// // set interceptor index
1806
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1807
// cv.visitVarInsn(ALOAD, 0);
1808
// cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
1809
// cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
1810
//
1811
// // set array length fields
1812
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1813
// cv.visitVarInsn(ALOAD, 0);
1814
// cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
1815
// cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
1816
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1817
// cv.visitVarInsn(ALOAD, 0);
1818
// cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
1819
// cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
1820
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1821
// cv.visitVarInsn(ALOAD, 0);
1822
// cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
1823
// cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
1824
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1825
// cv.visitVarInsn(ALOAD, 0);
1826
// cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
1827
// cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
1828
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1829
// cv.visitVarInsn(ALOAD, 0);
1830
// cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
1831
// cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
1832
//
1833
// // set arrays
1834
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1835
// cv.visitVarInsn(ALOAD, 0);
1836
// cv.visitFieldInsn(
1837
// GETFIELD, m_joinPointClassName, BEFORE_INTERCEPTORS_FIELD_NAME,
1838
// BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
1839
// );
1840
// cv.visitFieldInsn(
1841
// PUTFIELD, m_joinPointClassName, BEFORE_INTERCEPTORS_FIELD_NAME,
1842
// BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
1843
// );
1844
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1845
// cv.visitVarInsn(ALOAD, 0);
1846
// cv.visitFieldInsn(
1847
// GETFIELD, m_joinPointClassName, AROUND_INTERCEPTORS_FIELD_NAME,
1848
// AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
1849
// );
1850
// cv.visitFieldInsn(
1851
// PUTFIELD, m_joinPointClassName, AROUND_INTERCEPTORS_FIELD_NAME,
1852
// AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
1853
// );
1854
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1855
// cv.visitVarInsn(ALOAD, 0);
1856
// cv.visitFieldInsn(
1857
// GETFIELD, m_joinPointClassName, AFTER_INTERCEPTORS_FIELD_NAME, AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
1858
// );
1859
// cv.visitFieldInsn(
1860
// PUTFIELD, m_joinPointClassName, AFTER_INTERCEPTORS_FIELD_NAME, AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
1861
// );
1862
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1863
// cv.visitVarInsn(ALOAD, 0);
1864
// cv.visitFieldInsn(
1865
// GETFIELD, m_joinPointClassName, AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
1866
// AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
1867
// );
1868
// cv.visitFieldInsn(
1869
// PUTFIELD, m_joinPointClassName, AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
1870
// AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
1871
// );
1872
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1873
// cv.visitVarInsn(ALOAD, 0);
1874
// cv.visitFieldInsn(
1875
// GETFIELD, m_joinPointClassName, AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
1876
// AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
1877
// );
1878
// cv.visitFieldInsn(
1879
// PUTFIELD, m_joinPointClassName, AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
1880
// AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
1881
// );
1882
// }
1883
//
1884
// // set callee
1885
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1886
// cv.visitVarInsn(ALOAD, 0);
1887
// cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1888
// cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1889
//
1890
// // set caller
1891
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1892
// cv.visitVarInsn(ALOAD, 0);
1893
// cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1894
// cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1895
//
1896
// // set the arguments
1897
// for (int i = 0; i < m_fieldNames.length; i++) {
1898
// String fieldName = m_fieldNames[i];
1899
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1900
// cv.visitVarInsn(ALOAD, 0);
1901
// cv.visitFieldInsn(GETFIELD, m_joinPointClassName, fieldName, m_argumentTypes[i].getDescriptor());
1902
// cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, fieldName, m_argumentTypes[i].getDescriptor());
1903
// }
1904
//
1905
// // set the returned field if any
1906
// if (m_returnType.getSort() != Type.VOID) {
1907
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1908
// cv.visitVarInsn(ALOAD, 0);
1909
// cv.visitFieldInsn(GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
1910
// cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
1911
// }
1912
//
1913
// cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1914
// cv.visitInsn(ARETURN);
1915
// cv.visitMaxs(0, 0);
1916
// }
1917

1918  /**
1919   * Build up the signature of the 'invoke' methods.
1920   *
1921   * @return
1922   */

1923  protected String JavaDoc buildInvokeMethodSignature() {
1924    StringBuffer JavaDoc invokeDescBuf = new StringBuffer JavaDoc();
1925    invokeDescBuf.append('(');
1926    if (m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT) {
1927      if (!Modifier.isStatic(m_calleeMemberModifiers)) {
1928        // callee
1929
invokeDescBuf.append(m_calleeClassSignature);
1930      }
1931    }
1932    // args
1933
for (int i = 0; i < m_argumentTypes.length; i++) {
1934      Type type = m_argumentTypes[i];
1935      invokeDescBuf.append(type.getDescriptor());
1936    }
1937    // caller
1938
invokeDescBuf.append(m_callerClassSignature);
1939    invokeDescBuf.append(')');
1940    invokeDescBuf.append(m_returnType.getDescriptor());
1941    return invokeDescBuf.toString();
1942  }
1943
1944  /**
1945   * Checks if at least one advice is using this or target (bounded or runtime check)
1946   *
1947   * @return true if so
1948   */

1949  private boolean requiresThisOrTarget() {
1950    return m_isThisAdvisable ||
1951            requiresThisOrTarget(m_aroundAdviceMethodInfos) ||
1952            requiresThisOrTarget(m_beforeAdviceMethodInfos) ||
1953            requiresThisOrTarget(m_afterFinallyAdviceMethodInfos) ||
1954            requiresThisOrTarget(m_afterReturningAdviceMethodInfos) ||
1955            requiresThisOrTarget(m_afterThrowingAdviceMethodInfos);
1956  }
1957
1958  /**
1959   * Checks if at least one advice is using the non static JoinPoint explicitly
1960   *
1961   * @return true if so
1962   */

1963  private boolean requiresJoinPoint() {
1964    if (m_isThisAdvisable ||
1965            requiresJoinPoint(m_aroundAdviceMethodInfos) ||
1966            requiresJoinPoint(m_beforeAdviceMethodInfos) ||
1967            requiresJoinPoint(m_afterFinallyAdviceMethodInfos) ||
1968            requiresJoinPoint(m_afterReturningAdviceMethodInfos) ||
1969            requiresJoinPoint(m_afterThrowingAdviceMethodInfos)) {
1970      return true;
1971    }
1972
1973    // query the models to know which level of optimization we can use
1974
for (int i = 0; i < m_aspectModels.length; i++) {
1975      if (m_aspectModels[i].requiresReflectiveInfo()) {
1976        // if at least one model requries RTTI then build it
1977
return true;
1978      }
1979    }
1980
1981    return false;
1982  }
1983
1984  /**
1985   * Checks if at least one advice is using target or this (bounded or runtime check)
1986   *
1987   * @param adviceMethodInfos
1988   * @return true if so
1989   */

1990  private boolean requiresThisOrTarget(final AdviceMethodInfo[] adviceMethodInfos) {
1991    for (int i = 0; i < adviceMethodInfos.length; i++) {
1992      if (adviceMethodInfos[i].requiresThisOrTarget()) {
1993        return true;
1994      }
1995    }
1996    return false;
1997  }
1998
1999  /**
2000   * Checks if at least one advice is using non static JoinPoint explicitly
2001   *
2002   * @param adviceMethodInfos
2003   * @return true if so
2004   */

2005  private boolean requiresJoinPoint(final AdviceMethodInfo[] adviceMethodInfos) {
2006    for (int i = 0; i < adviceMethodInfos.length; i++) {
2007      if (adviceMethodInfos[i].requiresJoinPoint()) {
2008        return true;
2009      }
2010    }
2011    return false;
2012  }
2013
2014  /**
2015   * Handles the if case for runtime check (target instanceof, cflow)
2016   *
2017   * @param cv
2018   * @param adviceInfo
2019   * @return the label for endIf or null if the adviceInfo did not required runtime check
2020   */

2021  private Label beginRuntimeCheck(final MethodVisitor cv,
2022                                  final CompilerInput input,
2023                                  final AdviceInfo adviceInfo) {
2024    Label endRuntimeCheckLabel = null;
2025    DeploymentModel deploymentModel = adviceInfo.getAspectDeploymentModel();
2026    if (adviceInfo.hasTargetWithRuntimeCheck()
2027            || adviceInfo.getAdviceDefinition().hasCflowOrCflowBelow()
2028            || DeploymentModel.PER_THIS.equals(deploymentModel)
2029            || DeploymentModel.PER_TARGET.equals(deploymentModel)) {
2030
2031      int perObjectCheckType = RuntimeCheckVisitor.NULL_PER_OBJECT_TYPE;
2032
2033      if (DeploymentModel.PER_THIS.equals(deploymentModel)) {
2034        perObjectCheckType = RuntimeCheckVisitor.PER_THIS_TYPE;
2035      } else if (DeploymentModel.PER_TARGET.equals(deploymentModel)) {
2036        perObjectCheckType = RuntimeCheckVisitor.PER_TARGET_TYPE;
2037      }
2038
2039      endRuntimeCheckLabel = new Label();
2040      // create a specific visitor everytime
2041
RuntimeCheckVisitor runtimeCheckVisitor = new RuntimeCheckVisitor(
2042              cv,
2043              adviceInfo.getExpressionInfo(),
2044              input,
2045              perObjectCheckType,
2046              adviceInfo.getAspectQualifiedName()
2047      );
2048      runtimeCheckVisitor.pushCheckOnStack(adviceInfo);
2049      cv.visitJumpInsn(IFEQ, endRuntimeCheckLabel);
2050    }
2051    return endRuntimeCheckLabel;
2052  }
2053
2054  /**
2055   * Ends the ifLabel of a runtime check
2056   *
2057   * @param cv
2058   * @param adviceInfo
2059   * @param label if null, then do nothing (means we did not had a runtime check)
2060   */

2061  private void endRuntimeCheck(final MethodVisitor cv, final AdviceInfo adviceInfo, final Label label) {
2062    DeploymentModel deployModel = adviceInfo.getAspectDeploymentModel();
2063
2064    if (adviceInfo.hasTargetWithRuntimeCheck()
2065            || adviceInfo.getAdviceDefinition().hasCflowOrCflowBelow()
2066            || DeploymentModel.PER_THIS.equals(deployModel)
2067            || DeploymentModel.PER_TARGET.equals(deployModel)) {
2068
2069      cv.visitLabel(label);
2070    }
2071  }
2072
2073  /**
2074   * Helper method to load the callee on the stack
2075   *
2076   * @param cv
2077   * @param input
2078   */

2079  public static void loadCallee(final MethodVisitor cv,
2080                                final CompilerInput input) {
2081    if (input.isOptimizedJoinPoint) {
2082      // grab the callee from the invoke parameters directly
2083
cv.visitVarInsn(ALOAD, input.calleeIndex);
2084    } else {
2085      loadJoinPointInstance(cv, input);
2086      cv.visitFieldInsn(
2087              GETFIELD, input.joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, input.calleeClassSignature
2088      );
2089    }
2090  }
2091
2092  /**
2093   * Helper method to load the caller on the stack
2094   *
2095   * @param cv
2096   * @param input
2097   */

2098  public static void loadCaller(final MethodVisitor cv,
2099                                final CompilerInput input) {
2100    if (input.isOptimizedJoinPoint) {
2101      // grab the callee from the invoke parameters directly
2102
cv.visitVarInsn(ALOAD, input.callerIndex);
2103    } else {
2104      loadJoinPointInstance(cv, input);
2105      cv.visitFieldInsn(
2106              GETFIELD, input.joinPointClassName, CALLER_INSTANCE_FIELD_NAME, input.callerClassSignature
2107      );
2108    }
2109  }
2110
2111// /**
2112
// * Creates an invocation to Aspects.aspectOf(..).
2113
// *
2114
// * @param cv
2115
// * @param isOptimizedJoinPoint
2116
// * @param joinPointIndex
2117
// * @param callerIndex
2118
// * @param calleeIndex
2119
// * @param aspectInfo
2120
// */
2121
// public void createInvocationToAspectOf(final MethodVisitor cv,
2122
// final boolean isOptimizedJoinPoint,
2123
// final int joinPointIndex,
2124
// final int callerIndex,
2125
// final int calleeIndex,
2126
// final AspectInfo aspectInfo) {
2127
// if (DeploymentModel.PER_INSTANCE.equals(aspectInfo.getDeploymentModel())) {
2128
//
2129
// //generates code: aspectField = (cast) Aspects.aspect$Of(aspectQN, containerClassName, callee)
2130
// loadJoinPointInstance(cv, m_joinPointClassName, isOptimizedJoinPoint, joinPointIndex);
2131
// cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
2132
// if (calleeIndex >= 0) {
2133
// cv.visitVarInsn(ALOAD, calleeIndex);
2134
// cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
2135
// cv.visitMethodInsn(
2136
// INVOKESTATIC,
2137
// ASPECTS_CLASS_NAME,
2138
// ASPECT_OF_METHOD_NAME,
2139
// ASPECT_OF_PER_INSTANCE_METHOD_SIGNATURE
2140
// );
2141
// } else {
2142
// // TODO: should this really happen? we are filtering at early stage now. - REMOVE CODE BLOCK
2143
// // fallback to perClass
2144
// //aspectField = (cast) Aspects.aspectOf(aspectQN, containerClass, calleeClass)
2145
// cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
2146
// cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
2147
// cv.visitMethodInsn(
2148
// INVOKESTATIC,
2149
// ASPECTS_CLASS_NAME,
2150
// ASPECT_OF_METHOD_NAME,
2151
// ASPECT_OF_PER_CLASS_METHOD_SIGNATURE
2152
// );
2153
// }
2154
// cv.visitTypeInsn(CHECKCAST, aspectInfo.getAspectClassName());
2155
// cv.visitFieldInsn(
2156
// PUTFIELD, m_joinPointClassName, aspectInfo.getAspectFieldName(),
2157
// aspectInfo.getAspectClassSignature()
2158
// );
2159
// }
2160
// }
2161

2162  /**
2163   * Generates code needed for handling Advisable management for the target class.
2164   *
2165   * @param cv
2166   * @param joinPointInstanceIndex
2167   * @param advisableIndex
2168   */

2169  private void createInitializationForAdvisableManagement(final MethodVisitor cv,
2170                                                          final int joinPointInstanceIndex,
2171                                                          final int advisableIndex) {
2172    // interceptor index
2173
cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2174    cv.visitInsn(ICONST_M1);
2175    cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2176
2177    initializeAroundInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2178    initializeBeforeInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2179    initializeAfterInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2180    initializeAfterReturningInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2181    initializeAfterThrowingInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2182  }
2183
2184  /**
2185   * Handle the around interceptor init.
2186   *
2187   * @param cv
2188   * @param joinPointInstanceIndex
2189   * @param advisableIndex
2190   */

2191  private void initializeAroundInterceptors(final MethodVisitor cv,
2192                                            final int joinPointInstanceIndex,
2193                                            final int advisableIndex) {
2194    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2195    cv.visitVarInsn(ALOAD, advisableIndex);
2196    cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2197    cv.visitLdcInsn(new Integer JavaDoc(m_joinPointClassName.hashCode()));
2198    cv.visitMethodInsn(
2199            INVOKEINTERFACE,
2200            ADVISABLE_CLASS_NAME,
2201            GET_AROUND_ADVICE_METHOD_NAME,
2202            GET_AROUND_ADVICE_METHOD_SIGNATURE
2203    );
2204    cv.visitFieldInsn(
2205            PUTFIELD,
2206            m_joinPointClassName,
2207            AROUND_INTERCEPTORS_FIELD_NAME,
2208            AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2209    );
2210
2211    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2212    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2213    cv.visitFieldInsn(
2214            GETFIELD,
2215            m_joinPointClassName,
2216            AROUND_INTERCEPTORS_FIELD_NAME,
2217            AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2218    );
2219    cv.visitInsn(ARRAYLENGTH);
2220    cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2221  }
2222
2223  /**
2224   * Handle the before interceptor init.
2225   *
2226   * @param cv
2227   * @param joinPointInstanceIndex
2228   * @param advisableIndex
2229   */

2230  private void initializeBeforeInterceptors(final MethodVisitor cv,
2231                                            final int joinPointInstanceIndex,
2232                                            final int advisableIndex) {
2233    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2234    cv.visitVarInsn(ALOAD, advisableIndex);
2235    cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2236    cv.visitLdcInsn(new Integer JavaDoc(m_joinPointClassName.hashCode()));
2237    cv.visitMethodInsn(
2238            INVOKEINTERFACE,
2239            ADVISABLE_CLASS_NAME,
2240            GET_BEFORE_ADVICE_METHOD_NAME,
2241            GET_BEFORE_ADVICE_METHOD_SIGNATURE
2242    );
2243    cv.visitFieldInsn(
2244            PUTFIELD,
2245            m_joinPointClassName,
2246            BEFORE_INTERCEPTORS_FIELD_NAME,
2247            BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2248    );
2249
2250    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2251    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2252    cv.visitFieldInsn(
2253            GETFIELD,
2254            m_joinPointClassName,
2255            BEFORE_INTERCEPTORS_FIELD_NAME,
2256            BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2257    );
2258    cv.visitInsn(ARRAYLENGTH);
2259    cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2260  }
2261
2262  /**
2263   * Handle the after finally interceptor init.
2264   *
2265   * @param cv
2266   * @param joinPointInstanceIndex
2267   * @param advisableIndex
2268   */

2269  private void initializeAfterInterceptors(final MethodVisitor cv,
2270                                           final int joinPointInstanceIndex,
2271                                           final int advisableIndex) {
2272    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2273    cv.visitVarInsn(ALOAD, advisableIndex);
2274    cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2275    cv.visitLdcInsn(new Integer JavaDoc(m_joinPointClassName.hashCode()));
2276    cv.visitMethodInsn(
2277            INVOKEINTERFACE,
2278            ADVISABLE_CLASS_NAME,
2279            GET_AFTER_ADVICE_METHOD_NAME,
2280            GET_AFTER_ADVICE_METHOD_SIGNATURE
2281    );
2282    cv.visitFieldInsn(
2283            PUTFIELD,
2284            m_joinPointClassName,
2285            AFTER_INTERCEPTORS_FIELD_NAME,
2286            AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2287    );
2288
2289    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2290    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2291    cv.visitFieldInsn(
2292            GETFIELD,
2293            m_joinPointClassName,
2294            AFTER_INTERCEPTORS_FIELD_NAME,
2295            AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2296    );
2297    cv.visitInsn(ARRAYLENGTH);
2298    cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2299  }
2300
2301  /**
2302   * Handle the after returning interceptor init.
2303   *
2304   * @param cv
2305   * @param joinPointInstanceIndex
2306   * @param advisableIndex
2307   */

2308  private void initializeAfterReturningInterceptors(final MethodVisitor cv,
2309                                                    final int joinPointInstanceIndex,
2310                                                    final int advisableIndex) {
2311    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2312    cv.visitVarInsn(ALOAD, advisableIndex);
2313    cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2314    cv.visitLdcInsn(new Integer JavaDoc(m_joinPointClassName.hashCode()));
2315    cv.visitMethodInsn(
2316            INVOKEINTERFACE,
2317            ADVISABLE_CLASS_NAME,
2318            GET_AFTER_RETURNING_ADVICE_METHOD_NAME,
2319            GET_AFTER_RETURNING_ADVICE_METHOD_SIGNATURE
2320    );
2321    cv.visitFieldInsn(
2322            PUTFIELD,
2323            m_joinPointClassName,
2324            AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2325            AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2326    );
2327
2328    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2329    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2330    cv.visitFieldInsn(
2331            GETFIELD,
2332            m_joinPointClassName,
2333            AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2334            AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2335    );
2336    cv.visitInsn(ARRAYLENGTH);
2337    cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2338  }
2339
2340  /**
2341   * Handle the after throwing interceptor init.
2342   *
2343   * @param cv
2344   * @param joinPointInstanceIndex
2345   * @param advisableIndex
2346   */

2347  private void initializeAfterThrowingInterceptors(final MethodVisitor cv,
2348                                                   final int joinPointInstanceIndex,
2349                                                   final int advisableIndex) {
2350    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2351    cv.visitVarInsn(ALOAD, advisableIndex);
2352    cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2353    cv.visitLdcInsn(new Integer JavaDoc(m_joinPointClassName.hashCode()));
2354    cv.visitMethodInsn(
2355            INVOKEINTERFACE,
2356            ADVISABLE_CLASS_NAME,
2357            GET_AFTER_THROWING_ADVICE_METHOD_NAME,
2358            GET_AFTER_THROWING_ADVICE_METHOD_SIGNATURE
2359    );
2360    cv.visitFieldInsn(
2361            PUTFIELD,
2362            m_joinPointClassName,
2363            AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2364            AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2365    );
2366
2367    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2368    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2369    cv.visitFieldInsn(
2370            GETFIELD,
2371            m_joinPointClassName,
2372            AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2373            AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2374    );
2375    cv.visitInsn(ARRAYLENGTH);
2376    cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2377  }
2378
2379  /**
2380   * Handles the around interceptor invocations.
2381   *
2382   * @param cv
2383   */

2384  private void createAroundInterceptorInvocations(final MethodVisitor cv) {
2385    cv.visitVarInsn(ALOAD, 0);
2386    cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2387    cv.visitInsn(ICONST_M1);
2388    Label ifStatementLabel = new Label();
2389    cv.visitJumpInsn(IF_ICMPEQ, ifStatementLabel);
2390    cv.visitVarInsn(ALOAD, 0);
2391    cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2392    cv.visitVarInsn(ALOAD, 0);
2393    cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2394    cv.visitJumpInsn(IF_ICMPGE, ifStatementLabel);
2395    cv.visitVarInsn(ALOAD, 0);
2396    cv.visitFieldInsn(
2397            GETFIELD,
2398            m_joinPointClassName,
2399            AROUND_INTERCEPTORS_FIELD_NAME,
2400            AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2401    );
2402    cv.visitVarInsn(ALOAD, 0);
2403    cv.visitInsn(DUP);
2404    cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2405    cv.visitInsn(DUP_X1);
2406    cv.visitInsn(ICONST_1);
2407    cv.visitInsn(IADD);
2408    cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2409    cv.visitInsn(AALOAD);
2410    cv.visitVarInsn(ALOAD, 0);
2411    cv.visitMethodInsn(
2412            INVOKEINTERFACE,
2413            AROUND_ADVICE_CLASS_NAME,
2414            INTERCEPT_INVOKE_METHOD_NAME,
2415            AROUND_ADVICE_INVOKE_METHOD_SIGNATURE
2416    );
2417    cv.visitInsn(ARETURN);
2418    cv.visitLabel(ifStatementLabel);
2419  }
2420
2421  /**
2422   * Creates invocations fo the before interceptors.
2423   *
2424   * @param cv
2425   * @param joinPointInstanceIndex
2426   * @param registerDepth
2427   */

2428  private void createBeforeInterceptorInvocations(final MethodVisitor cv,
2429                                                  final int joinPointInstanceIndex,
2430                                                  final int registerDepth) {
2431    final int loopIndex = registerDepth + 1;
2432    cv.visitInsn(ICONST_0);
2433    cv.visitVarInsn(ISTORE, loopIndex);
2434    Label loopStartLabel = new Label();
2435    cv.visitLabel(loopStartLabel);
2436    cv.visitVarInsn(ILOAD, loopIndex);
2437    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2438    cv.visitFieldInsn(
2439            GETFIELD,
2440            m_joinPointClassName,
2441            NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME,
2442            I
2443    );
2444    Label loopCheckCondLabel = new Label();
2445    cv.visitJumpInsn(IF_ICMPGE, loopCheckCondLabel);
2446    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2447    cv.visitFieldInsn(
2448            GETFIELD,
2449            m_joinPointClassName,
2450            BEFORE_INTERCEPTORS_FIELD_NAME,
2451            BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2452    );
2453    cv.visitVarInsn(ILOAD, loopIndex);
2454    cv.visitInsn(AALOAD);
2455    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2456    cv.visitMethodInsn(
2457            INVOKEINTERFACE,
2458            BEFORE_ADVICE_CLASS_NAME,
2459            INTERCEPT_INVOKE_METHOD_NAME,
2460            BEFORE_ADVICE_INVOKE_METHOD_SIGNATURE
2461    );
2462    cv.visitIincInsn(loopIndex, 1);
2463    cv.visitJumpInsn(GOTO, loopStartLabel);
2464    cv.visitLabel(loopCheckCondLabel);
2465  }
2466
2467  /**
2468   * Creates invocations fo the after finally interceptors.
2469   *
2470   * @param cv
2471   * @param joinPointInstanceIndex
2472   * @param registerDepth
2473   */

2474  private void createAfterInterceptorInvocations(final MethodVisitor cv,
2475                                                 final int joinPointInstanceIndex,
2476                                                 final int registerDepth) {
2477    final int loopIndex = registerDepth + 1;
2478    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2479    cv.visitFieldInsn(
2480            GETFIELD,
2481            m_joinPointClassName,
2482            NR_OF_AFTER_INTERCEPTORS_FIELD_NAME,
2483            I
2484    );
2485    cv.visitInsn(ICONST_1);
2486    cv.visitInsn(ISUB);
2487    cv.visitVarInsn(ISTORE, loopIndex);
2488    Label loopLabel1 = new Label();
2489    cv.visitLabel(loopLabel1);
2490    cv.visitVarInsn(ILOAD, loopIndex);
2491    Label loopLabel2 = new Label();
2492    cv.visitJumpInsn(IFLT, loopLabel2);
2493    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2494    cv.visitFieldInsn(
2495            GETFIELD,
2496            m_joinPointClassName,
2497            AFTER_INTERCEPTORS_FIELD_NAME,
2498            AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2499    );
2500    cv.visitVarInsn(ILOAD, loopIndex);
2501    cv.visitInsn(AALOAD);
2502    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2503    cv.visitMethodInsn(
2504            INVOKEINTERFACE,
2505            AFTER_ADVICE_CLASS_NAME,
2506            INTERCEPT_INVOKE_METHOD_NAME,
2507            AFTER_ADVICE_INVOKE_METHOD_SIGNATURE
2508    );
2509    cv.visitIincInsn(loopIndex, -1);
2510    cv.visitJumpInsn(GOTO, loopLabel1);
2511    cv.visitLabel(loopLabel2);
2512  }
2513
2514  /**
2515   * Creates invocations fo the after returning interceptors.
2516   *
2517   * @param cv
2518   * @param joinPointInstanceIndex
2519   * @param returnValueInstanceIndex
2520   */

2521  private void createAfterReturningInterceptorInvocations(final MethodVisitor cv,
2522                                                          final int joinPointInstanceIndex,
2523                                                          final int returnValueInstanceIndex) {
2524    final int loopIndex = returnValueInstanceIndex + 1;
2525    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2526    cv.visitFieldInsn(
2527            GETFIELD,
2528            m_joinPointClassName,
2529            NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2530            I
2531    );
2532    cv.visitInsn(ICONST_1);
2533    cv.visitInsn(ISUB);
2534    cv.visitVarInsn(ISTORE, loopIndex);
2535    Label loopLabel1 = new Label();
2536    cv.visitLabel(loopLabel1);
2537    cv.visitVarInsn(ILOAD, loopIndex);
2538    Label loopLabel2 = new Label();
2539    cv.visitJumpInsn(IFLT, loopLabel2);
2540    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2541    cv.visitFieldInsn(
2542            GETFIELD,
2543            m_joinPointClassName,
2544            AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2545            AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2546    );
2547    cv.visitVarInsn(ILOAD, loopIndex);
2548    cv.visitInsn(AALOAD);
2549    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2550    cv.visitVarInsn(ALOAD, returnValueInstanceIndex);
2551    cv.visitMethodInsn(
2552            INVOKEINTERFACE,
2553            AFTER_RETURNING_ADVICE_CLASS_NAME,
2554            INTERCEPT_INVOKE_METHOD_NAME,
2555            AFTER_RETURNING_ADVICE_INVOKE_METHOD_SIGNATURE
2556    );
2557    cv.visitIincInsn(loopIndex, -1);
2558    cv.visitJumpInsn(GOTO, loopLabel1);
2559    cv.visitLabel(loopLabel2);
2560  }
2561
2562  /**
2563   * Creates invocations fo the after returning interceptors.
2564   *
2565   * @param cv
2566   * @param joinPointInstanceIndex
2567   * @param exceptionInstanceIndex
2568   */

2569  private void createAfterThrowingInterceptorInvocations(final MethodVisitor cv,
2570                                                         final int joinPointInstanceIndex,
2571                                                         final int exceptionInstanceIndex) {
2572    final int loopIndex = exceptionInstanceIndex + 1;
2573    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2574    cv.visitFieldInsn(
2575            GETFIELD,
2576            m_joinPointClassName,
2577            NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2578            I
2579    );
2580    cv.visitInsn(ICONST_1);
2581    cv.visitInsn(ISUB);
2582    cv.visitVarInsn(ISTORE, loopIndex);
2583    Label loopLabel1 = new Label();
2584    cv.visitLabel(loopLabel1);
2585    cv.visitVarInsn(ILOAD, loopIndex);
2586    Label loopLabel2 = new Label();
2587    cv.visitJumpInsn(IFLT, loopLabel2);
2588    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2589    cv.visitFieldInsn(
2590            GETFIELD,
2591            m_joinPointClassName,
2592            AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2593            AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2594    );
2595    cv.visitVarInsn(ILOAD, loopIndex);
2596    cv.visitInsn(AALOAD);
2597    cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2598    cv.visitVarInsn(ALOAD, exceptionInstanceIndex);
2599    cv.visitMethodInsn(
2600            INVOKEINTERFACE,
2601            AFTER_THROWING_ADVICE_CLASS_NAME,
2602            INTERCEPT_INVOKE_METHOD_NAME,
2603            AFTER_THROWING_ADVICE_INVOKE_METHOD_SIGNATURE
2604    );
2605    cv.visitIincInsn(loopIndex, -1);
2606    cv.visitJumpInsn(GOTO, loopLabel1);
2607    cv.visitLabel(loopLabel2);
2608  }
2609
2610  /**
2611   * Checks if the join point requires a proceed() method.
2612   *
2613   * @return
2614   */

2615  private boolean requiresProceedMethod() {
2616    return m_hasAroundAdvices || m_isThisAdvisable;
2617  }
2618
2619  public static boolean requiresCallerInstance(DeploymentModel deployModel) {
2620    return DeploymentModel.PER_INSTANCE.equals(deployModel)
2621            || DeploymentModel.PER_THIS.equals(deployModel);
2622  }
2623
2624  public static boolean requiresCalleeInstance(DeploymentModel deployModel) {
2625    return DeploymentModel.PER_TARGET.equals(deployModel);
2626  }
2627
2628  public static boolean requiresCallerOrCallee(DeploymentModel deploymentModel) {
2629    return requiresCallerInstance(deploymentModel)
2630            || requiresCalleeInstance(deploymentModel);
2631  }
2632
2633  public final AspectModel[] getAspectModels() {
2634    return m_aspectModels;
2635  }
2636
2637}
2638
Popular Tags