KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > aspectwerkz > aspect > container > AbstractAspectFactoryCompiler


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.aspect.container;
5
6 import com.tc.asm.ClassWriter;
7 import com.tc.asm.MethodVisitor;
8 import com.tc.asm.Opcodes;
9
10 import com.tc.aspectwerkz.reflect.impl.asm.AsmClassInfo;
11 import com.tc.aspectwerkz.reflect.ClassInfo;
12 import com.tc.aspectwerkz.reflect.ConstructorInfo;
13 import com.tc.aspectwerkz.transform.Properties;
14 import com.tc.aspectwerkz.transform.TransformationConstants;
15 import com.tc.aspectwerkz.transform.inlining.AsmHelper;
16 import com.tc.aspectwerkz.util.Strings;
17
18 import java.io.IOException JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.Map JavaDoc;
22
23 /**
24  * Create a factory class for different aspect life cycle models.
25  * <p/>
26  * Each model ends in instantiating the aspect thru "new XAspect()" if there is no aspect container, or thru
27  * keeping a reference to the container and delegating to it thru container.aspectOf(..).
28  * The container itself is created with a one per factory basis (thus controlled by QName) thru
29  * "new XContainer()" or "new XContainer(aspectClass, aopSystemClassLoader, String uuid, String aspectQName, Map aspectParam)"
30  * <p/>
31  * Each model has the aspectOf(..) method, and the "hasAspect(..)" method.
32  * <p/>
33  * PerObject has a bind(object) method suitable for perTarget / perThis, that delegates to a supposely implemented
34  * interface in the target object itself (to avoid a map)
35  * <p/>
36  * PerCflowX has a bind(thread) / unbind(thread) suitable for perCflow / perCflowBelow.
37  * <p/>
38  * TODO: none is synchronized. AspectJ does not synchronize neither...
39  *
40  * @author <a HREF="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
41  * @author Jonas Bon&#233;r
42  */

43 public abstract class AbstractAspectFactoryCompiler implements Opcodes, TransformationConstants {
44
45   final static Artifact[] EMPTY_ARTIFACT_ARRAY = new Artifact[0];
46
47   private final ClassLoader JavaDoc m_loader;
48
49   protected String JavaDoc m_aspectFactoryClassName;
50   protected String JavaDoc[] m_interfaces = null;
51   protected final String JavaDoc m_aspectQualifiedName;
52   protected final String JavaDoc m_aspectClassName;
53   protected final String JavaDoc m_aspectClassSignature;
54   protected final String JavaDoc m_aspectContainerClassName;
55   protected final boolean m_hasAspectContainer;
56
57   private final String JavaDoc m_uuid;
58   private boolean m_hasParameters;
59   private String JavaDoc m_rawParameters;
60   private Map JavaDoc m_parametersLazy;
61
62   protected ClassWriter m_cw;
63   protected MethodVisitor m_clinit;
64
65   public AbstractAspectFactoryCompiler(String JavaDoc uuid,
66                                        String JavaDoc aspectClassName,
67                                        String JavaDoc aspectQualifiedName,
68                                        String JavaDoc containerClassName,
69                                        String JavaDoc rawParameters,
70                                        ClassLoader JavaDoc loader) {
71     m_uuid = uuid;
72     m_aspectClassName = aspectClassName.replace('.', '/');
73     m_aspectClassSignature = 'L' + m_aspectClassName + ';';
74     m_aspectQualifiedName = aspectQualifiedName;
75     m_aspectFactoryClassName = AspectFactoryManager.getAspectFactoryClassName(
76             m_aspectClassName, m_aspectQualifiedName
77     );
78     if (containerClassName != null) {
79       m_aspectContainerClassName = containerClassName.replace('.', '/');
80       m_hasAspectContainer = true;
81     } else {
82       m_aspectContainerClassName = null;
83       m_hasAspectContainer = false;
84     }
85     if (rawParameters != null) {
86       m_rawParameters = rawParameters;
87       m_hasParameters = true;
88     } else {
89       m_rawParameters = null;
90       m_hasParameters = false;
91     }
92     m_loader = loader;
93   }
94
95   private Map JavaDoc getParameters() {
96     if (m_parametersLazy == null) {
97       Map JavaDoc map;
98       if (m_rawParameters != null) {
99         map = new HashMap JavaDoc();
100         String JavaDoc[] raw = Strings.splitString(m_rawParameters, DELIMITER);
101         for (int i = 0; i < raw.length; i++) {
102           if (i < raw.length) {
103             map.put(raw[i], raw[++i]);
104           }
105         }
106       } else {
107         map = new HashMap JavaDoc(0);
108       }
109       m_parametersLazy = map;
110     }
111     return m_parametersLazy;
112   }
113
114   public Artifact compile() {
115     m_cw = AsmHelper.newClassWriter(true);
116
117     m_cw.visit(
118             AsmHelper.JAVA_VERSION,
119             ACC_PUBLIC,
120             m_aspectFactoryClassName,
121             null,
122             OBJECT_CLASS_NAME,
123             m_interfaces
124     );
125
126     // create a CLASS field to host this factory class
127
m_cw.visitField(
128             ACC_STATIC + ACC_PRIVATE,
129             FACTORY_CLASS_FIELD_NAME,
130             CLASS_CLASS_SIGNATURE,
131             null,
132             null
133     );
134
135     // create a clinit method
136
m_clinit = m_cw.visitMethod(
137             ACC_STATIC,
138             CLINIT_METHOD_NAME,
139             CLINIT_METHOD_SIGNATURE,
140             null,
141             null
142     );
143
144     // init the CLASS field
145
m_clinit.visitLdcInsn(m_aspectFactoryClassName.replace('/', '.'));
146     m_clinit.visitMethodInsn(
147             INVOKESTATIC,
148             CLASS_CLASS,
149             FOR_NAME_METHOD_NAME,
150             FOR_NAME_METHOD_SIGNATURE
151     );
152     m_clinit.visitFieldInsn(
153             PUTSTATIC,
154             m_aspectFactoryClassName,
155             FACTORY_CLASS_FIELD_NAME,
156             CLASS_CLASS_SIGNATURE
157     );
158
159     if (m_hasParameters) {
160       createParametersFieldAndClinit();
161     }
162     if (m_hasAspectContainer) {
163       createAspectContainerFieldAndClinit();
164     }
165
166     createAspectOf();
167     createHasAspect();
168     createOtherArtifacts();
169
170     m_clinit.visitInsn(RETURN);
171     m_clinit.visitMaxs(0, 0);
172
173     Artifact artifact = new Artifact(m_aspectFactoryClassName, m_cw.toByteArray());
174
175     if (Properties.DUMP_JIT_FACTORIES) try {
176       AsmHelper.dumpClass(Properties.DUMP_DIR_FACTORIES, artifact.className, artifact.bytecode);
177     } catch (IOException JavaDoc e) {
178     }
179     return artifact;
180   }
181
182   protected abstract void createAspectOf();
183
184   protected abstract void createHasAspect();
185
186   protected abstract void createOtherArtifacts();
187
188   private void createParametersFieldAndClinit() {
189     m_cw.visitField(
190             ACC_PRIVATE + ACC_STATIC + ACC_FINAL,
191             FACTORY_PARAMS_FIELD_NAME,
192             MAP_CLASS_SIGNATURE,
193             null,
194             null
195     );
196
197     m_clinit.visitTypeInsn(NEW, HASH_MAP_CLASS_NAME);
198     m_clinit.visitInsn(DUP);
199     m_clinit.visitMethodInsn(INVOKESPECIAL, HASH_MAP_CLASS_NAME, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
200     for (Iterator JavaDoc iterator = getParameters().entrySet().iterator(); iterator.hasNext();) {
201       m_clinit.visitInsn(DUP);
202       Map.Entry JavaDoc entry = (Map.Entry JavaDoc) iterator.next();
203       m_clinit.visitLdcInsn(entry.getKey());
204       m_clinit.visitLdcInsn(entry.getValue());
205       m_clinit.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME, PUT_METHOD_NAME, PUT_METHOD_SIGNATURE);
206       m_clinit.visitInsn(POP);
207     }
208     m_clinit.visitFieldInsn(PUTSTATIC, m_aspectFactoryClassName, FACTORY_PARAMS_FIELD_NAME, MAP_CLASS_SIGNATURE);
209   }
210
211   private void createAspectContainerFieldAndClinit() {
212     m_cw.visitField(
213             ACC_PRIVATE + ACC_STATIC,
214             FACTORY_CONTAINER_FIELD_NAME,
215             ASPECT_CONTAINER_CLASS_SIGNATURE,
216             null,
217             null
218     );
219
220     //support 2 different ctor for AspectContainer impl.
221
ClassInfo containerClassInfo = AsmClassInfo.getClassInfo(
222             m_aspectContainerClassName,
223             m_loader
224     );
225     boolean hasConstructor = false;
226     for (int i = 0; i < containerClassInfo.getConstructors().length; i++) {
227       ConstructorInfo constructorInfo = containerClassInfo.getConstructors()[i];
228       if (ASPECT_CONTAINER_OPTIONAL_INIT_SIGNATURE.equals(constructorInfo.getSignature())) {
229         hasConstructor = true;
230         break;
231       }
232       //TODO: check for no-arg ctor to avoid verify error and report error
233
}
234     m_clinit.visitTypeInsn(NEW, m_aspectContainerClassName);
235     m_clinit.visitInsn(DUP);
236     if (hasConstructor) {
237       m_clinit.visitLdcInsn(m_aspectClassName.replace('/', '.'));
238       m_clinit.visitMethodInsn(INVOKESTATIC, CLASS_CLASS, FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
239       //Note have access to the CL that defines the aspect (can be child of aspect CL)
240
m_clinit.visitFieldInsn(
241               GETSTATIC, m_aspectFactoryClassName, FACTORY_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE
242       );
243       m_clinit.visitMethodInsn(
244               INVOKEVIRTUAL,
245               CLASS_CLASS,
246               GETCLASSLOADER_METHOD_NAME,
247               CLASS_CLASS_GETCLASSLOADER_METHOD_SIGNATURE
248       );
249       m_clinit.visitLdcInsn(m_uuid);
250       m_clinit.visitLdcInsn(m_aspectQualifiedName);
251       if (m_hasParameters) {
252         m_clinit.visitFieldInsn(
253                 GETSTATIC, m_aspectFactoryClassName, FACTORY_PARAMS_FIELD_NAME, MAP_CLASS_SIGNATURE
254         );
255       } else {
256         m_clinit.visitInsn(ACONST_NULL);
257       }
258       m_clinit.visitMethodInsn(
259               INVOKESPECIAL,
260               m_aspectContainerClassName,
261               INIT_METHOD_NAME,
262               ASPECT_CONTAINER_OPTIONAL_INIT_SIGNATURE
263       );
264     } else {
265       m_clinit.visitMethodInsn(
266               INVOKESPECIAL, m_aspectContainerClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE
267       );
268     }
269     m_clinit.visitFieldInsn(
270             PUTSTATIC, m_aspectFactoryClassName, FACTORY_CONTAINER_FIELD_NAME, ASPECT_CONTAINER_CLASS_SIGNATURE
271     );
272   }
273 }
274
Popular Tags