KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > fractal > julia > asm > AttributeControllerClassGenerator


1 /***
2  * Julia: France Telecom's implementation of the Fractal API
3  * Copyright (C) 2001-2002 France Telecom R&D
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Contact: Eric.Bruneton@rd.francetelecom.com
20  *
21  * Author: Eric Bruneton
22  */

23
24 package org.objectweb.fractal.julia.asm;
25
26 import org.objectweb.fractal.api.control.AttributeController;
27
28 import org.objectweb.fractal.julia.control.attribute.CloneableAttributeController;
29 import org.objectweb.fractal.julia.loader.Tree;
30
31 import org.objectweb.asm.CodeVisitor;
32 import org.objectweb.asm.Label;
33 import org.objectweb.asm.Type;
34
35 import java.lang.reflect.Method JavaDoc;
36 import java.util.ArrayList JavaDoc;
37 import java.util.Arrays JavaDoc;
38 import java.util.HashSet JavaDoc;
39 import java.util.List JavaDoc;
40 import java.util.Set JavaDoc;
41
42 /**
43  * A class generator to generate {@link AttributeController}
44  * classes. This generator produces classes that implement a given set of
45  * attribute controller interfaces, i.e., interfaces with only <tt>getXXX</tt>
46  * and <tt>setXXX</tt> methods. The methods that are generated to implement
47  * these interfaces store and retreive values in private fields of the generated
48  * class, two for each method pair.
49  * <p>
50  * More precisely, the code generated for the IAttributes interface below is the
51  * following:
52  * <pre>
53  * public interface IAttributes extends AttributeController {
54  * int getI ();
55  * void setI (int i);
56  * }
57  *
58  * public class <i>XYZ</i>
59  * implements IAttributes, CloneableAttributeController, Generated
60  * {
61  *
62  * private int I;
63  * private boolean _I; // true if I has been set
64  *
65  * public int getI () {
66  * return I;
67  * }
68  *
69  * public void setI (int i) {
70  * I = i;
71  * _I = true;
72  * }
73  *
74  * public void cloneFcAttributes (AttributeController ac) {
75  * if (_I) {
76  * ((IAttributes)ac).setI(I);
77  * }
78  * }
79  *
80  * public String getFcGeneratorParameters () {
81  * return "(<i>...</i> ... (IAttributes))";
82  * }
83  * }
84  * </pre>
85  */

86
87 public class AttributeControllerClassGenerator extends AbstractClassGenerator {
88
89   /**
90    * The set of already generated fields.
91    */

92
93   private Set JavaDoc fields = new HashSet JavaDoc();
94
95   /**
96    * The {@link CodeVisitor} used to generate the {@link
97    * CloneableAttributeController#cloneFcAttributes cloneFcAttributes} method.
98    */

99
100   private CodeVisitor imv;
101
102   /**
103    * A label that designates the end of the {@link
104    * CloneableAttributeController#cloneFcAttributes cloneFcAttributes} method.
105    */

106
107   private Label endLabel;
108
109   /**
110    * Initializes this class generator with the given arguments. This method
111    * requires arguments of the form "(objectDescriptor (itfName1 ...
112    * itfNameN))", where itfName1 ... itfNameN are the names of the interfaces it
113    * must implement.
114    *
115    * @param args the descriptor of the class to be generated.
116    */

117
118   protected void parseArgs (final Tree args) {
119     superClass = "java/lang/Object";
120     interfaces = new ArrayList JavaDoc(Arrays.asList(args.getSubTree(1).getSubTrees()));
121     for (int i = 0; i < interfaces.size(); ++i) {
122       interfaces.set(i, interfaces.get(i).toString().replace('.', '/'));
123     }
124   }
125
126   /**
127    * Adds {@link CloneableAttributeController} to the list returned by the
128    * overriden method.
129    *
130    * @return the names of all the interfaces implemented by the generated class.
131    * @throws ClassGenerationException if a problem occurs.
132    */

133
134   protected List JavaDoc getImplementedInterfaces () throws ClassGenerationException {
135     List JavaDoc itfs = super.getImplementedInterfaces();
136     itfs.add(Type.getInternalName(CloneableAttributeController.class));
137     return itfs;
138   }
139
140   /**
141    * Calls the overriden method and generates the header of the {@link
142    * CloneableAttributeController#cloneFcAttributes cloneFcAttributes} method.
143    *
144    * @throws ClassGenerationException if a problem occurs.
145    */

146
147   protected void generateDefaultMethods () throws ClassGenerationException {
148     super.generateDefaultMethods();
149     imv = cw.visitMethod(
150       ACC_PUBLIC,
151       "cloneFcAttributes",
152       "(" + Type.getDescriptor(AttributeController.class) + ")V",
153       null,
154       null);
155   }
156
157   /**
158    * Calls the overriden method and finishes the generation of the {@link
159    * CloneableAttributeController#cloneFcAttributes cloneFcAttributes} method.
160    *
161    * @throws ClassGenerationException if a problem occurs.
162    */

163
164   protected void generateInterfaceMethods () throws ClassGenerationException {
165     super.generateInterfaceMethods();
166     if (endLabel != null) {
167       imv.visitLabel(endLabel);
168     }
169     imv.visitInsn(RETURN);
170     imv.visitMaxs(3, 3);
171   }
172
173   /**
174    * Generates a getter or setter method, and the corresponding fields if they
175    * are not already generated. If the given method is a setter method, this
176    * method also adds code corresponding to this attribute to the {@link
177    * CloneableAttributeController#cloneFcAttributes cloneFcAttributes} method.
178    *
179    * @param m the method to be generated.
180    * @throws ClassGenerationException if a problem occurs.
181    */

182
183   protected void generateMethod (final Method JavaDoc m) {
184     // generates the header of the method
185
String JavaDoc mName = m.getName();
186     String JavaDoc mDesc = Type.getMethodDescriptor(m);
187     CodeVisitor mv = cw.visitMethod(ACC_PUBLIC, mName, mDesc, null, null);
188     // computes the name and type of the corresponding field
189
String JavaDoc fieldName = mName.substring(3);
190     String JavaDoc iFieldName = "_" + fieldName;
191     Class JavaDoc fieldType;
192     if (mName.startsWith("get")) {
193       fieldType = m.getReturnType();
194     } else {
195       fieldType = m.getParameterTypes()[0];
196     }
197     String JavaDoc fieldDesc = Type.getDescriptor(fieldType);
198     if (!fields.contains(fieldName)) {
199       cw.visitField(ACC_PRIVATE, fieldName, fieldDesc, null, null);
200       cw.visitField(ACC_PRIVATE, iFieldName, "Z", null, null);
201       fields.add(fieldName);
202     }
203     if (mName.startsWith("get")) {
204       // generates the bytecode corresponding to 'return xxx;'
205
mv.visitVarInsn(ALOAD, 0);
206       mv.visitFieldInsn(GETFIELD, name, fieldName, fieldDesc);
207       mv.visitInsn(IRETURN + getOpcodeOffset(fieldType));
208     } else {
209       // generates the bytecode corresponding to 'this.xxx = xxx;'
210
mv.visitVarInsn(ALOAD, 0);
211       mv.visitVarInsn(ILOAD + getOpcodeOffset(fieldType), 1);
212       mv.visitFieldInsn(PUTFIELD, name, fieldName, fieldDesc);
213       // generates the bytecode corresponding to 'this._xxx = true;'
214
mv.visitVarInsn(ALOAD, 0);
215       mv.visitInsn(ICONST_1);
216       mv.visitFieldInsn(PUTFIELD, name, iFieldName, "Z");
217       mv.visitInsn(RETURN);
218       // adds code corresponding to 'xxx' in 'copyFcAttributes'
219
generateInitMethod(fieldName, fieldDesc, iFieldName, m);
220     }
221     mv.visitMaxs(Math.max(2, 1 + getSize(fieldType)), 1 + getSize(fieldType));
222   }
223
224   /**
225    * Adds the code corresponding to the given attribute to the {@link
226    * CloneableAttributeController#cloneFcAttributes cloneFcAttributes} method.
227    *
228    * @param fieldName the name of the 'xxx' field corresponding to the
229    * attribute.
230    * @param fieldDesc the descriptor of the 'xxx' field corresponding to an
231    * attribute.
232    * @param iFieldName the name of the '_xxx' field corresponding to the
233    * attribute.
234    * @param m the 'setXXX' setter method corresponding to the attribute.
235    */

236
237   private void generateInitMethod (
238     final String JavaDoc fieldName,
239     final String JavaDoc fieldDesc,
240     final String JavaDoc iFieldName,
241     final Method JavaDoc m)
242   {
243     if (endLabel != null) {
244       imv.visitLabel(endLabel);
245     }
246     endLabel = new Label();
247     String JavaDoc owner = Type.getInternalName(m.getDeclaringClass());
248     String JavaDoc desc = Type.getMethodDescriptor(m);
249     // generates the bytecode corresponding to 'if (_xxx) {'
250
imv.visitVarInsn(ALOAD, 0);
251     imv.visitFieldInsn(GETFIELD, name, iFieldName, "Z");
252     imv.visitJumpInsn(IFEQ, endLabel);
253     // generates the bytecode corresponding to '(XYZ)ac'
254
imv.visitVarInsn(ALOAD, 1);
255     imv.visitTypeInsn(CHECKCAST, owner);
256     // generates the bytecode corresponding to 'setXXX(xxx)'
257
imv.visitVarInsn(ALOAD, 0);
258     imv.visitFieldInsn(GETFIELD, name, fieldName, fieldDesc);
259     imv.visitMethodInsn(INVOKEINTERFACE, owner, m.getName(), desc);
260   }
261 }
262
Popular Tags