KickJava   Java API By Example, From Geeks To Geeks.

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


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

35 public class AddWrapperVisitor extends ClassAdapter implements Constants, TransformationConstants {
36
37     private ContextImpl m_context;
38
39     private Set JavaDoc m_addedMethods;
40
41
42     public AddWrapperVisitor(ClassVisitor classVisitor, Context context, Set JavaDoc alreadyAddedMethods) {
43         super(classVisitor);
44         m_context = (ContextImpl) context;
45         m_addedMethods = alreadyAddedMethods;
46     }
47
48     /**
49      * Visits the class.
50      *
51      * @param access
52      * @param name
53      * @param superName
54      * @param interfaces
55      * @param sourceFile
56      */

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

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

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

224     private void createMethodWrapperMethod(final int access,
225                                            final String JavaDoc declaringTypeName,
226                                            final String JavaDoc name,
227                                            final String JavaDoc desc,
228                                            final String JavaDoc[] exceptions,
229                                            final Attribute attrs) {
230         final String JavaDoc wrapperName = TransformationUtil.getWrapperMethodName(
231                 name, desc, declaringTypeName, INVOKE_WRAPPER_METHOD_PREFIX
232         );
233
234         final String JavaDoc wrapperKey = AlreadyAddedMethodAdapter.getMethodKey(wrapperName, desc);
235         if (m_addedMethods.contains(wrapperKey)) {
236             return;
237         }
238         m_addedMethods.add(wrapperKey);
239
240         int modifiers = ACC_SYNTHETIC;
241         if (Modifier.isStatic(access)) {
242             modifiers |= ACC_STATIC;
243         }
244
245         CodeVisitor mv = super.visitMethod(
246                 modifiers,
247                 wrapperName,
248                 desc,
249                 exceptions,
250                 attrs
251         );
252
253         if (Modifier.isStatic(access)) {
254             AsmHelper.loadArgumentTypes(mv, Type.getArgumentTypes(desc), Modifier.isStatic(access));
255             mv.visitMethodInsn(INVOKESTATIC, declaringTypeName, name, desc);
256         } else {
257             mv.visitVarInsn(ALOAD, 0);
258             AsmHelper.loadArgumentTypes(mv, Type.getArgumentTypes(desc), Modifier.isStatic(access));
259             mv.visitMethodInsn(INVOKEVIRTUAL, declaringTypeName, name, desc);
260         }
261
262         AsmHelper.addReturnStatement(mv, Type.getReturnType(desc));
263
264         mv.visitMaxs(0, 0);
265     }
266
267 }
268
Popular Tags