KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > easybeans > enhancer > interceptors > EasyBeansInvocationContextGenerator


1 /**
2  * EasyBeans
3  * Copyright (C) 2006 Bull S.A.S.
4  * Contact: easybeans@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: EasyBeansInvocationContextGenerator.java 840 2006-07-12 09:02:12Z benoitf $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.easybeans.enhancer.interceptors;
27
28 import static org.objectweb.easybeans.deployment.annotations.InterceptorType.AROUND_INVOKE;
29
30 import java.io.File JavaDoc;
31 import java.io.FileOutputStream JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.List JavaDoc;
34
35 import org.objectweb.asm.ClassWriter;
36 import org.objectweb.asm.Label;
37 import org.objectweb.asm.MethodVisitor;
38 import org.objectweb.asm.Type;
39 import org.objectweb.easybeans.api.EasyBeansInvocationContext;
40 import org.objectweb.easybeans.deployment.annotations.InterceptorType;
41 import org.objectweb.easybeans.deployment.annotations.JClassInterceptor;
42 import org.objectweb.easybeans.deployment.annotations.JMethod;
43 import org.objectweb.easybeans.deployment.annotations.metadata.ClassAnnotationMetadata;
44 import org.objectweb.easybeans.deployment.annotations.metadata.MethodAnnotationMetadata;
45 import org.objectweb.easybeans.enhancer.CommonClassGenerator;
46 import org.objectweb.easybeans.enhancer.lib.MethodRenamer;
47 import org.objectweb.easybeans.log.JLog;
48 import org.objectweb.easybeans.log.JLogFactory;
49
50 /**
51  * Generates the implementation of
52  * {@link org.objectweb.easybeans.api.EasyBeansInvocationContext} interface for a
53  * given business method.
54  * @author Florent Benoit
55  */

56 public class EasyBeansInvocationContextGenerator extends CommonClassGenerator {
57
58     /**
59      * Prefix used as package name for generated classes
60      * (EasyBeansInvocationContext* impl).
61      */

62     public static final String JavaDoc PACKAGE_NAME_PREFIX = "org.objectweb.easybeans_gen.invocationcontext.";
63
64     /**
65      * Name of the attributes will start with this name with an index as suffix,
66      * ie : arg0, arg1, arg2,...
67      */

68     public static final String JavaDoc ARG = "arg";
69
70     /**
71      * Name of the interceptor attributes will start with this name with an index as suffix,
72      * ie : interceptor0, interceptor1, interceptor2,...
73      */

74     public static final String JavaDoc INTERCEPTOR = "interceptor";
75
76     /**
77      * Suffix for generated classes EasyBeansInvocationContextImpl.
78      */

79     public static final String JavaDoc SUFFIX_CLASS = "EasyBeansInvocationContextImpl";
80
81     /**
82      * Interface of this invocation context.
83      */

84     public static final String JavaDoc[] INTERFACES = new String JavaDoc[] {"org/objectweb/easybeans/api/EasyBeansInvocationContext"};
85
86     /**
87      * Exceptions of the proceed method.
88      */

89     public static final String JavaDoc[] PROCEED_EXCEPTIONS = new String JavaDoc[] {Type.getInternalName(Exception JavaDoc.class)};
90
91     /**
92      * EasyBeansInvocationContext interface.
93      */

94     public static final String JavaDoc EASYBEANS_INVOCATION_CONTEXT = Type.getDescriptor(EasyBeansInvocationContext.class);
95
96     /**
97      * Logger.
98      */

99     private static JLog logger = JLogFactory.getLog(EasyBeansInvocationContextGenerator.class);
100
101     /**
102      * Metadata available for a class (extracted from method metadat object.
103      * (parent))
104      */

105     private ClassAnnotationMetadata classAnnotationMetadata = null;
106
107     /**
108      * Package name which is used for generating class.
109      */

110     private String JavaDoc packageName = null;
111
112     /**
113      * Full class name of the generated class (prefixed by packageName).
114      */

115     private String JavaDoc generatedClassName = null;
116
117     /**
118      * JMethod object which correspond to the current method metadata which is
119      * used.
120      */

121     private JMethod jMethod = null;
122
123     /**
124      * Metadata available for a method (given as constructor arg).
125      */

126     private MethodAnnotationMetadata methodAnnotationMetadata;
127
128     /**
129      * Bean class descriptor.
130      */

131     private String JavaDoc beanClassDesc = null;
132
133     /**
134      * Bean class name.
135      */

136     private String JavaDoc beanClassName = null;
137
138     /**
139      * Bean class Type (ASM).
140      */

141     private Type beanClassType = null;
142
143     /**
144      * ASM descriptor of the generated constructor.
145      */

146     private String JavaDoc constructorDesc = null;
147
148     /**
149      * ASM Type arguments of the method.
150      */

151     private Type[] methodArgsType = null;
152
153     /**
154      * List of interceptors.
155      */

156     private List JavaDoc<JClassInterceptor> allInterceptors = null;
157
158     /**
159      * Type of the interceptor (AroundInvoke, PostConstruct, etc).
160      */

161     private InterceptorType interceptorType = null;
162
163     /**
164      * Name of the interceptor manager class.
165      */

166     private String JavaDoc interceptorManagerClassName = null;
167
168     /**
169      * Suffix for InterceptorManager.
170      */

171     public static final String JavaDoc SUFFIX_INTERCEPTOR_MANAGER = "InterceptorManager";
172
173     /**
174      * Constructor It will generate a class for the given method metadata.
175      * @param methodAnnotationMetadata method meta data
176      * @param interceptorType the type of invocationContext to generate (AroundInvoke, PostConstruct, etc)
177      */

178     public EasyBeansInvocationContextGenerator(final MethodAnnotationMetadata methodAnnotationMetadata,
179             final InterceptorType interceptorType) {
180         super(new ClassWriter(true));
181         this.methodAnnotationMetadata = methodAnnotationMetadata;
182         this.classAnnotationMetadata = methodAnnotationMetadata.getClassAnnotationMetadata();
183         this.jMethod = methodAnnotationMetadata.getJMethod();
184
185         // package name is prefixed
186
packageName = PACKAGE_NAME_PREFIX + classAnnotationMetadata.getClassName();
187
188         // Type of the generated interceptor
189
this.interceptorType = interceptorType;
190
191         this.interceptorManagerClassName = classAnnotationMetadata.getClassName() + SUFFIX_INTERCEPTOR_MANAGER;
192
193
194         // Name of the class that is generated
195
generatedClassName = packageName.replace(".", "/") + "/" + SUFFIX_CLASS;
196         generatedClassName += methodAnnotationMetadata.getJMethod().getName() + interceptorType.name().replace("_", "");
197         // Also, as two methods with the same name but different parameters will produce the same class name,
198
// add the hashcode of the ASM descriptor.
199
generatedClassName += methodAnnotationMetadata.getJMethod().getDescriptor().hashCode();
200
201         // useful constants
202
beanClassDesc = encodeClassDesc(classAnnotationMetadata.getClassName());
203         beanClassName = classAnnotationMetadata.getClassName();
204         beanClassType = Type.getType(beanClassDesc);
205
206         // type arguments of the method
207
methodArgsType = Type.getArgumentTypes(jMethod.getDescriptor());
208
209         // build a list of all interceptors (first = global then method then users)
210
allInterceptors = new ArrayList JavaDoc<JClassInterceptor>();
211         if (classAnnotationMetadata.getGlobalEasyBeansInterceptors() != null) {
212             for (JClassInterceptor interceptor : classAnnotationMetadata.getGlobalEasyBeansInterceptors()) {
213                 allInterceptors.add(interceptor);
214             }
215         }
216
217         // global interceptor on the method (remove annotation for example)
218
if (methodAnnotationMetadata.getGlobalEasyBeansInterceptors() != null) {
219             for (JClassInterceptor interceptor : methodAnnotationMetadata.getGlobalEasyBeansInterceptors()) {
220                 allInterceptors.add(interceptor);
221             }
222         }
223
224         // Get interceptors on method metadata (tx, security, etc)
225
if (methodAnnotationMetadata.getInterceptors() != null) {
226             for (JClassInterceptor interceptor : methodAnnotationMetadata.getInterceptors()) {
227                 allInterceptors.add(interceptor);
228             }
229         }
230
231         // interceptors in the interceptor classes (user) + not excluded
232
if (classAnnotationMetadata.getExternalUserEasyBeansInterceptors() != null
233                 && !methodAnnotationMetadata.isExcludedClassInterceptors()) {
234             List JavaDoc<JClassInterceptor> userInterceptorslist =
235                 classAnnotationMetadata.getExternalUserEasyBeansInterceptors().get(interceptorType);
236             if (userInterceptorslist != null) {
237                 for (JClassInterceptor interceptor : userInterceptorslist) {
238                     allInterceptors.add(interceptor);
239                 }
240             }
241         }
242
243         // interceptors on the method (user)
244
if (methodAnnotationMetadata.getUserEasyBeansInterceptors() != null) {
245             List JavaDoc<JClassInterceptor> userInterceptorslist =
246                 methodAnnotationMetadata.getUserEasyBeansInterceptors().get(interceptorType);
247             if (userInterceptorslist != null) {
248                 for (JClassInterceptor interceptor : userInterceptorslist) {
249                     allInterceptors.add(interceptor);
250                 }
251             }
252         }
253
254         // interceptors on the bean class (user) + not excluded
255
if (classAnnotationMetadata.getInternalUserEasyBeansInterceptors() != null
256                 && !methodAnnotationMetadata.isExcludedClassInterceptors()) {
257             List JavaDoc<JClassInterceptor> userInterceptorslist =
258                 classAnnotationMetadata.getInternalUserEasyBeansInterceptors().get(interceptorType);
259             if (userInterceptorslist != null) {
260                 for (JClassInterceptor interceptor : userInterceptorslist) {
261                     allInterceptors.add(interceptor);
262                 }
263             }
264         }
265     }
266
267     /**
268      * Generates the class. It call sub methods for being more clear for read
269      * the code
270      */

271     public void generate() {
272         if (logger.isDebugEnabled()) {
273             logger.debug("Generating InvocationContext for Method " + jMethod + " of class " + beanClassName);
274         }
275
276         addClassDeclaration();
277         addAttributes();
278         addConstructor();
279         addStaticClassInitialization();
280         addMethods();
281         endClass();
282
283
284         if (logger.isDebugEnabled()) {
285             String JavaDoc fName = System.getProperty("java.io.tmpdir") + File.separator
286                 + generatedClassName.replace("/", ".") + ".class";
287             logger.debug("Writing Invocation context of method " + methodAnnotationMetadata.getMethodName() + " to "
288                     + fName);
289             try {
290                 FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc(fName);
291                 fos.write(getCW().toByteArray());
292                 fos.close();
293             } catch (Exception JavaDoc e) {
294                 throw new RuntimeException JavaDoc(e);
295             }
296         }
297     }
298
299     /**
300      * @return the bytecode of the generated class.
301      */

302     public byte[] getBytes() {
303         return getCW().toByteArray();
304     }
305
306
307     /**
308      * Creates the declaration of the class with the given interfaces.
309      */

310     private void addClassDeclaration() {
311         // create class
312
getCW().visit(GENERATED_CLASS_VERSION, ACC_PUBLIC + ACC_SUPER, generatedClassName, null, "java/lang/Object",
313                 INTERFACES);
314     }
315
316     /**
317      * Create the constructor which should look like :
318      * <ul>
319      * <li> First arg = bean instance</li>
320      * <li> Last args are arguments of the method (if any)</li>
321      * </ul>
322      * <br>
323      *
324      * <pre>
325      * public CtxImpl(Bean bean, int i, Long k, ...) {
326      * this.bean = bean;
327      * this.factory = bean.getEasyBeansFactory();
328      * this.interceptorManager = bean.getEasyBeansInterceptorManager();
329      * this.i = i;
330      * this.k = k;
331      * this... = ...
332      * this.interceptor0 = interceptorManager.getXXXInterceptor();
333      * this.interceptor1 = interceptorManager....();
334      * }
335      * </pre>
336      */

337     private void addConstructor() {
338
339         // First, get the desc of the intercepted method
340
String JavaDoc argsMethodDesc = "";
341         for (Type t : methodArgsType) {
342             argsMethodDesc += t.getDescriptor();
343         }
344
345
346         // Add the bean class type before arguments
347
// public CtxImpl(Bean bean, <args of the method>)
348
// it is a void type for return type
349
constructorDesc = "(" + beanClassDesc + argsMethodDesc + ")V";
350
351         // Generate constructor
352
MethodVisitor mv = getCW().visitMethod(ACC_PUBLIC, "<init>", constructorDesc, null, null);
353         mv.visitCode();
354
355         // Call super constructor
356
int arg = 1;
357         mv.visitVarInsn(ALOAD, 0);
358         mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
359
360         // Now, set the attributes of the class
361
// this.bean = bean
362
int argBean = arg++;
363         mv.visitVarInsn(ALOAD, 0);
364         mv.visitVarInsn(ALOAD, argBean);
365         mv
366                 .visitFieldInsn(PUTFIELD, generatedClassName, "bean", encodeClassDesc(classAnnotationMetadata
367                         .getClassName()));
368
369
370         // this.factory = bean.getEasyBeansFactory();
371
mv.visitVarInsn(ALOAD, 0);
372         mv.visitVarInsn(ALOAD, argBean);
373         mv.visitMethodInsn(INVOKEVIRTUAL, classAnnotationMetadata.getClassName(), "getEasyBeansFactory",
374                 "()Lorg/objectweb/easybeans/api/Factory;");
375         mv.visitFieldInsn(PUTFIELD, generatedClassName, "factory", "Lorg/objectweb/easybeans/api/Factory;");
376
377
378         // this.interceptorManager = bean.getEasyBeansInterceptorManager();
379
mv.visitVarInsn(ALOAD, 0);
380         mv.visitVarInsn(ALOAD, argBean);
381         mv.visitMethodInsn(INVOKEVIRTUAL, classAnnotationMetadata.getClassName(), "getEasyBeansInterceptorManager",
382                 "()" + encodeClassDesc(interceptorManagerClassName));
383         mv.visitFieldInsn(PUTFIELD, generatedClassName, "interceptorManager", encodeClassDesc(interceptorManagerClassName));
384
385         // And now, the attributes corresponding to the arguments of the method
386
// it will do : this.ARG0 = xxx;
387
int methodArg = 0;
388         for (Type type : methodArgsType) {
389             mv.visitVarInsn(ALOAD, 0);
390             int opCode = putFieldLoadOpCode(type.getSort());
391             mv.visitVarInsn(opCode, arg++);
392             mv.visitFieldInsn(PUTFIELD, generatedClassName, ARG + (methodArg++), type.getDescriptor());
393             // Double and Long are special parameters
394
if (opCode == LLOAD || opCode == DLOAD) {
395                 arg++;
396             }
397         }
398
399
400         // this.interceptorXX = interceptorManager.getXXXInterceptor();
401
int index = 0;
402         for (JClassInterceptor interceptor : allInterceptors) {
403             // Only if interceptor is not in the bean class
404
if (!interceptor.getClassName().equals(beanClassName)) {
405                 mv.visitVarInsn(ALOAD, 0);
406                 mv.visitVarInsn(ALOAD, 0);
407                 mv.visitFieldInsn(GETFIELD, generatedClassName, "interceptorManager",
408                         encodeClassDesc(interceptorManagerClassName));
409                 String JavaDoc getterName = "get" + interceptor.getClassName().replace("/", "");
410                 mv.visitMethodInsn(INVOKEVIRTUAL, interceptorManagerClassName, getterName, "()"
411                         + encodeClassDesc(interceptor.getClassName()));
412                 mv.visitFieldInsn(PUTFIELD, generatedClassName, INTERCEPTOR + (index++), encodeClassDesc(interceptor
413                         .getClassName()));
414             }
415         }
416
417
418
419         // need to add return instruction
420
mv.visitInsn(RETURN);
421
422         // visit max compute automatically
423
mv.visitMaxs(0, 0);
424         mv.visitEnd();
425
426     }
427
428     /**
429      * Called when the generated class is done.
430      */

431     private void endClass() {
432         getCW().visitEnd();
433     }
434
435     /**
436      * Add attributes of the class in two steps.
437      * <ul>
438      * <li>InvocationContext interface</li>
439      * <li>EasyBeansInvocationContext interface</li>
440      * </ul>
441      */

442     private void addAttributes() {
443         addInvocationContextAttributes();
444         addEasyBeansInvocationContextAttributes();
445
446     }
447
448     /**
449      * Add methods of the class in two steps.
450      * <ul>
451      * <li>InvocationContext interface</li>
452      * <li>EasyBeansInvocationContext interface</li>
453      * <li>toString() method</li>
454      * </ul>
455      */

456     private void addMethods() {
457         addInvocationContextMethods();
458         addEasyBeansInvocationContextMethods();
459         addToString();
460
461     }
462
463     /**
464      * Add methods for InvocationContext interface.
465      */

466     private void addInvocationContextMethods() {
467         addInvocationContextGetParameters();
468         addInvocationContextSetParameters();
469         addInvocationContextGetMethod();
470         addInvocationContextGetTarget();
471         addInvocationContextProceed();
472         addInvocationContextGetContextData();
473     }
474
475     /**
476      * Add methods for EasyBeansInvocationContext interface.
477      */

478     private void addEasyBeansInvocationContextMethods() {
479
480         addEasyBeansInvocationContextGetFactory();
481
482     }
483
484
485     /**
486      * Adds the getTarget method of InvocationContext interface.<br>
487      * It adds :
488      *
489      * <pre>
490      * public Object getTarget() {
491      * return bean;
492      * }
493      * </pre>
494      */

495     private void addInvocationContextGetTarget() {
496         MethodVisitor mv = getCW().visitMethod(ACC_PUBLIC, "getTarget", "()Ljava/lang/Object;", null, null);
497         mv.visitCode();
498         mv.visitVarInsn(ALOAD, 0);
499         mv.visitFieldInsn(GETFIELD, generatedClassName, "bean", beanClassDesc);
500         mv.visitInsn(ARETURN);
501         mv.visitMaxs(0, 0);
502         mv.visitEnd();
503     }
504
505
506     /**
507      * Adds the getFactory method of EasyBeansInvocationContext interface.<br>
508      * It adds :
509      *
510      * <pre>
511      * public Factory getFactory() {
512      * return this.factory;
513      * }
514      * </pre>
515      */

516     private void addEasyBeansInvocationContextGetFactory() {
517         MethodVisitor mv = getCW().visitMethod(ACC_PUBLIC, "getFactory", "()" + EASYBEANS_FACTORY, null, null);
518         mv.visitCode();
519         mv.visitVarInsn(ALOAD, 0);
520         mv.visitFieldInsn(GETFIELD, generatedClassName, "factory", EASYBEANS_FACTORY);
521         mv.visitInsn(ARETURN);
522         mv.visitMaxs(0, 0);
523         mv.visitEnd();
524
525     }
526
527
528     /**
529      * Adds the getMethod() method of InvocationContext interface.<br>
530      * It adds :
531      *
532      * <pre>
533      * public Method getMethod() {
534      * if (method == null) {
535      * try {
536      * method = MyEjb.class.getMethod("methodName", new Class[] {xxx, yyy, ...});
537      * } catch (SecurityException e) {
538      * throw new RuntimeException("Cannot...", e);
539      * } catch (NoSuchMethodException e) {
540      * throw new RuntimeException("Cannot...", e);
541      * }
542      * }
543      * return method;
544      * }
545      * </pre>
546      */

547     private void addInvocationContextGetMethod() {
548         MethodVisitor mv = getCW().visitMethod(ACC_PUBLIC, "getMethod", "()" + JAVA_LANG_REFLECT_METHOD, null, null);
549         mv.visitCode();
550
551         // only for around invoke type, lifecycle interceptor should return null
552
if (interceptorType == AROUND_INVOKE) {
553
554             // if (method == null) {
555
mv.visitFieldInsn(GETSTATIC, generatedClassName, "method", JAVA_LANG_REFLECT_METHOD);
556             // go to this label if not null
557
Label notNullParametersLabel = new Label();
558             mv.visitJumpInsn(IFNONNULL, notNullParametersLabel);
559
560
561             // Start of the try block
562
Label tryLabel = new Label();
563             mv.visitLabel(tryLabel);
564
565             // call a method on the bean class
566
mv.visitLdcInsn(beanClassType);
567             // name of the method which is searched
568
mv.visitLdcInsn(jMethod.getName());
569
570
571             // build an array of java.lang.Class with the size of args of the method
572
mv.visitIntInsn(BIPUSH, methodArgsType.length);
573             mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");
574             int argCount = 0;
575             for (Type type : methodArgsType) {
576                 mv.visitInsn(DUP);
577                 mv.visitIntInsn(BIPUSH, argCount);
578                 visitClassType(type, mv);
579                 mv.visitInsn(AASTORE);
580                 argCount++;
581             }
582
583             // signature of the getMethod() method on java.lang.Class class
584
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class",
585                     "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
586
587             // set the result : method = ...
588
mv.visitFieldInsn(PUTSTATIC, generatedClassName, "method", "Ljava/lang/reflect/Method;");
589
590
591             // go to the return label
592
mv.visitJumpInsn(GOTO, notNullParametersLabel);
593
594             // start of the catch label which throw a runtime exception
595
// } catch (SecurityException e) {
596
// throw new RuntimeException("Cannot...", e);
597
// }
598
Label firstCatchLabel = new Label();
599             mv.visitLabel(firstCatchLabel);
600             mv.visitVarInsn(ASTORE, 1);
601             mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
602             mv.visitInsn(DUP);
603             mv.visitLdcInsn("Cannot find method due to a security exception");
604             mv.visitVarInsn(ALOAD, 1);
605             mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>",
606                     "(Ljava/lang/String;Ljava/lang/Throwable;)V");
607             mv.visitInsn(ATHROW);
608
609
610             // } catch (NoSuchMethodException e) {
611
// throw new RuntimeException("Cannot...", e);
612
// }
613
Label secondCatchLabel = new Label();
614             mv.visitLabel(secondCatchLabel);
615             mv.visitVarInsn(ASTORE, 1);
616             mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
617             mv.visitInsn(DUP);
618             mv.visitLdcInsn("Cannot find the method");
619             mv.visitVarInsn(ALOAD, 1);
620             mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>",
621                     "(Ljava/lang/String;Ljava/lang/Throwable;)V");
622             mv.visitInsn(ATHROW);
623
624
625             // if method is not null, return it
626
mv.visitLabel(notNullParametersLabel);
627             mv.visitFieldInsn(GETSTATIC, generatedClassName, "method", JAVA_LANG_REFLECT_METHOD);
628             mv.visitInsn(ARETURN);
629
630             // add try/cacth
631
mv.visitTryCatchBlock(tryLabel, firstCatchLabel, firstCatchLabel, "java/lang/SecurityException");
632             mv.visitTryCatchBlock(tryLabel, firstCatchLabel, secondCatchLabel, "java/lang/NoSuchMethodException");
633         } else {
634             // for lifecycle method
635
mv.visitInsn(ACONST_NULL);
636             mv.visitInsn(ARETURN);
637         }
638
639
640         // finish
641
mv.visitMaxs(0, 0);
642         mv.visitEnd();
643
644
645     }
646     /**
647      * Adds attributes of InvocationContext interface.
648      *
649      * <pre>
650      * private StatelessBean bean;
651      * private Object[] parameters;
652      * private static Method method;
653      * private int interceptor;
654      * private Map contextData;
655      *
656      * // args of the method
657      * private TYPE_ARG_METHOD arg0 = xxx;
658      * private TYPE_ARG_METHOD arg1 = xxx;
659      * private TYPE_ARG_METHOD arg2 = xxx;
660      * private TYPE_ARG_METHOD.......;
661      * </pre>
662      */

663     private void addInvocationContextAttributes() {
664
665         // Add bean attribute
666
// private StatelessBean bean;
667
addAttribute(ACC_PRIVATE, "bean", beanClassDesc);
668
669         // Add parameters attribute
670
// private Object[] parameters;
671
addAttribute(ACC_PRIVATE, "parameters", ARRAY_OBJECTS);
672
673         // Add java.lang.reflect.Method attribute
674
// private static Method method;
675
addAttribute(ACC_PRIVATE + ACC_STATIC, "method", JAVA_LANG_REFLECT_METHOD);
676
677         // Add the interceptor counter
678
// private int interceptor;
679
addAttribute(ACC_PRIVATE, "interceptor", "I", new Integer JavaDoc(0));
680
681         // Now, add argument of the method as attributes
682
int arg = 0;
683         for (Type t : methodArgsType) {
684             addAttribute(ACC_PRIVATE, ARG + (arg++), t.getDescriptor());
685         }
686
687         // Now, add interceptors objects
688
int intercpt = 0;
689         for (JClassInterceptor interceptor : allInterceptors) {
690             // Only if interceptor is not in the bean class
691
if (!interceptor.getClassName().equals(beanClassName)) {
692                 addAttribute(ACC_PRIVATE , INTERCEPTOR + (intercpt++), encodeClassDesc(interceptor.getClassName()));
693             }
694         }
695
696         // ContextData
697
addAttribute(ACC_PRIVATE, "contextData", "Ljava/util/Map;");
698
699     }
700
701     /**
702      * Adds the initialization of static attributes.
703      * ie : private static Method method = null
704      * private static InterceptorClass interceptor0 = new MyInterceptor();
705      * private static InterceptorClass2 interceptor1 = ....
706      */

707     private void addStaticClassInitialization() {
708         MethodVisitor mv = getCW().visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
709         mv.visitCode();
710
711         // private static Method method = null
712
mv.visitInsn(ACONST_NULL);
713         mv.visitFieldInsn(PUTSTATIC, generatedClassName, "method", JAVA_LANG_REFLECT_METHOD);
714
715
716         mv.visitInsn(RETURN);
717         mv.visitMaxs(0, 0);
718         mv.visitEnd();
719
720     }
721
722
723
724     /**
725      * Adds attributes of EasyBeansInvocationContext interface.
726      *
727      * <pre>
728      * private Factory factory;
729      * </pre>
730      */

731     private void addEasyBeansInvocationContextAttributes() {
732
733         // Add factory attribute
734
// private Factory factory;
735
addAttribute(ACC_PRIVATE, "factory", EASYBEANS_FACTORY);
736
737
738         // Add interceptor manager attribute
739
// private interceptorManagerClassName interceptorManager;
740
addAttribute(ACC_PRIVATE, "interceptorManager", encodeClassDesc(interceptorManagerClassName));
741
742     }
743
744     /**
745      * Adds the proceed method.<br>
746      * It adds :
747      *
748      * <pre>
749      * public Object proceed() throws Exception {
750      * interceptor++;
751      * switch (interceptor) {
752      * case 1 :
753      * return myInterceptor.intercept(this);
754      * case 2 :
755      * return otherInterceptor.intercept(this);
756      * case 3 :
757      * return bean.originalmethod(...);
758      * default:
759      * throw new IllegalStateException("Problem in interceptors");
760      * }
761      * }
762      * </pre>
763      */

764     private void addInvocationContextProceed() {
765         MethodVisitor mv = getCW()
766                 .visitMethod(ACC_PUBLIC, "proceed", "()" + JAVA_LANG_OBJECT, null, PROCEED_EXCEPTIONS);
767         mv.visitCode();
768
769
770         // interceptor++ or in fact : interceptor = interceptor + 1;
771
mv.visitVarInsn(ALOAD, 0);
772         mv.visitInsn(DUP);
773         mv.visitFieldInsn(GETFIELD, generatedClassName, "interceptor", "I");
774         mv.visitInsn(ICONST_1);
775         mv.visitInsn(IADD); // + 1
776
mv.visitFieldInsn(PUTFIELD, generatedClassName, "interceptor", "I");
777
778
779
780         // load interceptor constant to do the switch
781
mv.visitVarInsn(ALOAD, 0);
782         mv.visitFieldInsn(GETFIELD, generatedClassName, "interceptor", "I");
783
784
785         // Size
786
int sizeInterceptors = allInterceptors.size();
787
788         // need to add call to the original method
789
int switchSize = sizeInterceptors + 1;
790
791         // Build array of labels corresponding to swtich entries
792
Label[] switchLabels = new Label[switchSize];
793         for (int s = 0; s < switchSize; s++) {
794             switchLabels[s] = new Label();
795         }
796
797         // default label
798
Label defaultCaseLabel = new Label();
799
800         // switch
801
mv.visitTableSwitchInsn(1, switchSize, defaultCaseLabel, switchLabels);
802
803         // add each interceptor switch entry with a return block at the end
804
// ie : case 1 :
805
// return myInterceptor.intercept(this); // interceptor class
806
// or case 1 :
807
// return bean.intercept(this) // bean class
808
int index = 0;
809         int interceptorIndex = 0;
810         for (JClassInterceptor interceptor : allInterceptors) {
811             mv.visitLabel(switchLabels[index]);
812
813             Type returnType = Type.getReturnType(interceptor.getJMethod().getDescriptor());
814
815             // interceptor on the bean
816
if (interceptor.getClassName().equals(beanClassName)) {
817                 mv.visitVarInsn(ALOAD, 0);
818                 mv.visitFieldInsn(GETFIELD, generatedClassName, "bean", beanClassDesc);
819                 mv.visitVarInsn(ALOAD, 0);
820                 mv.visitMethodInsn(INVOKEVIRTUAL, beanClassName,
821                         interceptor.getJMethod().getName(), interceptor.getJMethod().getDescriptor());
822
823                 // return object or null if the return type is void
824
returnsObject(returnType, mv);
825             } else { // interceptor in another class
826
mv.visitVarInsn(ALOAD, 0);
827                 mv.visitFieldInsn(GETFIELD, generatedClassName, INTERCEPTOR + interceptorIndex ,
828                         encodeClassDesc(interceptor.getClassName()));
829                 mv.visitVarInsn(ALOAD, 0);
830                 mv.visitMethodInsn(INVOKEVIRTUAL, interceptor.getClassName(),
831                 interceptor.getJMethod().getName(), interceptor.getJMethod().getDescriptor());
832                 // return object or null if the return type is void
833
returnsObject(returnType, mv);
834                 interceptorIndex++;
835             }
836             index++;
837         }
838
839         // then, add call to original method, ie bean.businessMethod(i,j,...);
840
mv.visitLabel(switchLabels[index++]);
841         // get bean object
842
mv.visitVarInsn(ALOAD, 0);
843         mv.visitFieldInsn(GETFIELD, generatedClassName, "bean", beanClassDesc);
844
845         // arguments of the method
846
int indexArg = 0;
847         for (Type argType : methodArgsType) {
848             mv.visitVarInsn(ALOAD, 0);
849             mv.visitFieldInsn(GETFIELD, generatedClassName, ARG + (indexArg++), argType.getDescriptor());
850         }
851
852         // Call to the renamed method only for AroundInvoke
853
// LifeCycle interceptors call the original method
854
String JavaDoc interceptedMethod = null;
855         if (interceptorType.equals(AROUND_INVOKE)) {
856             interceptedMethod = MethodRenamer.encode(jMethod.getName());
857         } else {
858             interceptedMethod = jMethod.getName();
859         }
860
861         mv.visitMethodInsn(INVOKEVIRTUAL, beanClassName, interceptedMethod, jMethod.getDescriptor());
862         Type returnType = Type.getReturnType(jMethod.getDescriptor());
863         // return object or null if the return type is void
864
returnsObject(returnType, mv);
865
866
867         // default case
868
mv.visitLabel(defaultCaseLabel);
869         mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
870         mv.visitInsn(DUP);
871         mv.visitLdcInsn("Problem in interceptors. Shouldn't go in the default case.");
872         mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>", "(Ljava/lang/String;)V");
873         mv.visitInsn(ATHROW);
874
875         // end
876
mv.visitMaxs(0, 0);
877         mv.visitEnd();
878     }
879
880     /**
881      * Adds the getContextData() method.
882      * <pre>
883      * public Map getContextData() {
884      * if (contextData == null) {
885      * contextData = new HashMap();
886      * }
887      * return contextData;
888      * }
889      * </pre>
890      *
891      */

892     public void addInvocationContextGetContextData() {
893         MethodVisitor mv = getCW().visitMethod(ACC_PUBLIC, "getContextData", "()Ljava/util/Map;", null, null);
894             mv.visitCode();
895             mv.visitVarInsn(ALOAD, 0);
896             mv.visitFieldInsn(GETFIELD, generatedClassName, "contextData", "Ljava/util/Map;");
897
898             Label elseLabel = new Label();
899             mv.visitJumpInsn(IFNONNULL, elseLabel);
900
901             // if
902
mv.visitVarInsn(ALOAD, 0);
903             mv.visitTypeInsn(NEW, "java/util/HashMap");
904             mv.visitInsn(DUP);
905             mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashMap", "<init>", "()V");
906             mv.visitFieldInsn(PUTFIELD, generatedClassName, "contextData", "Ljava/util/Map;");
907
908             // else
909
mv.visitLabel(elseLabel);
910             mv.visitVarInsn(ALOAD, 0);
911             mv.visitFieldInsn(GETFIELD, generatedClassName, "contextData", "Ljava/util/Map;");
912
913             // return
914
mv.visitInsn(ARETURN);
915
916             mv.visitMaxs(0, 0);
917             mv.visitEnd();
918
919
920     }
921
922     /**
923      * Adds the getParameters method of InvocationContext interface.<br>
924      * It adds :
925      *
926      * <pre>
927      * public Object[] getParameters() {
928      * if (parameters == null) {
929      * parameters = new Object[] {arg0, arg1, argxxx};
930      * }
931      * return parameters;
932      * }
933      * </pre>
934      */

935     private void addInvocationContextGetParameters() {
936         MethodVisitor mv = getCW().visitMethod(ACC_PUBLIC, "getParameters", "()" + ARRAY_OBJECTS, null, null);
937         mv.visitCode();
938
939         // only for around invoke type
940
if (interceptorType == AROUND_INVOKE) {
941
942             // if (parameters == null) {
943
mv.visitVarInsn(ALOAD, 0);
944             mv.visitFieldInsn(GETFIELD, generatedClassName, "parameters", ARRAY_OBJECTS);
945             // go to this label if not null
946
Label notNullParametersLabel = new Label();
947             mv.visitJumpInsn(IFNONNULL, notNullParametersLabel);
948
949             // parameters = new Object[] {arg0, arg1, arg...};
950
// put size of the array
951
mv.visitVarInsn(ALOAD, 0);
952             mv.visitIntInsn(BIPUSH, methodArgsType.length);
953             mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
954
955             // for each argument of the methods :
956
int argCount = 0;
957             for (Type type : methodArgsType) {
958                 mv.visitInsn(DUP);
959                 mv.visitIntInsn(BIPUSH, argCount);
960                 mv.visitVarInsn(ALOAD, 0);
961                 mv.visitFieldInsn(GETFIELD, generatedClassName, ARG + argCount, type.getDescriptor());
962                 // if type is not object type, need to convert it
963
// for example : Integer.valueOf(i);
964
transformPrimitiveIntoObject(type, mv);
965                 mv.visitInsn(AASTORE);
966                 argCount++;
967             }
968
969             // store field
970
mv.visitFieldInsn(PUTFIELD, generatedClassName, "parameters", ARRAY_OBJECTS);
971
972             // not null label :
973
// return parameters;
974
mv.visitLabel(notNullParametersLabel);
975             mv.visitVarInsn(ALOAD, 0);
976             mv.visitFieldInsn(GETFIELD, generatedClassName, "parameters", ARRAY_OBJECTS);
977         } else {
978             // throw Exception
979
mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
980             mv.visitInsn(DUP);
981             mv.visitLdcInsn("Operation getParameters can only be applied on AroundInvoke interceptors");
982             mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>", "(Ljava/lang/String;)V");
983             mv.visitInsn(ATHROW);
984         }
985
986         // return
987
mv.visitInsn(ARETURN);
988         mv.visitMaxs(0, 0);
989         mv.visitEnd();
990
991
992     }
993
994     /**
995      * Adds the setParameters method of InvocationContext interface.<br>
996      * It adds :
997      *
998      * <pre>
999      * public void setParameters(Object aobj[]) {
1000     * if (aobj == null) {
1001     * throw new IllegalStateException("Cannot set a null array.");
1002     * }
1003     * if (aobj.length != ...) {
1004     * throw new IllegalStateException("Invalid size of the given array. The length should be '" + ... + "'.");
1005     * }
1006     * parameters = aobj;
1007     *
1008     * arg0 = (Integer) aobj[0];
1009     * arg1 = ((Integer) aobj[1]).intValue();
1010     * arg2 = ((Double) aobj[2]).doubleValue();
1011     * arg3 = ((Float) aobj[3]).floatValue();
1012     * arg4 = (String) aobj[4];
1013     * ...
1014     * }
1015     *
1016     * </pre>
1017     */

1018    private void addInvocationContextSetParameters() {
1019        MethodVisitor mv = getCW().visitMethod(ACC_PUBLIC, "setParameters", "(" + ARRAY_OBJECTS + ")V", null, null);
1020        mv.visitCode();
1021
1022        // only for aroundInvoke
1023
if (interceptorType == AROUND_INVOKE) {
1024            /**
1025             * if (aobj == null) { throw new IllegalStateException("Cannot set a
1026             * null array."); }
1027             */

1028            mv.visitVarInsn(ALOAD, 1);
1029            Label notNull = new Label();
1030            mv.visitJumpInsn(IFNONNULL, notNull);
1031            mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
1032            mv.visitInsn(DUP);
1033            mv.visitLdcInsn("Cannot set a null array.");
1034            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>", "(Ljava/lang/String;)V");
1035            mv.visitInsn(ATHROW);
1036            mv.visitLabel(notNull);
1037
1038            /**
1039             * if (aobj.length != ...) { throw new
1040             * IllegalStateException("Invalid size of the given array. The
1041             * length should be '" + ... + "'."); }
1042             */

1043            mv.visitVarInsn(ALOAD, 1);
1044            mv.visitInsn(ARRAYLENGTH);
1045            mv.visitIntInsn(BIPUSH, methodArgsType.length);
1046            Label sizeOk = new Label();
1047            mv.visitJumpInsn(IF_ICMPEQ, sizeOk);
1048            mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
1049            mv.visitInsn(DUP);
1050            mv.visitLdcInsn("Invalid size of the given array. The length should be '" + methodArgsType.length + "'.");
1051            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>", "(Ljava/lang/String;)V");
1052            mv.visitInsn(ATHROW);
1053            mv.visitLabel(sizeOk);
1054
1055            // this.parameters = parameters
1056
mv.visitVarInsn(ALOAD, 0);
1057            mv.visitVarInsn(ALOAD, 1);
1058            mv.visitFieldInsn(PUTFIELD, generatedClassName, "parameters", ARRAY_OBJECTS);
1059
1060            /**
1061             * arg0 = (Integer) aobj[0]; arg1 = ((Integer) aobj[1]).intValue();
1062             * arg2 = ((Double) aobj[2]).doubleValue(); arg3 = ((Float)
1063             * aobj[3]).floatValue(); arg4 = (String) aobj[4]; ...
1064             */

1065            int argCount = 0;
1066            for (Type type : methodArgsType) {
1067                mv.visitVarInsn(ALOAD, 0);
1068                mv.visitVarInsn(ALOAD, 1);
1069                mv.visitIntInsn(BIPUSH, argCount);
1070                mv.visitInsn(AALOAD);
1071                // Cast object Integer.valueOf(i);
1072
transformObjectIntoPrimitive(type, mv);
1073                // write result
1074
mv.visitFieldInsn(PUTFIELD, generatedClassName, ARG + argCount, type.getDescriptor());
1075                argCount++;
1076            }
1077        } else {
1078            // throw Exception
1079
mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
1080            mv.visitInsn(DUP);
1081            mv.visitLdcInsn("Operation setParameters can only be applied on AroundInvoke interceptors");
1082            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalStateException", "<init>", "(Ljava/lang/String;)V");
1083            mv.visitInsn(ATHROW);
1084        }
1085
1086        mv.visitInsn(RETURN);
1087        mv.visitMaxs(0, 0);
1088        mv.visitEnd();
1089    }
1090
1091
1092    /**
1093     * Generated toString() method.
1094     * Generated code is in the comments of the method body.
1095     */

1096    private void addToString() {
1097        MethodVisitor mv = getCW().visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
1098        mv.visitCode();
1099
1100        // local vars
1101
// 1 = sb
1102
// 2 = classNames
1103
// 3 = className
1104
// 4 = indent2
1105
// 5 = indent4
1106
// 6 = i
1107
//
1108
int localVar = 1;
1109        final int varSB = localVar++;
1110        int varCLASSNAMES = localVar++;
1111        int varCLASSNAME = localVar++;
1112        int varINDENT2 = localVar++;
1113        int varINDENT4 = localVar++;
1114        int varI = localVar++;
1115
1116        /*
1117         * StringBuilder sb = new StringBuilder();
1118         * String[] classNames = this.getClass().getName().split("\\.");
1119         * String className = classNames[classNames.length - 1];
1120         * // classname
1121         * sb.append(className);
1122         * sb.append("[\n");
1123         * String indent2 = " ";
1124         * String indent4 = " ";
1125         * sb.append(indent2);
1126         * sb.append("List of interceptors :\n");
1127         */

1128
1129        mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
1130        mv.visitInsn(DUP);
1131        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V");
1132        mv.visitVarInsn(ASTORE, varSB);
1133        mv.visitVarInsn(ALOAD, 0);
1134        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
1135        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;");
1136        mv.visitLdcInsn("\\.");
1137        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "split", "(Ljava/lang/String;)[Ljava/lang/String;");
1138        mv.visitVarInsn(ASTORE, varCLASSNAMES);
1139        mv.visitVarInsn(ALOAD, varCLASSNAMES);
1140        mv.visitVarInsn(ALOAD, varCLASSNAMES);
1141        mv.visitInsn(ARRAYLENGTH);
1142        mv.visitInsn(ICONST_1);
1143        mv.visitInsn(ISUB);
1144        mv.visitInsn(AALOAD);
1145        mv.visitVarInsn(ASTORE, varCLASSNAME);
1146        mv.visitVarInsn(ALOAD, varSB);
1147        mv.visitVarInsn(ALOAD, varCLASSNAME);
1148        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1149        mv.visitInsn(POP);
1150        mv.visitVarInsn(ALOAD, varSB);
1151        mv.visitLdcInsn("[\n");
1152        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1153        mv.visitInsn(POP);
1154        mv.visitLdcInsn(" ");
1155        mv.visitVarInsn(ASTORE, varINDENT2);
1156        mv.visitLdcInsn(" ");
1157        mv.visitVarInsn(ASTORE, varINDENT4);
1158        mv.visitVarInsn(ALOAD, varSB);
1159        mv.visitVarInsn(ALOAD, varINDENT2);
1160        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1161        mv.visitInsn(POP);
1162        mv.visitVarInsn(ALOAD, varSB);
1163        mv.visitLdcInsn("List of interceptors :\n");
1164        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1165        mv.visitInsn(POP);
1166
1167        /*
1168         * In the loop, print :
1169         * sb.append(indent4);
1170         * sb.append(i);
1171         * sb.append(") - ");
1172         * sb.append(interceptor.getClassName());
1173         * sb.append("[");
1174         * sb.append(interceptor.getJMethod().getName());
1175         * sb.append("]\n");
1176         */

1177        int i = 1;
1178
1179        // int i = 1;
1180
mv.visitInsn(ICONST_1);
1181        mv.visitVarInsn(ISTORE, varI);
1182
1183        if (allInterceptors != null) {
1184            for (JClassInterceptor interceptor : allInterceptors) {
1185                mv.visitVarInsn(ALOAD, varSB);
1186                mv.visitVarInsn(ALOAD, varINDENT4);
1187                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1188                        "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1189                mv.visitInsn(POP);
1190
1191                mv.visitVarInsn(ALOAD, varSB);
1192                mv.visitVarInsn(ILOAD, varI);
1193                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;");
1194                mv.visitInsn(POP);
1195
1196                mv.visitVarInsn(ALOAD, varSB);
1197                mv.visitLdcInsn(") - ");
1198                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1199                        "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1200                mv.visitInsn(POP);
1201
1202                // sb.append(interceptor.getClassName());
1203
mv.visitVarInsn(ALOAD, varSB);
1204                mv.visitLdcInsn(interceptor.getClassName());
1205                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1206                        "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1207                mv.visitInsn(POP);
1208
1209                mv.visitVarInsn(ALOAD, varSB);
1210                mv.visitLdcInsn("[");
1211                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1212                        "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1213                mv.visitInsn(POP);
1214
1215                // sb.append(interceptor.getJMethod().getName());
1216
mv.visitVarInsn(ALOAD, varSB);
1217                mv.visitLdcInsn(interceptor.getJMethod().getName());
1218                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1219                        "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1220                mv.visitInsn(POP);
1221
1222                mv.visitVarInsn(ALOAD, varSB);
1223                mv.visitLdcInsn("]\n");
1224                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1225                        "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1226                mv.visitInsn(POP);
1227
1228                i++;
1229                // i++
1230
mv.visitIincInsn(varI, 1);
1231            }
1232            /*
1233             * sb.append(indent2);
1234             * sb.append("Current interceptor : ");
1235             * sb.append(interceptor); sb.append("/");
1236             * sb.append(allInterceptors.size());
1237             */

1238            mv.visitVarInsn(ALOAD, varSB);
1239            mv.visitVarInsn(ALOAD, varINDENT2);
1240            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1241                    "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1242            mv.visitInsn(POP);
1243
1244            mv.visitVarInsn(ALOAD, varSB);
1245            mv.visitLdcInsn("Current interceptor : ");
1246            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1247                    "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1248            mv.visitInsn(POP);
1249
1250            mv.visitVarInsn(ALOAD, varSB);
1251            mv.visitVarInsn(ALOAD, 0);
1252            mv.visitFieldInsn(GETFIELD, generatedClassName, "interceptor", "I");
1253            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;");
1254            mv.visitInsn(POP);
1255
1256            mv.visitVarInsn(ALOAD, varSB);
1257            mv.visitLdcInsn("/");
1258            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1259                    "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1260            mv.visitInsn(POP);
1261
1262            mv.visitVarInsn(ALOAD, varSB);
1263            mv.visitLdcInsn(String.valueOf(allInterceptors.size()));
1264            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1265                    "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1266            mv.visitInsn(POP);
1267
1268        } else {
1269            /*
1270             * sb.append(indent2);
1271             * sb.append("No interceptors : ");
1272             */

1273            mv.visitVarInsn(ALOAD, varSB);
1274            mv.visitVarInsn(ALOAD, varINDENT2);
1275            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1276                    "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1277            mv.visitInsn(POP);
1278
1279            mv.visitVarInsn(ALOAD, varSB);
1280            mv.visitLdcInsn("No interceptors : ");
1281            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1282                    "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1283            mv.visitInsn(POP);
1284        }
1285
1286        /*
1287         * sb.append("\n");
1288         * sb.append("]");
1289         * return sb.toString();
1290         */

1291        mv.visitVarInsn(ALOAD, varSB);
1292        mv.visitLdcInsn("\n");
1293        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1294                "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1295        mv.visitInsn(POP);
1296
1297        mv.visitVarInsn(ALOAD, varSB);
1298        mv.visitLdcInsn("]");
1299        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
1300                "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1301        mv.visitInsn(POP);
1302
1303        mv.visitVarInsn(ALOAD, varSB);
1304        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
1305        mv.visitInsn(ARETURN);
1306
1307        mv.visitMaxs(0, 0);
1308        mv.visitEnd();
1309
1310    }
1311
1312    /**
1313     * @return method metadata used by this generator
1314     */

1315    public MethodAnnotationMetadata getMethodAnnotationMetadata() {
1316        return methodAnnotationMetadata;
1317    }
1318
1319    /**
1320     * @return the name of the generated class name (with package name)
1321     */

1322    public String JavaDoc getGeneratedClassName() {
1323        return generatedClassName;
1324    }
1325
1326    /**
1327     * @return the ASM descriptor of the generated constructor.
1328     */

1329    public String JavaDoc getConstructorDesc() {
1330        return constructorDesc;
1331    }
1332
1333    /**
1334     * @return the interceptors used by this InvocationContext implementation object.
1335     */

1336    public List JavaDoc<JClassInterceptor> getAllInterceptors() {
1337        return allInterceptors;
1338    }
1339
1340}
1341
Popular Tags