KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > transform > inlining > weaver > JoinPointInitVisitor


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

8 package org.codehaus.aspectwerkz.transform.inlining.weaver;
9
10 import org.objectweb.asm.ClassAdapter;
11 import org.objectweb.asm.ClassVisitor;
12 import org.objectweb.asm.CodeVisitor;
13 import org.objectweb.asm.Attribute;
14 import org.objectweb.asm.CodeAdapter;
15 import org.codehaus.aspectwerkz.transform.Context;
16 import org.codehaus.aspectwerkz.transform.TransformationConstants;
17 import org.codehaus.aspectwerkz.transform.inlining.ContextImpl;
18 import org.codehaus.aspectwerkz.transform.inlining.EmittedJoinPoint;
19
20 import java.util.Iterator JavaDoc;
21
22 /**
23  * A ClassAdapter that take care of all weaved class and add the glue between the class and its JIT dependencies.
24  * <p/>
25  * Adds a 'private static final Class aw$clazz' field a 'private static void ___AW_$_AW_$initJoinPoints()' method
26  * and patches the 'clinit' method.
27  * <p/>
28  * If the class has been made advisable, we also add a ___AW_$_AW_$emittedJoinPoints fields that gets populated.
29  *
30  *
31  * @author <a HREF="mailto:alex@gnilux.com">Alexandre Vasseur </a>
32  * @author <a HREF="mailto:jboner@codehaus.org">Jonas Bonér </a>
33  * @TODO: for multi weaving, we could go on in adding several AW initJoinPoints_xxWeaveCount method, but then cannot be
34  * done with RW
35  */

36 public class JoinPointInitVisitor extends ClassAdapter implements TransformationConstants {
37
38     private final ContextImpl m_ctx;
39     private boolean m_hasClinitMethod = false;
40     private boolean m_hasInitJoinPointsMethod = false;
41     private boolean m_hasClassField = false;
42     private boolean m_hasEmittedJoinPointsField = false;
43
44     /**
45      * Creates a new instance.
46      *
47      * @param cv
48      * @param ctx
49      */

50     public JoinPointInitVisitor(final ClassVisitor cv, final Context ctx) {
51         super(cv);
52         m_ctx = (ContextImpl) ctx;
53     }
54
55     /**
56      * Visits the methods. If the AW joinPointsInit method is found, remember that, it means we are in a multi-weaving
57      * scheme. Patch the 'clinit' method if already present.
58      *
59      * @TODO: multi-weaving will lead to several invocation of AW initJoinPoints and several assigment of __AW_Clazz in the patched clinit which slows down a bit the load time
60      * @see org.objectweb.asm.ClassVisitor#visitMethod(int, java.lang.String, java.lang.String, java.lang.String[],
61             * org.objectweb.asm.Attribute)
62      */

63     public CodeVisitor visitMethod(final int access,
64                                    final String JavaDoc name,
65                                    final String JavaDoc desc,
66                                    final String JavaDoc[] exceptions,
67                                    final Attribute attrs) {
68
69         if (CLINIT_METHOD_NAME.equals(name)) {
70             m_hasClinitMethod = true;
71             // at the beginning of the existing <clinit> method
72
// ___AWClazz = Class.forName("TargetClassName");
73
// ___AW_$_AW_$initJoinPoints();
74
CodeVisitor ca = new InsertBeforeClinitCodeAdapter(cv.visitMethod(access, name, desc, exceptions, attrs));
75             ca.visitMaxs(0, 0);
76             return ca;
77
78         } else if (INIT_JOIN_POINTS_METHOD_NAME.equals(name)) {
79             m_hasInitJoinPointsMethod = true;
80             // add the gathered JIT dependencies for multi-weaving support
81
CodeVisitor ca = new InsertBeforeInitJoinPointsCodeAdapter(
82                     cv.visitMethod(access, name, desc, exceptions, attrs)
83             );
84             ca.visitMaxs(0, 0);
85             return ca;
86         } else {
87             return super.visitMethod(access, name, desc, exceptions, attrs);
88         }
89     }
90
91     /**
92      * Remember if we have already the static class field for multi-weaving scheme.
93      *
94      * @param access
95      * @param name
96      * @param desc
97      * @param value
98      * @param attrs
99      */

100     public void visitField(int access, String JavaDoc name, String JavaDoc desc, Object JavaDoc value, Attribute attrs) {
101         if (TARGET_CLASS_FIELD_NAME.equals(name)) {
102             m_hasClassField = true;
103         } else if (EMITTED_JOINPOINTS_FIELD_NAME.equals(name)) {
104             m_hasEmittedJoinPointsField = true;
105         }
106         super.visitField(access, name, desc, value, attrs);
107     }
108
109     /**
110      * Finalize the visit. Add static class field if needed, add initJoinPoints method if needed, add <clinit>if
111      * needed.
112      */

113     public void visitEnd() {
114         if (!m_ctx.isAdvised()) {
115             super.visitEnd();
116             return;
117         }
118
119         if (!m_hasClassField) {
120             // create field
121
// private final static Class aw$clazz = Class.forName("TargetClassName");
122
cv.visitField(
123                     ACC_PRIVATE + ACC_FINAL + ACC_STATIC + ACC_SYNTHETIC,
124                     TARGET_CLASS_FIELD_NAME,
125                     CLASS_CLASS_SIGNATURE,
126                     null,
127                     null
128             );
129         }
130
131         if (!m_hasEmittedJoinPointsField && m_ctx.isMadeAdvisable()) {
132             // create field
133
// private final static Class aw$emittedJoinPoints that will host a Trove int Object map
134
cv.visitField(
135                     ACC_PRIVATE + ACC_FINAL + ACC_STATIC + ACC_SYNTHETIC,
136                     EMITTED_JOINPOINTS_FIELD_NAME,
137                     "Lgnu/trove/TIntObjectHashMap;",
138                     null,
139                     null
140             );
141         }
142
143         if (!m_hasClinitMethod) {
144             CodeVisitor ca = new InsertBeforeClinitCodeAdapter(
145                     cv.visitMethod(
146                             ACC_STATIC,
147                             CLINIT_METHOD_NAME,
148                             NO_PARAMS_RETURN_VOID_METHOD_SIGNATURE,
149                             null,
150                             null
151                     )
152             );
153             ca.visitInsn(RETURN);
154             ca.visitMaxs(0, 0);
155         }
156
157         if (!m_hasInitJoinPointsMethod) {
158             CodeVisitor mv = new InsertBeforeInitJoinPointsCodeAdapter(
159                     cv.visitMethod(
160                             ACC_PRIVATE + ACC_FINAL + ACC_STATIC + ACC_SYNTHETIC,
161                             INIT_JOIN_POINTS_METHOD_NAME,
162                             NO_PARAMS_RETURN_VOID_METHOD_SIGNATURE,
163                             null,
164                             null
165                     )
166             );
167             mv.visitInsn(RETURN);
168             mv.visitMaxs(0, 0);
169         }
170
171         cv.visitEnd();
172     }
173
174     /**
175      * Handles the method body of the <clinit>method.
176      *
177      * @author <a HREF="mailto:alex@gnilux.com">Alexandre Vasseur </a>
178      */

179     public class InsertBeforeClinitCodeAdapter extends CodeAdapter {
180
181         public InsertBeforeClinitCodeAdapter(CodeVisitor ca) {
182             super(ca);
183             if (!m_hasClassField) {
184                 cv.visitLdcInsn(m_ctx.getClassName().replace('/', '.'));
185                 cv.visitMethodInsn(INVOKESTATIC, CLASS_CLASS, FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
186                 cv.visitFieldInsn(PUTSTATIC, m_ctx.getClassName(), TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
187             }
188             if (!m_hasEmittedJoinPointsField && m_ctx.isMadeAdvisable()) {
189                 // aw$emittedJoinPoints = new TIntObjectHashMap()
190
cv.visitTypeInsn(NEW, "gnu/trove/TIntObjectHashMap");
191                 cv.visitInsn(DUP);
192                 cv.visitMethodInsn(INVOKESPECIAL, "gnu/trove/TIntObjectHashMap", "<init>", "()V");
193                 cv.visitFieldInsn(PUTSTATIC, m_ctx.getClassName(), EMITTED_JOINPOINTS_FIELD_NAME, "Lgnu/trove/TIntObjectHashMap;");
194             }
195             if (!m_hasClassField) {
196                 cv.visitMethodInsn(
197                         INVOKESTATIC,
198                         m_ctx.getClassName(),
199                         INIT_JOIN_POINTS_METHOD_NAME,
200                         NO_PARAMS_RETURN_VOID_METHOD_SIGNATURE
201                 );
202             }
203         }
204     }
205
206     /**
207      * Handles the method body of the AW initJoinPoints method.
208      *
209      * @author <a HREF="mailto:alex@gnilux.com">Alexandre Vasseur </a>
210      * @author <a HREF="mailto:jboner@codehaus.org">Jonas Bonér </a>
211      */

212     public class InsertBeforeInitJoinPointsCodeAdapter extends CodeAdapter {
213
214         public InsertBeforeInitJoinPointsCodeAdapter(CodeVisitor ca) {
215             super(ca);
216
217             // loop over emitted jp and insert call to "JoinPointManager.loadJoinPoint(...)"
218
// add calls to aw$emittedJoinPoints.put(.. new EmittedJoinPoint) if needed.
219
for (Iterator JavaDoc iterator = m_ctx.getEmittedJoinPoints().iterator(); iterator.hasNext();) {
220
221                 EmittedJoinPoint jp = (EmittedJoinPoint) iterator.next();
222                 cv.visitLdcInsn(new Integer JavaDoc(jp.getJoinPointType()));
223
224                 cv.visitFieldInsn(GETSTATIC, m_ctx.getClassName(), TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
225                 cv.visitLdcInsn(jp.getCallerMethodName());
226                 cv.visitLdcInsn(jp.getCallerMethodDesc());
227                 cv.visitLdcInsn(new Integer JavaDoc(jp.getCallerMethodModifiers()));
228
229                 cv.visitLdcInsn(jp.getCalleeClassName());
230                 cv.visitLdcInsn(jp.getCalleeMemberName());
231                 cv.visitLdcInsn(jp.getCalleeMemberDesc());
232                 cv.visitLdcInsn(new Integer JavaDoc(jp.getCalleeMemberModifiers()));
233
234                 cv.visitLdcInsn(new Integer JavaDoc(jp.getJoinPointHash()));
235                 cv.visitLdcInsn(jp.getJoinPointClassName());
236                 cv.visitMethodInsn(
237                         INVOKESTATIC,
238                         JOIN_POINT_MANAGER_CLASS_NAME,
239                         LOAD_JOIN_POINT_METHOD_NAME,
240                         LOAD_JOIN_POINT_METHOD_SIGNATURE
241                 );
242
243                 if (m_ctx.isMadeAdvisable()) {
244                     // trove map
245
cv.visitFieldInsn(GETSTATIC, m_ctx.getClassName(), EMITTED_JOINPOINTS_FIELD_NAME, "Lgnu/trove/TIntObjectHashMap;");
246                     // trove map key
247
cv.visitLdcInsn(new Integer JavaDoc(jp.getJoinPointClassName().hashCode()));
248
249
250                     cv.visitTypeInsn(NEW, "org/codehaus/aspectwerkz/transform/inlining/EmittedJoinPoint");
251                     cv.visitInsn(DUP);
252
253                     cv.visitLdcInsn(new Integer JavaDoc(jp.getJoinPointType()));
254
255                     cv.visitLdcInsn(m_ctx.getClassName());
256                     cv.visitLdcInsn(jp.getCallerMethodName());
257                     cv.visitLdcInsn(jp.getCallerMethodDesc());
258                     cv.visitLdcInsn(new Integer JavaDoc(jp.getCallerMethodModifiers()));
259
260                     cv.visitLdcInsn(jp.getCalleeClassName());
261                     cv.visitLdcInsn(jp.getCalleeMemberName());
262                     cv.visitLdcInsn(jp.getCalleeMemberDesc());
263                     cv.visitLdcInsn(new Integer JavaDoc(jp.getCalleeMemberModifiers()));
264
265                     cv.visitLdcInsn(new Integer JavaDoc(jp.getJoinPointHash()));
266                     cv.visitLdcInsn(jp.getJoinPointClassName());
267
268                     cv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/aspectwerkz/transform/inlining/EmittedJoinPoint", "<init>",
269                             "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;IILjava/lang/String;)V"
270                             );
271                     cv.visitMethodInsn(
272                             INVOKEVIRTUAL,
273                             "gnu/trove/TIntObjectHashMap",
274                             "put",
275                             "(ILjava/lang/Object;)Ljava/lang/Object;"
276                     );
277                 }
278             }
279         }
280     }
281
282 }
Popular Tags