KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > aop > instrument > GeneratedAdvisorFieldAccessTransformer


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.aop.instrument;
23
24 import java.util.ArrayList JavaDoc;
25
26 import org.jboss.aop.util.JavassistMethodHashing;
27
28 import javassist.CannotCompileException;
29 import javassist.CtClass;
30 import javassist.CtField;
31 import javassist.CtMethod;
32 import javassist.Modifier;
33 import javassist.NotFoundException;
34 import javassist.expr.FieldAccess;
35
36 /**
37  * Comment
38  *
39  * @author <a HREF="mailto:kabir.khan@jboss.org">Kabir Khan</a>
40  * @version $Revision$
41  */

42 public class GeneratedAdvisorFieldAccessTransformer extends FieldAccessTransformer
43 {
44
45    public GeneratedAdvisorFieldAccessTransformer(Instrumentor instrumentor)
46    {
47       super(instrumentor);
48    }
49
50    protected void doBuildFieldWrappers(CtClass clazz, CtField field, int index, JoinpointClassification classificationGet, JoinpointClassification classificationSet) throws NotFoundException, CannotCompileException
51    {
52       instrumentor.setupBasics(clazz);
53       boolean wrappedGet = classificationGet.equals(JoinpointClassification.WRAPPED);
54       boolean wrappedSet = classificationSet.equals(JoinpointClassification.WRAPPED);
55       int mod = field.getModifiers();
56
57       //Create placeholder static wrappers, since without these methods replaceFieldAccessInternally()
58
//will not compile.
59
//If we add the actual static wrappers before calling replaceFieldAccessInternally()
60
//field access done in the inner invocation classes as well as in the static wrappers
61
//is replaced with a call to the wrapper instead, which means infinite recursion
62
buildWrapperPlaceHolders(clazz,
63             field,
64             isPrepared(classificationGet),
65             isPrepared(classificationSet),
66             mod);
67
68       try
69       {
70          if (isPrepared(classificationGet))
71          {
72             addFieldReadInfoFieldToGeneratedAdvisor(field, index);
73             // prepareForWrapping
74
wrapper.prepareForWrapping(field, GET_INDEX);
75          }
76
77          if (isPrepared(classificationSet))
78          {
79             addFieldWriteInfoFieldToGeneratedAdvisor(field, index);
80             // prepareForWrapping
81
wrapper.prepareForWrapping(field, SET_INDEX);
82          }
83       }
84       catch (Exception JavaDoc e)
85       {
86          throw new CannotCompileException(e);
87       }
88
89       // wrap
90
if (wrappedGet)
91       {
92          wrapper.wrap(field, GET_INDEX);
93          if (classificationGet.equals(JoinpointClassification.DYNAMICALY_WRAPPED))
94          {
95             instrumentor.dynamicTransformationObserver.fieldReadDynamicalyWrapped(field);
96          }
97       }
98       if (wrappedSet)
99       {
100          wrapper.wrap(field, SET_INDEX);
101          if (classificationSet.equals(JoinpointClassification.DYNAMICALY_WRAPPED))
102          {
103             instrumentor.dynamicTransformationObserver.fieldWriteDynamicalyWrapped(field);
104          }
105       }
106
107       // executeWrapping
108
replaceFieldAccessInternally(clazz, field, wrappedGet, wrappedSet, index);
109       buildWrappers(clazz, field, wrappedGet, wrappedSet, index);
110    }
111
112    protected String JavaDoc addFieldReadInfoFieldToGeneratedAdvisor(CtField field, int index)throws NotFoundException, CannotCompileException
113    {
114       CtClass genadvisor = getGenadvisor();
115       String JavaDoc finame = addFieldReadInfoFieldWithAccessors(
116             Modifier.PROTECTED,
117             genadvisor,
118             field);
119
120       addReadJoinPoint(field, finame, index);
121
122       long wrapperHash = JavassistMethodHashing.methodHash(
123             field.getDeclaringClass().getDeclaredMethod(fieldRead(field.getName())));
124       ((GeneratedAdvisorInstrumentor)instrumentor).initialiseFieldReadInfoField(finame, index, field.getName(), wrapperHash);
125       return finame;
126    }
127
128    protected boolean addInfoAsWeakReference()
129    {
130       return false;
131    }
132
133    private void addReadJoinPoint(CtField field, String JavaDoc finame, int index) throws CannotCompileException, NotFoundException
134    {
135       CtClass joinpoint = createReadJoinPointClass(field, finame, index);
136       CtClass genadvisor = ((GeneratedAdvisorInstrumentor)instrumentor).getGenadvisor();
137       CtField jpfield = new CtField(
138             joinpoint,
139             FieldJoinPointGenerator.getInfoFieldName(field.getName(), true),
140             genadvisor);
141       jpfield.setModifiers(Modifier.PROTECTED);
142       genadvisor.addField(jpfield);
143    }
144
145    private CtClass createReadJoinPointClass(CtField field, String JavaDoc finame, int index) throws CannotCompileException, NotFoundException
146    {
147       return FieldJoinPointGenerator.createReadJoinpointBaseClass((GeneratedAdvisorInstrumentor)instrumentor,
148             field.getDeclaringClass(),
149             field,
150             finame,
151             index);
152    }
153
154    protected String JavaDoc addFieldWriteInfoFieldToGeneratedAdvisor(CtField field, int index)throws NotFoundException, CannotCompileException
155    {
156       CtClass genadvisor = getGenadvisor();
157
158       String JavaDoc finame = addFieldWriteInfoField(
159             Modifier.PROTECTED,
160             genadvisor,
161             field);
162
163       addWriteJoinPoint(field, finame, index);
164
165       long wrapperHash = JavassistMethodHashing.methodHash(
166             field.getDeclaringClass().getDeclaredMethod(fieldWrite(field.getName())));
167       ((GeneratedAdvisorInstrumentor)instrumentor).initialiseFieldWriteInfoField(finame, index, field.getName(), wrapperHash);
168
169       return finame;
170    }
171
172    private void addWriteJoinPoint(CtField field, String JavaDoc finame, int index) throws CannotCompileException, NotFoundException
173    {
174       CtClass joinpoint = createWriteJoinPointClass(field, finame, index);
175       CtClass genadvisor = ((GeneratedAdvisorInstrumentor)instrumentor).getGenadvisor();
176       CtField jpfield = new CtField(
177             joinpoint,
178             FieldJoinPointGenerator.getInfoFieldName(field.getName(), false),
179             genadvisor);
180       jpfield.setModifiers(Modifier.PROTECTED);
181       genadvisor.addField(jpfield);
182    }
183
184    private CtClass createWriteJoinPointClass(CtField field, String JavaDoc finame, int index) throws CannotCompileException, NotFoundException
185    {
186       return FieldJoinPointGenerator.createWriteJoinpointBaseClass((GeneratedAdvisorInstrumentor)instrumentor,
187             field.getDeclaringClass(),
188             field,
189             finame,
190             index);
191    }
192
193    protected void buildWrapperPlaceHolders(CtClass clazz, CtField field, boolean doGet, boolean doSet, int mod)
194    throws NotFoundException, CannotCompileException
195    {
196       super.buildWrapperPlaceHolders(clazz, field, doGet, doSet, getStaticModifiers(field));
197
198       CtClass genadvisor = getGenadvisor();
199       if (doGet)
200       {
201          CtMethod rmethod = super.buildReadWrapperPlaceHolder(
202                genadvisor,
203                field,
204                advisorFieldRead(genadvisor, field.getName()),
205                Modifier.PROTECTED);
206
207       }
208       if (doSet)
209       {
210          CtMethod wmethod = super.buildWriteWrapperPlaceHolder(
211                genadvisor,
212                field,
213                advisorFieldWrite(genadvisor, field.getName()),
214                Modifier.PROTECTED);
215
216       }
217    }
218
219    public static String JavaDoc advisorFieldRead(CtClass genadvisor, String JavaDoc fieldName)
220    {
221       return genadvisor.getSimpleName() + "$" + fieldRead(fieldName);
222    }
223
224    public static String JavaDoc advisorFieldWrite(CtClass genadvisor, String JavaDoc fieldName)
225    {
226       return genadvisor.getSimpleName() + "$" + fieldWrite(fieldName);
227    }
228
229    protected String JavaDoc getWrapperBody(CtClass clazz, CtField field, boolean get, int fieldIndex) throws NotFoundException, CannotCompileException
230    {
231       if (get)
232       {
233          return getMainReadWrapperBody(clazz, field, fieldIndex);
234       }
235       return getMainWriteWrapperBody(clazz, field, fieldIndex);
236    }
237
238    protected void replaceFieldAccessInternally(CtClass clazz, CtField field, boolean doGet, boolean doSet, int index) throws CannotCompileException
239    {
240       GeneratedAdvisorFieldAccessExprEditor expr = new GeneratedAdvisorFieldAccessExprEditor(clazz, field, doGet, doSet, index);
241       clazz.instrument(expr);
242    }
243
244    private CtClass getGenadvisor()
245    {
246       return ((GeneratedAdvisorInstrumentor)instrumentor).getGenadvisor();
247    }
248
249    private CtClass getGenInstanceAdvisor()
250    {
251       return ((GeneratedAdvisorInstrumentor)instrumentor).getGenInstanceadvisor();
252    }
253
254    private String JavaDoc getAdvisorReadWrapperBody(CtClass clazz, CtField field, int index)
255    throws NotFoundException, CannotCompileException
256    {
257       boolean isStatic = Modifier.isStatic(field.getModifiers());
258       String JavaDoc code = null;
259       String JavaDoc infoName = FieldJoinPointGenerator.getInfoFieldName(field.getName(), true);
260       String JavaDoc generatorName = FieldJoinPointGenerator.getJoinPointGeneratorFieldName(field.getName(), true);
261       if (isStatic)
262       {
263          code =
264             "{" +
265             " if (" + infoName + " == null && " + generatorName + " != null)" +
266             " {" +
267             " " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();" +
268             " }" +
269             " if (" + infoName + " == null)" +
270             " { " +
271             " return " + clazz.getName() + "." + field.getName() + ";" +
272             " }" +
273             " else" +
274             " {" +
275             " " + MethodExecutionTransformer.getAopReturnStr(false) + infoName + "." + JoinPointGenerator.INVOKE_JOINPOINT + "();" +
276             " }" +
277             "}";
278       }
279       else
280       {
281          code =
282             "{" +
283             " if (" + infoName + " == null && " + generatorName + " != null)" +
284             " {" +
285             " " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();" +
286             " }" +
287             " if (" + infoName + " == null)" +
288             " { " +
289             " return ((" + clazz.getName() + ")$1)." + field.getName() + ";" +
290             " }" +
291             " else" +
292             " {" +
293             " " + MethodExecutionTransformer.getAopReturnStr(false) + infoName + "." + JoinPointGenerator.INVOKE_JOINPOINT + "((" + clazz.getName() + ")$1);" +
294             " }" +
295             "}";
296       }
297
298       return code;
299    }
300
301    private String JavaDoc getAdvisorWriteWrapperBody(CtClass clazz, CtField field, int index)
302    throws NotFoundException, CannotCompileException
303    {
304       boolean isStatic = Modifier.isStatic(field.getModifiers());
305       String JavaDoc code = null;
306       String JavaDoc infoName = FieldJoinPointGenerator.getInfoFieldName(field.getName(), false);
307       String JavaDoc generatorName = FieldJoinPointGenerator.getJoinPointGeneratorFieldName(field.getName(), false);
308       if (isStatic)
309       {
310          code =
311             "{" +
312             " if (" + infoName + " == null && " + generatorName + " != null)" +
313             " {" +
314             " " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();" +
315             " }" +
316             " if (" + infoName + " == null)" +
317             " { " +
318             " " + clazz.getName() + "." + field.getName() + " = $2;" +
319             " }" +
320             " else" +
321             " {" +
322             " " + infoName + "." + JoinPointGenerator.INVOKE_JOINPOINT + "($2);" +
323             " }" +
324             "}";
325       }
326       else
327       {
328          code =
329             "{" +
330             " if (" + infoName + " == null && " + generatorName + " != null)" +
331             " {" +
332             " " + generatorName + "." + JoinPointGenerator.GENERATE_JOINPOINT_CLASS + "();" +
333             " }" +
334             " if (" + infoName + " == null)" +
335             " { " +
336             " ((" + clazz.getName() + ")$1)." + field.getName() + " = $2;" +
337             " }" +
338             " else" +
339             " {" +
340             " " + MethodExecutionTransformer.getAopReturnStr(false) + infoName + "." + JoinPointGenerator.INVOKE_JOINPOINT + "((" + clazz.getName() + ")$1, $2);" +
341             " }" +
342             "}";
343       }
344
345       return code;
346    }
347
348
349    private String JavaDoc getMainReadWrapperBody(CtClass clazz, CtField field, int index)
350    throws NotFoundException, CannotCompileException
351    {
352       //Just delegate to method in advisor
353
boolean isStatic = Modifier.isStatic(field.getModifiers());
354
355       String JavaDoc code;
356       String JavaDoc advisor = isStatic ?
357             "((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(clazz) + ")" + Instrumentor.HELPER_FIELD_NAME + ")" :
358                "((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(clazz) + ")((" + clazz.getName() + ")$1)." + GeneratedAdvisorInstrumentor.GET_CURRENT_ADVISOR + ")";
359
360       return "return " + advisor + "." + advisorFieldRead(getGenadvisor(), field.getName()) + "($$);";
361    }
362
363    private String JavaDoc getMainWriteWrapperBody(CtClass clazz, CtField field, int index)
364       throws NotFoundException, CannotCompileException
365    {
366       //Just delegate to method in advisor
367
boolean isStatic = Modifier.isStatic(field.getModifiers());
368
369       String JavaDoc code;
370       String JavaDoc advisor = isStatic ?
371             "((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(clazz) + ")" + Instrumentor.HELPER_FIELD_NAME + ")" :
372             "((" + GeneratedAdvisorInstrumentor.getAdvisorFQN(clazz) + ")((" + clazz.getName() + ")$1)." + GeneratedAdvisorInstrumentor.GET_CURRENT_ADVISOR + ")";
373
374       return advisor + "." + advisorFieldWrite(getGenadvisor(), field.getName()) + "($$);";
375    }
376
377
378
379    private void buildWrappers(CtClass clazz, CtField field, boolean doGet, boolean doSet, int index) throws NotFoundException, CannotCompileException
380    {
381       if (doGet)
382       {
383          //Set wrapper code in advisor
384
String JavaDoc code = getAdvisorReadWrapperBody(clazz, field, index);
385          CtMethod method = getGenadvisor().getDeclaredMethod(advisorFieldRead(getGenadvisor(), field.getName()));
386          try
387          {
388             method.setBody(code);
389          }
390          catch (CannotCompileException e)
391          {
392             throw new RuntimeException JavaDoc("Field " + field + " code: " + code + " in Method " + method, e);
393          }
394
395          //Make main class wrapper delegate to advisor wrapper
396
String JavaDoc mcode = getMainReadWrapperBody(clazz, field, index);
397          CtMethod mmethod = clazz.getDeclaredMethod(fieldRead(field.getName()));
398
399          mmethod.setBody(mcode);
400       }
401       if (doSet)
402       {
403          //Set wrapper code in advisor
404
String JavaDoc code = getAdvisorWriteWrapperBody(clazz, field, index);
405          CtMethod method = getGenadvisor().getDeclaredMethod(advisorFieldWrite(getGenadvisor(), field.getName()));
406          try
407          {
408             method.setBody(code);
409          }
410          catch (CannotCompileException e)
411          {
412             throw new RuntimeException JavaDoc("Field " + field + " code: " + code + " in Method " + method, e);
413          }
414
415          //Make main class wrapper delegate to advisor wrapper
416
String JavaDoc mcode = getMainWriteWrapperBody(clazz, field, index);
417          CtMethod mmethod = clazz.getDeclaredMethod(fieldWrite(field.getName()));
418
419          mmethod.setBody(mcode);
420       }
421    }
422
423    private ArrayList JavaDoc pendingFieldWriteInfos = new ArrayList JavaDoc();
424    private ArrayList JavaDoc pendingFieldReadInfos = new ArrayList JavaDoc();
425
426    private class PendingFieldInfo
427    {
428       CtField field;
429       int index;
430       public PendingFieldInfo(CtField field, int index)
431       {
432          this.field = field;
433          this.index = index;
434       }
435       public CtField getField()
436       {
437          return field;
438       }
439       public int getIndex()
440       {
441          return index;
442       }
443    }
444
445    protected class GeneratedAdvisorFieldAccessExprEditor extends FieldAccessExprEditor
446    {
447       public GeneratedAdvisorFieldAccessExprEditor(CtClass clazz, CtField field, boolean doGet, boolean doSet, int index)
448       {
449          super(clazz, field, doGet, doSet, index);
450       }
451
452       protected void replaceRead(FieldAccess fieldAccess) throws CannotCompileException
453       {
454          if (fieldAccess.isStatic())
455          {
456             String JavaDoc code =
457                     " { " +
458                     " $_ = ($r)" + fieldRead(field.getName()) + "(null);" +
459                     " } " +
460                      "";
461             fieldAccess.replace(code);
462          }
463          else
464          {
465             String JavaDoc code =
466                     " { " +
467                     " $_ = ($r)" + fieldRead(field.getName()) + "($0);" +
468                     " } " +
469                     "";
470             fieldAccess.replace(code);
471          }
472       }
473
474       protected void replaceWrite(FieldAccess fieldAccess) throws CannotCompileException
475       {
476          String JavaDoc fieldWrite = fieldWrite(field.getName());
477          if (fieldAccess.isStatic())
478          {
479             String JavaDoc code =
480                     " { " +
481                     " " + fieldWrite + "(null, $1);" +
482                     " } " +
483                     "";
484             fieldAccess.replace(code);
485          }
486          else
487          {
488             String JavaDoc code =
489                     " { " +
490                     " " + fieldWrite + "($0, $1);" +
491                     " } " +
492                     "";
493             fieldAccess.replace(code);
494          }
495       }
496    }
497
498 }
499
Popular Tags