KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > cflow > CflowCompiler


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.cflow;
9
10 import org.objectweb.asm.Constants;
11 import org.objectweb.asm.ClassWriter;
12 import org.objectweb.asm.CodeVisitor;
13 import org.objectweb.asm.Label;
14 import org.codehaus.aspectwerkz.transform.TransformationConstants;
15 import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
16 import org.codehaus.aspectwerkz.transform.inlining.compiler.AbstractJoinPointCompiler;
17
18 /**
19  * Compiler for the JIT cflow Aspect
20  *
21  * @author <a HREF="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
22  */

23 public class CflowCompiler implements Constants, TransformationConstants {
24
25     public final static String JavaDoc JIT_CFLOW_CLASS = "org/codehaus/aspectwerkz/cflow/Cflow_";
26     private final static String JavaDoc ABSTRACT_CFLOW_CLASS = "org/codehaus/aspectwerkz/cflow/AbstractCflowSystemAspect";
27     private final static String JavaDoc INSTANCE_CFLOW_FIELD_NAME = "INSTANCE";
28     private final static String JavaDoc[] EMPTY_STRING_ARRAY = new String JavaDoc[0];
29     public static final String JavaDoc IN_CFLOW_METOD_NAME = "inCflow";
30     public static final String JavaDoc IN_CFLOW_METOD_SIGNATURE = "()Z";
31     public static final String JavaDoc CFLOW_ASPECTOF_METHOD_NAME = "aspectOf";
32
33     /**
34      * Checks if a class name (ASM style) is a cflow name
35      *
36      * @param className
37      * @return
38      */

39     public static boolean isCflowClass(String JavaDoc className) {
40         return className.indexOf(JIT_CFLOW_CLASS) >= 0;
41     }
42
43     /**
44      * The jit cflow aspect class name (with /)
45      */

46     private final String JavaDoc m_className;
47
48     /**
49      * The jit cflow aspect class name (with /)
50      */

51     private final String JavaDoc m_classSignature;
52
53     private ClassWriter m_cw;
54
55     /**
56      * private ctor
57      * @param cflowId
58      */

59     private CflowCompiler(int cflowId) {
60         m_className = getCflowAspectClassName(cflowId);
61         m_classSignature = "L"+m_className+";";
62     }
63
64     /**
65      * compile the jit cflow aspect
66      * @return bytecode for the concrete jit cflow aspect
67      */

68     private byte[] compile() {
69         m_cw = AsmHelper.newClassWriter(true);
70
71         // class extends AbstractCflowsystemAspect
72
m_cw.visit(
73                 AsmHelper.JAVA_VERSION,
74                 ACC_PUBLIC + ACC_SUPER + ACC_SYNTHETIC,
75                 m_className,
76                 ABSTRACT_CFLOW_CLASS,
77                 EMPTY_STRING_ARRAY,
78                 null
79         );
80
81         // static INSTANCE field
82
m_cw.visitField(
83                 ACC_PRIVATE + ACC_STATIC,
84                 INSTANCE_CFLOW_FIELD_NAME,
85                 m_classSignature,
86                 null,
87                 null
88         );
89
90         // private ctor
91
CodeVisitor ctor = m_cw.visitMethod(
92                 ACC_PRIVATE,
93                 INIT_METHOD_NAME,
94                 NO_PARAM_RETURN_VOID_SIGNATURE,
95                 EMPTY_STRING_ARRAY,
96                 null
97         );
98         // invoke the constructor of abstract
99
ctor.visitVarInsn(ALOAD, 0);
100         ctor.visitMethodInsn(INVOKESPECIAL, ABSTRACT_CFLOW_CLASS, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
101         ctor.visitInsn(RETURN);
102         ctor.visitMaxs(0, 0);
103
104         // static isInCflow() delegators
105
CodeVisitor isInCflow = m_cw.visitMethod(
106                 ACC_PUBLIC + ACC_STATIC,
107                 IS_IN_CFLOW_METOD_NAME,
108                 IS_IN_CFLOW_METOD_SIGNATURE,
109                 EMPTY_STRING_ARRAY,
110                 null
111         );
112         isInCflow.visitFieldInsn(GETSTATIC, m_className, INSTANCE_CFLOW_FIELD_NAME, m_classSignature);
113         Label isNull = new Label();
114         isInCflow.visitJumpInsn(IFNULL, isNull);
115         isInCflow.visitFieldInsn(GETSTATIC, m_className, INSTANCE_CFLOW_FIELD_NAME, m_classSignature);
116         isInCflow.visitMethodInsn(INVOKEVIRTUAL, ABSTRACT_CFLOW_CLASS, IN_CFLOW_METOD_NAME, IN_CFLOW_METOD_SIGNATURE);
117         isInCflow.visitInsn(IRETURN);
118         isInCflow.visitLabel(isNull);
119         isInCflow.visitInsn(ICONST_0);
120         isInCflow.visitInsn(IRETURN);
121         isInCflow.visitMaxs(0, 0);
122
123         // static aspectOf()
124
CodeVisitor aspectOf = m_cw.visitMethod(
125                 ACC_PUBLIC + ACC_STATIC,
126                 CFLOW_ASPECTOF_METHOD_NAME,
127                 "()"+m_classSignature,
128                 EMPTY_STRING_ARRAY,
129                 null
130         );
131         aspectOf.visitFieldInsn(GETSTATIC, m_className, INSTANCE_CFLOW_FIELD_NAME, m_classSignature);
132         Label isNotNull = new Label();
133         aspectOf.visitJumpInsn(IFNONNULL, isNotNull);
134         aspectOf.visitTypeInsn(NEW, m_className);
135         aspectOf.visitInsn(DUP);
136         aspectOf.visitMethodInsn(INVOKESPECIAL, m_className, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
137         aspectOf.visitFieldInsn(PUTSTATIC, m_className, INSTANCE_CFLOW_FIELD_NAME, m_classSignature);
138         aspectOf.visitLabel(isNotNull);
139         aspectOf.visitFieldInsn(GETSTATIC, m_className, INSTANCE_CFLOW_FIELD_NAME, m_classSignature);
140         aspectOf.visitInsn(ARETURN);
141         aspectOf.visitMaxs(0, 0);
142
143         m_cw.visitEnd();
144
145         return m_cw.toByteArray();
146     }
147
148     /**
149      * The naming strategy for jit cflow aspect
150      * @param cflowID
151      * @return org.codehaus.aspectwerkz.cflow.Cflow_cflowID
152      */

153     public static String JavaDoc getCflowAspectClassName(int cflowID) {
154         return JIT_CFLOW_CLASS + cflowID;
155     }
156
157     /**
158      * If necessary, compile a jit cflow aspect and attach it to the given classloader
159      *
160      * @param loader
161      * @param cflowID
162      * @return
163      */

164     public static Class JavaDoc compileCflowAspectAndAttachToClassLoader(ClassLoader JavaDoc loader, int cflowID) {
165         //TODO we need a Class.forName check first to avoid unecessary compilation
166
// else it will fail in defineClass and fallback on Class.forName ie uneeded compilation
167
// -> price to pay between compilation + exception in the worse case vs Class.forName each time
168
CompiledCflowAspect cflowAspect = compileCflowAspect(cflowID);
169
170         if (AbstractJoinPointCompiler.DUMP_JIT_CLASSES) {
171             try {
172                 AsmHelper.dumpClass("_dump", getCflowAspectClassName(cflowID), cflowAspect.bytecode);
173             } catch (Throwable JavaDoc t) {;}
174         }
175         
176         Class JavaDoc cflowAspectClass = AsmHelper.defineClass(
177                 loader,
178                 cflowAspect.bytecode,
179                 getCflowAspectClassName(cflowID)
180         );
181         return cflowAspectClass;
182     }
183
184     /**
185      * Compile a jit cflow aspect
186      *
187      * @param cflowID
188      * @return
189      */

190     public static CompiledCflowAspect compileCflowAspect(int cflowID) {
191         CompiledCflowAspect cflowAspect = new CompiledCflowAspect();
192         CflowCompiler compiler = new CflowCompiler(cflowID);
193         cflowAspect.bytecode = compiler.compile();
194         cflowAspect.className = compiler.m_className;
195         return cflowAspect;
196     }
197
198     /**
199      * Information about a compiled Cflow Aspect
200      */

201     public static class CompiledCflowAspect {
202         public byte[] bytecode;
203         public String JavaDoc className;// ASM style
204

205         public boolean equals(Object JavaDoc o) {
206             if (this == o) return true;
207             if (!(o instanceof CompiledCflowAspect)) return false;
208
209             final CompiledCflowAspect compiledCflowAspect = (CompiledCflowAspect) o;
210
211             if (!className.equals(compiledCflowAspect.className)) return false;
212
213             return true;
214         }
215
216         public int hashCode() {
217             return className.hashCode();
218         }
219     }
220 }
221
Popular Tags