KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > aspectwerkz > transform > inlining > weaver > AddWrapperVisitor


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.weaver;
5
6 import com.tc.asm.Opcodes;
7 import com.tc.asm.ClassAdapter;
8 import com.tc.asm.ClassVisitor;
9 import com.tc.asm.MethodVisitor;
10 import com.tc.asm.Type;
11
12 import com.tc.aspectwerkz.joinpoint.management.JoinPointType;
13 import com.tc.aspectwerkz.transform.InstrumentationContext;
14 import com.tc.aspectwerkz.transform.TransformationConstants;
15 import com.tc.aspectwerkz.transform.TransformationUtil;
16 import com.tc.aspectwerkz.transform.inlining.AsmHelper;
17 import com.tc.aspectwerkz.transform.inlining.EmittedJoinPoint;
18
19 import java.util.List JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.Set JavaDoc;
22 import java.lang.reflect.Modifier JavaDoc;
23
24 /**
25  * Adds field and method and ctor wrappers when there has been at least one joinpoint emitted.
26  *
27  * @author <a HREF="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
28  * @author <a HREF="mailto:jboner@codehaus.org">Jonas Bonér </a>
29  */

30 public class AddWrapperVisitor extends ClassAdapter implements Opcodes, TransformationConstants {
31
32   private InstrumentationContext m_context;
33
34   private Set JavaDoc m_addedMethods;
35
36
37   public AddWrapperVisitor(ClassVisitor classVisitor, InstrumentationContext context, Set JavaDoc alreadyAddedMethods) {
38     super(classVisitor);
39     m_context = (InstrumentationContext) context;
40     m_addedMethods = alreadyAddedMethods;
41   }
42
43   /**
44    * Visits the class.
45    *
46    * @param access
47    * @param name
48    * @param signature
49    * @param superName
50    * @param interfaces
51    */

52   public void visit(final int version, final int access,
53                     final String JavaDoc name,
54                     final String JavaDoc signature,
55                     final String JavaDoc superName,
56                     final String JavaDoc[] interfaces) {
57     // iterate on the emitted joinpoints
58
// we don't need to filter more since the joinpoint type and the weaving phase did that for us
59
List JavaDoc jps = m_context.getEmittedJoinPoints();
60     for (Iterator JavaDoc iterator = jps.iterator(); iterator.hasNext();) {
61       EmittedJoinPoint emittedJoinPoint = (EmittedJoinPoint) iterator.next();
62       int jpType = emittedJoinPoint.getJoinPointType();
63       if (Modifier.isPublic(emittedJoinPoint.getCalleeMemberModifiers())
64               || !name.equals(emittedJoinPoint.getCalleeClassName())) {//TODO ?
65
continue;
66       }
67       switch (jpType) {
68         case (JoinPointType.FIELD_GET_INT) :
69           createGetFieldWrapperMethod(
70                   Modifier.isStatic(emittedJoinPoint.getCalleeMemberModifiers()),
71                   name,
72                   emittedJoinPoint.getCalleeMemberName(),
73                   emittedJoinPoint.getCalleeMemberDesc(),
74                   null//TODO generic is that ok ?
75
);
76           break;
77         case (JoinPointType.FIELD_SET_INT) :
78           createPutFieldWrapperMethod(
79                   Modifier.isStatic(emittedJoinPoint.getCalleeMemberModifiers()),
80                   name,
81                   emittedJoinPoint.getCalleeMemberName(),
82                   emittedJoinPoint.getCalleeMemberDesc(),
83                   null//TODO generic is that ok ?
84
);
85           break;
86         case (JoinPointType.METHOD_EXECUTION_INT) :
87         case (JoinPointType.METHOD_CALL_INT) :
88           createMethodWrapperMethod(
89                   emittedJoinPoint.getCalleeMemberModifiers(),
90                   name,
91                   emittedJoinPoint.getCalleeMemberName(),
92                   emittedJoinPoint.getCalleeMemberDesc(),
93                   null,//TODO generic is that ok ?
94
EMPTY_STRING_ARRAY//TODO should throw Throwable ??
95
);
96           break;
97         case (JoinPointType.CONSTRUCTOR_CALL_INT) :
98         case (JoinPointType.CONSTRUCTOR_EXECUTION_INT) :
99           createConstructorWrapperMethod(
100                   emittedJoinPoint.getCalleeMemberModifiers(),
101                   name,
102                   emittedJoinPoint.getCalleeMemberName(),
103                   emittedJoinPoint.getCalleeMemberDesc(),
104                   null,//TODO generic is that ok ?
105
EMPTY_STRING_ARRAY//TODO should throw Throwable ??
106
);
107           break;
108       }
109     }
110
111     super.visit(version, access, name, signature, superName, interfaces);
112   }
113
114   /**
115    * Creates a public wrapper method that delegates to the GETFIELD instruction of the non-public field.
116    *
117    * @param isStaticField
118    * @param declaringTypeName
119    * @param name
120    * @param desc
121    * @param signature
122    */

123   private void createGetFieldWrapperMethod(final boolean isStaticField,
124                                            final String JavaDoc declaringTypeName,
125                                            final String JavaDoc name,
126                                            final String JavaDoc desc,
127                                            final String JavaDoc signature) {
128     String JavaDoc wrapperName = TransformationUtil.getWrapperMethodName(
129             name, desc, declaringTypeName, GETFIELD_WRAPPER_METHOD_PREFIX
130     );
131
132     StringBuffer JavaDoc wsignature = new StringBuffer JavaDoc();
133     wsignature.append('(');
134     wsignature.append(')');
135     wsignature.append(desc);
136
137     final String JavaDoc wrapperKey = AlreadyAddedMethodAdapter.getMethodKey(wrapperName, wsignature.toString());
138     if (m_addedMethods.contains(wrapperKey)) {
139       return;
140     }
141     m_addedMethods.add(wrapperKey);
142
143     int modifiers = ACC_SYNTHETIC;
144     if (isStaticField) {
145       modifiers |= ACC_STATIC;
146     }
147
148     MethodVisitor mv = cv.visitMethod(
149             modifiers,
150             wrapperName,
151             wsignature.toString(),
152             signature,
153             EMPTY_STRING_ARRAY
154     );
155
156     if (isStaticField) {
157       mv.visitFieldInsn(GETSTATIC, declaringTypeName, name, desc);
158     } else {
159       mv.visitVarInsn(ALOAD, 0);
160       mv.visitFieldInsn(GETFIELD, declaringTypeName, name, desc);
161     }
162
163     AsmHelper.addReturnStatement(mv, Type.getType(desc));
164     mv.visitMaxs(0, 0);
165   }
166
167   /**
168    * Creates a public wrapper method that delegates to the PUTFIELD instruction of the non-public field.
169    * Static method if field is static (PUTSTATIC instr)
170    *
171    * @param isStaticField
172    * @param declaringTypeName
173    * @param name
174    * @param desc
175    * @param signature
176    */

177   private void createPutFieldWrapperMethod(boolean isStaticField,
178                                            final String JavaDoc declaringTypeName,
179                                            final String JavaDoc name,
180                                            final String JavaDoc desc,
181                                            final String JavaDoc signature) {
182     String JavaDoc wrapperName = TransformationUtil.getWrapperMethodName(
183             name, desc, declaringTypeName, PUTFIELD_WRAPPER_METHOD_PREFIX
184     );
185
186     StringBuffer JavaDoc wsignature = new StringBuffer JavaDoc();
187     wsignature.append('(');
188     wsignature.append(desc);
189     wsignature.append(')');
190     wsignature.append('V');
191
192     final String JavaDoc wrapperKey = AlreadyAddedMethodAdapter.getMethodKey(wrapperName, wsignature.toString());
193     if (m_addedMethods.contains(wrapperKey)) {
194       return;
195     }
196     m_addedMethods.add(wrapperKey);
197
198     int modifiers = ACC_SYNTHETIC;
199     if (isStaticField) {
200       modifiers |= ACC_STATIC;
201     }
202
203     MethodVisitor mv = cv.visitMethod(
204             modifiers,
205             wrapperName,
206             wsignature.toString(),
207             signature,
208             EMPTY_STRING_ARRAY
209     );
210
211     Type fieldType = Type.getType(desc);
212     if (isStaticField) {
213       AsmHelper.loadArgumentTypes(mv, new Type[]{fieldType}, true);
214       mv.visitFieldInsn(PUTSTATIC, declaringTypeName, name, desc);
215     } else {
216       mv.visitVarInsn(ALOAD, 0);
217       AsmHelper.loadArgumentTypes(mv, new Type[]{fieldType}, false);
218       mv.visitFieldInsn(PUTFIELD, declaringTypeName, name, desc);
219     }
220
221     AsmHelper.addReturnStatement(mv, Type.VOID_TYPE);
222     mv.visitMaxs(0, 0);
223   }
224
225   /**
226    * Creates a public wrapper method that delegates to the non-public target method.
227    *
228    * @param access
229    * @param declaringTypeName
230    * @param name
231    * @param desc
232    * @param signature
233    * @param exceptions
234    */

235   private void createMethodWrapperMethod(final int access,
236                                          final String JavaDoc declaringTypeName,
237                                          final String JavaDoc name,
238                                          final String JavaDoc desc,
239                                          final String JavaDoc signature,
240                                          final String JavaDoc[] exceptions) {
241     final String JavaDoc wrapperName = TransformationUtil.getWrapperMethodName(
242             name, desc, declaringTypeName, INVOKE_WRAPPER_METHOD_PREFIX
243     );
244
245     final String JavaDoc wrapperKey = AlreadyAddedMethodAdapter.getMethodKey(wrapperName, desc);
246     if (m_addedMethods.contains(wrapperKey)) {
247       return;
248     }
249     m_addedMethods.add(wrapperKey);
250
251     int modifiers = ACC_SYNTHETIC;
252     if (Modifier.isStatic(access)) {
253       modifiers |= ACC_STATIC;
254     }
255
256     MethodVisitor mv = super.visitMethod(
257             modifiers,
258             wrapperName,
259             desc,
260             signature,
261             exceptions
262     );
263
264     if (Modifier.isStatic(access)) {
265       AsmHelper.loadArgumentTypes(mv, Type.getArgumentTypes(desc), Modifier.isStatic(access));
266       mv.visitMethodInsn(INVOKESTATIC, declaringTypeName, name, desc);
267     } else {
268       mv.visitVarInsn(ALOAD, 0);
269       AsmHelper.loadArgumentTypes(mv, Type.getArgumentTypes(desc), Modifier.isStatic(access));
270       mv.visitMethodInsn(INVOKEVIRTUAL, declaringTypeName, name, desc);
271     }
272
273     AsmHelper.addReturnStatement(mv, Type.getReturnType(desc));
274
275     mv.visitMaxs(0, 0);
276   }
277
278   /**
279    * Creates a public wrapper static method that delegates to the non-public target ctor.
280    *
281    * @param access
282    * @param declaringTypeName
283    * @param name
284    * @param desc
285    * @param signature
286    * @param exceptions
287    */

288   private void createConstructorWrapperMethod(final int access,
289                                               final String JavaDoc declaringTypeName,
290                                               final String JavaDoc name,
291                                               final String JavaDoc desc,
292                                               final String JavaDoc signature,
293                                               final String JavaDoc[] exceptions) {
294     final String JavaDoc wrapperName = TransformationUtil.getWrapperMethodName(
295             name, desc, declaringTypeName, INVOKE_WRAPPER_METHOD_PREFIX
296     );
297
298     final String JavaDoc wrapperKey = AlreadyAddedMethodAdapter.getMethodKey(wrapperName, desc);
299     if (m_addedMethods.contains(wrapperKey)) {
300       return;
301     }
302     m_addedMethods.add(wrapperKey);
303
304     int modifiers = ACC_SYNTHETIC;
305     modifiers |= ACC_STATIC;
306
307     Type declaringType = Type.getType('L' + declaringTypeName + ';');
308     String JavaDoc ctorDesc = Type.getMethodDescriptor(declaringType, Type.getArgumentTypes(desc));
309
310     MethodVisitor mv = super.visitMethod(
311             modifiers,
312             wrapperName,
313             ctorDesc,
314             signature,
315             exceptions
316     );
317
318     mv.visitTypeInsn(NEW, declaringTypeName);
319     mv.visitInsn(DUP);
320     AsmHelper.loadArgumentTypes(mv, Type.getArgumentTypes(desc), true);
321     mv.visitMethodInsn(INVOKESPECIAL, declaringTypeName, name, desc);
322     AsmHelper.addReturnStatement(mv, declaringType);
323
324     mv.visitMaxs(0, 0);
325   }
326
327 }
328
Popular Tags