KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > aspectwerkz > transform > inlining > ProxyWeavingStrategy


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;
5
6 import java.util.HashSet JavaDoc;
7 import java.util.Iterator JavaDoc;
8 import java.util.Set JavaDoc;
9
10 import com.tc.asm.ClassReader;
11 import com.tc.asm.ClassVisitor;
12 import com.tc.asm.ClassWriter;
13
14 import com.tc.aspectwerkz.definition.SystemDefinition;
15 import com.tc.aspectwerkz.exception.WrappedRuntimeException;
16 import com.tc.aspectwerkz.reflect.impl.asm.AsmClassInfo;
17 import com.tc.aspectwerkz.reflect.ClassInfo;
18 import com.tc.aspectwerkz.transform.InstrumentationContext;
19 import com.tc.aspectwerkz.transform.WeavingStrategy;
20 import com.tc.aspectwerkz.transform.inlining.weaver.AddInterfaceVisitor;
21 import com.tc.aspectwerkz.transform.inlining.weaver.AddMixinMethodsVisitor;
22 import com.tc.aspectwerkz.transform.inlining.weaver.AddWrapperVisitor;
23 import com.tc.aspectwerkz.transform.inlining.weaver.JoinPointInitVisitor;
24 import com.tc.aspectwerkz.transform.inlining.weaver.MethodExecutionVisitor;
25 import com.tc.aspectwerkz.expression.ExpressionContext;
26 import com.tc.aspectwerkz.expression.PointcutType;
27
28 /**
29  * A weaving strategy implementing a weaving scheme based on statical compilation, and no reflection.
30  *
31  * @author <a HREF="mailto:jboner@codehaus.org">Jonas Bon&#233;r </a>
32  */

33 public class ProxyWeavingStrategy implements WeavingStrategy {
34
35   /**
36    * Performs the weaving of the target class.
37    *
38    * @param className
39    * @param context
40    */

41   public void transform(String JavaDoc className, final InstrumentationContext context) {
42     try {
43       final byte[] bytecode = context.getInitialBytecode();
44       final ClassLoader JavaDoc loader = context.getLoader();
45
46       ClassInfo classInfo = AsmClassInfo.getClassInfo(className, bytecode, loader);
47
48       final Set JavaDoc definitions = context.getDefinitions();
49       final ExpressionContext[] ctxs = new ExpressionContext[]{
50               new ExpressionContext(PointcutType.EXECUTION, classInfo, classInfo)
51       };
52
53       // has AW aspects?
54
final boolean isAdvisable = !classFilter(definitions, ctxs, classInfo);
55
56       if (!isAdvisable) {
57         context.setCurrentBytecode(context.getInitialBytecode());
58         return;
59       }
60
61       // prepare ctor call jp
62
final ClassReader crLookahead = new ClassReader(bytecode);
63
64       Set JavaDoc addedMethods = new HashSet JavaDoc();
65 // crLookahead.accept(new AlreadyAddedMethodAdapter(addedMethods), true);
66

67       // ------------------------------------------------
68
// -- Phase 1 -- type change (ITDs)
69
final ClassWriter writerPhase1 = AsmHelper.newClassWriter(true);
70       final ClassReader readerPhase1 = new ClassReader(bytecode);
71       ClassVisitor reversedChainPhase1 = writerPhase1;
72       reversedChainPhase1 = new AddMixinMethodsVisitor(reversedChainPhase1, classInfo, context, addedMethods);
73       reversedChainPhase1 = new AddInterfaceVisitor(reversedChainPhase1, classInfo, context);
74       readerPhase1.accept(reversedChainPhase1, null, false);
75       context.setCurrentBytecode(writerPhase1.toByteArray());
76
77       // ------------------------------------------------
78
// update the class info with new ITDs
79
classInfo = AsmClassInfo.newClassInfo(context.getCurrentBytecode(), loader);
80
81       // ------------------------------------------------
82
// -- Phase 2 -- advice
83
final ClassWriter writerPhase2 = AsmHelper.newClassWriter(true);
84       final ClassReader readerPhase2 = new ClassReader(context.getCurrentBytecode());
85       ClassVisitor reversedChainPhase2 = writerPhase2;
86 // reversedChainPhase2 = new InstanceLevelAspectVisitor(reversedChainPhase2, classInfo, context);
87
reversedChainPhase2 = new MethodExecutionVisitor(reversedChainPhase2, classInfo, context, addedMethods);
88 // reversedChainPhase2 = new LabelToLineNumberVisitor(reversedChainPhase2, context);
89
readerPhase2.accept(reversedChainPhase2, null, false);
90       context.setCurrentBytecode(writerPhase2.toByteArray());
91
92       // ------------------------------------------------
93
// -- AW Finalization -- JP init code and wrapper methods
94
if (context.isAdvised()) {
95         final ClassWriter writerPhase3 = AsmHelper.newClassWriter(true);
96         ClassReader readerPhase3 = new ClassReader(context.getCurrentBytecode());
97         ClassVisitor reversedChainPhase3 = writerPhase3;
98         reversedChainPhase3 = new AddWrapperVisitor(reversedChainPhase3, context, addedMethods);
99         reversedChainPhase3 = new JoinPointInitVisitor(reversedChainPhase3, context);
100         readerPhase3.accept(reversedChainPhase3, null, false);
101         context.setCurrentBytecode(writerPhase3.toByteArray());
102       }
103     } catch (Throwable JavaDoc t) {
104       t.printStackTrace();
105       throw new WrappedRuntimeException(t);
106     }
107   }
108
109   /**
110    * Filters out the classes that are not eligible for transformation.
111    *
112    * @param definitions the definitions
113    * @param ctxs an array with the contexts
114    * @param classInfo the class to filter
115    * @return boolean true if the class should be filtered out
116    */

117   private static boolean classFilter(final Set JavaDoc definitions, final ExpressionContext[] ctxs, final ClassInfo classInfo) {
118     if (classInfo.isInterface()) {
119       return true;
120     }
121     for (Iterator JavaDoc defs = definitions.iterator(); defs.hasNext();) {
122       if (classFilter((SystemDefinition) defs.next(), ctxs, classInfo)) {
123         continue;
124       } else {
125         return false;
126       }
127     }
128     return true;
129   }
130
131   /**
132    * Filters out the classes that are not eligible for transformation.
133    *
134    * @param definition the definition
135    * @param ctxs an array with the contexts
136    * @param classInfo the class to filter
137    * @return boolean true if the class should be filtered out
138    * @TODO: when a class had execution pointcut that were removed it must be unweaved, thus not filtered out How to
139    * handle that? cache lookup? or custom class level attribute ?
140    */

141   private static boolean classFilter(final SystemDefinition definition, final ExpressionContext[] ctxs,
142                                      final ClassInfo classInfo) {
143
144     if (classInfo.isInterface()) {
145       return true;
146     }
147     String JavaDoc className = classInfo.getName();
148     if (definition.inExcludePackage(className)) {
149       return true;
150     }
151     if (!definition.inIncludePackage(className)) {
152       return true;
153     }
154     if (definition.isAdvised(ctxs)) {
155       return false;
156     }
157     if (definition.hasMixin(ctxs)) {
158       return false;
159     }
160     if (definition.hasIntroducedInterface(ctxs)) {
161       return false;
162     }
163     if (definition.inPreparePackage(className)) {
164       return false;
165     }
166     return true;
167   }
168
169   private static boolean classFilterFor(final Set JavaDoc definitions, final ExpressionContext[] ctxs) {
170     for (Iterator JavaDoc defs = definitions.iterator(); defs.hasNext();) {
171       if (classFilterFor((SystemDefinition) defs.next(), ctxs)) {
172         continue;
173       } else {
174         return false;
175       }
176     }
177     return true;
178   }
179
180   private static boolean classFilterFor(final SystemDefinition definition, final ExpressionContext[] ctxs) {
181     if (definition.isAdvised(ctxs)) {
182       return false;
183     }
184     return true;
185   }
186
187   private static boolean hasPointcut(final Set JavaDoc definitions, final ExpressionContext ctx) {
188     for (Iterator JavaDoc defs = definitions.iterator(); defs.hasNext();) {
189       if (hasPointcut((SystemDefinition) defs.next(), ctx)) {
190         return true;
191       } else {
192         continue;
193       }
194     }
195     return false;
196   }
197
198   private static boolean hasPointcut(final SystemDefinition definition, final ExpressionContext ctx) {
199     if (definition.hasPointcut(ctx)) {
200       return true;
201     }
202     return false;
203   }
204 }
205     
Popular Tags