KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > transform > AspectWerkzPreProcessor


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;
9
10 import org.codehaus.aspectwerkz.util.Util;
11 import org.codehaus.aspectwerkz.expression.SubtypePatternType;
12 import org.codehaus.aspectwerkz.expression.regexp.Pattern;
13 import org.codehaus.aspectwerkz.expression.regexp.TypePattern;
14 import org.codehaus.aspectwerkz.hook.ClassPreProcessor;
15 import org.codehaus.aspectwerkz.transform.inlining.InliningWeavingStrategy;
16 import org.codehaus.aspectwerkz.transform.inlining.EmittedJoinPoint;
17 import org.codehaus.aspectwerkz.transform.inlining.ContextImpl;
18
19 import java.util.Collection JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.Map JavaDoc;
22
23 /**
24  * AspectWerkzPreProcessor is the entry point of the AspectWerkz layer 2. <p/>It implements the ClassPreProcessor
25  * interface defined in layer 1. <p/>Available options are:
26  * <ul>
27  * <li><code>-Daspectwerkz.transform.verbose=yes</code> turns on verbose mode: print on stdout all non filtered class
28  * names and which transformation are applied</li>
29  * <li><code>-Daspectwerkz.transform.dump=org.myapp.*</code> dumps transformed class matching pattern <i>org.myapp.*
30  * </i>(even unmodified ones) in <i>./_dump </i> directory (relative to where applications starts). The syntax
31  * <code>-Daspectwerkz.transform.dump=*</code> matchs all classes. The pattern language is the same as pointcut
32  * pattern language.</li>
33  * <li>else <code>-Daspectwerkz.transform.dump=org.myapp.*,before</code> dumps class before and after the
34  * transformation whose name starts with <i>org.myapp. </i>(even unmodified ones) in <i>./_dump/before </i> and
35  * <i>./_dump/after </i> directories (relative to where application starts)</li>
36  * <li><code>-Daspectwerkz.transform.filter=no</code> (or false) disables filtering of
37  * <code>org.codehaus.aspectwerkz</code> and related classes (trove, dom4j etc.). This should only be used in offline
38  * mode where weaving of those classes is needed. Setting this option in online mode will lead to
39  * <code>ClassCircularityError</code>.</li>
40  * </ul>
41  *
42  * @author <a HREF="mailto:alex@gnilux.com">Alexandre Vasseur </a>
43  * @author <a HREF="mailto:jboner@codehaus.org">Jonas BonŽr </a>
44  */

45 public class AspectWerkzPreProcessor implements ClassPreProcessor {
46
47     private final static String JavaDoc AW_TRANSFORM_FILTER = "aspectwerkz.transform.filter";
48
49     private final static String JavaDoc AW_TRANSFORM_VERBOSE = "aspectwerkz.transform.verbose";
50
51     private final static String JavaDoc AW_TRANSFORM_DETAILS = "aspectwerkz.transform.details";
52
53     private final static String JavaDoc AW_TRANSFORM_GENJP = "aspectwerkz.transform.genjp";
54
55     private final static String JavaDoc AW_TRANSFORM_DUMP = "aspectwerkz.transform.dump";
56
57     private final static TypePattern DUMP_PATTERN;
58
59     private final static boolean NOFILTER; // TODO: not used, remove?
60

61     private final static boolean DUMP_BEFORE;
62
63     private final static boolean DUMP_AFTER;
64
65     public final static boolean VERBOSE;
66
67     public final static boolean DETAILS;
68
69     public final static boolean GENJP;
70
71     static {
72         // define the tracing and dump options
73
String JavaDoc verbose = System.getProperty(AW_TRANSFORM_VERBOSE, null);
74         VERBOSE = "yes".equalsIgnoreCase(verbose) || "true".equalsIgnoreCase(verbose);
75         String JavaDoc details = System.getProperty(AW_TRANSFORM_DETAILS, null);
76         DETAILS = "yes".equalsIgnoreCase(details) || "true".equalsIgnoreCase(details);
77         String JavaDoc genjp = System.getProperty(AW_TRANSFORM_GENJP, null);
78         GENJP = "yes".equalsIgnoreCase(genjp) || "true".equalsIgnoreCase(genjp);
79         String JavaDoc filter = System.getProperty(AW_TRANSFORM_FILTER, null);
80         NOFILTER = "no".equalsIgnoreCase(filter) || "false".equalsIgnoreCase(filter);
81         String JavaDoc dumpPattern = System.getProperty(AW_TRANSFORM_DUMP, null);
82         if (dumpPattern == null) {
83             DUMP_BEFORE = false;
84             DUMP_AFTER = false;
85             DUMP_PATTERN = null;
86         } else {
87             dumpPattern = dumpPattern.trim();
88             DUMP_AFTER = true;
89             DUMP_BEFORE = dumpPattern.indexOf(",before") > 0;
90             if (DUMP_BEFORE) {
91                 DUMP_PATTERN = Pattern.compileTypePattern(
92                         dumpPattern.substring(0, dumpPattern.indexOf(',')),
93                         SubtypePatternType.NOT_HIERARCHICAL
94                 );
95             } else {
96                 DUMP_PATTERN = Pattern.compileTypePattern(dumpPattern, SubtypePatternType.NOT_HIERARCHICAL);
97             }
98         }
99     }
100
101     /**
102      * Marks the pre-processor as initialized.
103      */

104     private boolean m_initialized = false;
105
106     /**
107      * Pre processor weaving strategy.
108      */

109     private WeavingStrategy m_weavingStrategy;
110
111     /**
112      * Initializes the transformer stack.
113      */

114     public void initialize() {
115         m_weavingStrategy = new InliningWeavingStrategy();
116         m_initialized = true;
117     }
118
119     /**
120      * Transform bytecode according to the transformer stack
121      * Adapted for embedded modes, that will filter out framework classes
122      * See preProcessWithOutput for a tool entry point.
123      *
124      * @param name class name
125      * @param bytecode bytecode to transform
126      * @param loader classloader loading the class
127      * @return modified (or not) bytecode
128      */

129     public byte[] preProcess(final String JavaDoc name, final byte[] bytecode, final ClassLoader JavaDoc loader) {
130         // filter out ExtClassLoader and BootClassLoader
131
if (!NOFILTER) {
132             if ((loader == null) || (loader.getParent() == null)) {
133                 return bytecode;
134             }
135         }
136         // needed for JRockit (as well as all in all TFs)
137
final String JavaDoc className = (name!=null)?name.replace('/', '.'):null;
138
139         // will filter null named classes
140
if (filter(className) || !m_initialized) {
141             return bytecode;
142         }
143         if (VERBOSE) {
144             log(Util.classLoaderToString(loader) + ':' + className + '[' + Thread.currentThread().getName() + ']');
145         }
146
147         try {
148             Context context = _preProcess(className, bytecode, loader);
149             return context.getCurrentBytecode();
150         } catch (Exception JavaDoc e) {
151             log("failed " + className);
152             e.printStackTrace();
153             return bytecode;
154         }
155     }
156
157     /**
158      * Weaving of the class
159      *
160      * @param className
161      * @param bytecode
162      * @param loader
163      * @return the weaving context, where getCurrentBytecode is the resulting bytecode
164      */

165     public Context _preProcess(final String JavaDoc className, final byte[] bytecode, final ClassLoader JavaDoc loader) {
166         final Context context = m_weavingStrategy.newContext(className, bytecode, loader);
167
168         // dump before (not compliant with multiple CL weaving same class differently, since based
169
// on class FQN className)
170
dumpBefore(className, context);
171
172         // do the transformation
173
m_weavingStrategy.transform(className, context);
174
175         // dump after as required
176
dumpAfter(className, context);
177
178         // return the transformed bytecode
179
return context;
180     }
181
182     /**
183      * Weaving without filtering any class and returning a rich object with emitted joinpoints
184      *
185      * @param name
186      * @param bytecode
187      * @param loader
188      * @return
189      */

190     public Output preProcessWithOutput(final String JavaDoc name, final byte[] bytecode, final ClassLoader JavaDoc loader) {
191         // needed for JRockit (as well as all in all TFs)
192
final String JavaDoc className = name.replace('/', '.');
193
194         // we do not filter anything except JP in this mode
195
if (name.endsWith((TransformationConstants.JOIN_POINT_CLASS_SUFFIX))) {
196             Output output = new Output();
197             output.bytecode = bytecode;
198             output.emittedJoinPoints = null;
199             return output;
200         }
201
202         Context context = _preProcess(className, bytecode, loader);
203         Output output = new Output();
204         output.bytecode = context.getCurrentBytecode();
205         output.emittedJoinPoints =
206         (EmittedJoinPoint[]) ((ContextImpl) context).getEmittedJoinPoints().toArray(new EmittedJoinPoint[0]);
207
208         // resolve line numbers
209
for (int i = 0; i < output.emittedJoinPoints.length; i++) {
210             EmittedJoinPoint emittedJoinPoint = output.emittedJoinPoints[i];
211             emittedJoinPoint.resolveLineNumber(context);
212         }
213         return output;
214     }
215
216     /**
217      * Logs a message.
218      *
219      * @param msg the message to log
220      */

221     public static void log(final String JavaDoc msg) {
222         if (VERBOSE) {
223             System.out.println(msg);
224         }
225     }
226
227     /**
228      * Excludes instrumentation for the class used during the instrumentation
229      *
230      * @param klass the AspectWerkz class
231      */

232     private static boolean filter(final String JavaDoc klass) {
233         return (klass == null)
234                || klass.endsWith(TransformationConstants.JOIN_POINT_CLASS_SUFFIX)
235                || klass.startsWith("org.codehaus.aspectwerkz.")
236                || klass.startsWith("org.objectweb.asm.")
237                || klass.startsWith("com.karneim.")
238                || klass.startsWith("com.bluecast.")
239                || klass.startsWith("gnu.trove.")
240                || klass.startsWith("org.dom4j.")
241                || klass.startsWith("org.xml.sax.")
242                || klass.startsWith("javax.xml.parsers.")
243                || klass.startsWith("sun.reflect.Generated")// issue on J2SE 5 reflection - AW-245
244
|| klass.startsWith("EDU.oswego.cs.dl.util.concurrent")
245                 ;
246     }
247
248     /**
249      * Dumps class before weaving.
250      *
251      * @param className
252      * @param context
253      */

254     public static void dumpBefore(final String JavaDoc className, final Context context) {
255         if (DUMP_BEFORE) {
256             if (DUMP_PATTERN.matches(className)) {
257                 context.dump("_dump/before/");
258             }
259         }
260     }
261
262     /**
263      * Dumps class after weaving.
264      *
265      * @param className
266      * @param context
267      */

268     public static void dumpAfter(final String JavaDoc className, final Context context) {
269         if (DUMP_AFTER) {
270             if (DUMP_PATTERN.matches(className)) {
271                 context.dump("_dump/" + (DUMP_BEFORE ? "after/" : ""));
272             }
273         }
274     }
275
276     /**
277      * Structure build when invoking tool weaving
278      */

279     public static class Output {
280         public byte[] bytecode;
281         public EmittedJoinPoint[] emittedJoinPoints;
282     }
283
284 }
Popular Tags