KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > speedo > generation > enhancer > ClassAccessorAdder


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

18 package org.objectweb.speedo.generation.enhancer;
19
20 import org.objectweb.asm.Attribute;
21 import org.objectweb.asm.ClassVisitor;
22 import org.objectweb.asm.CodeVisitor;
23 import org.objectweb.asm.Constants;
24 import org.objectweb.asm.Type;
25 import org.objectweb.speedo.generation.lib.NamingRules;
26 import org.objectweb.speedo.metadata.SpeedoClass;
27 import org.objectweb.speedo.metadata.SpeedoField;
28 import org.objectweb.speedo.metadata.SpeedoModifier;
29 import org.objectweb.util.monolog.api.BasicLevel;
30 import org.objectweb.util.monolog.api.Logger;
31
32 import java.util.Collection JavaDoc;
33 import java.util.Iterator JavaDoc;
34
35 /**
36  * Adds getter and setter methods to a class.
37  *
38  * Adapted from generateAccessors, genGetter and genSetter in EnhancerTool.
39  */

40 public class ClassAccessorAdder extends LoggedClassAdapter {
41
42     /**
43      * The Speedo meta information for the visited class.
44      */

45     private final SpeedoClass jdoClass;
46
47     /**
48      * A collection of SpeedoXMLDescriptor describing known persistent classes
49      */

50     private final Collection JavaDoc xmlDescriptors;
51
52     /**
53      * Creates a new {@link ClassAccessorAdder}.
54      *
55      * @param _cv the class visitor to be used to generate the modified class
56      * @param _jdoClass the Speedo meta information for the visited class.
57      */

58     public ClassAccessorAdder(final ClassVisitor _cv,
59                               final SpeedoClass _jdoClass,
60                               final Collection JavaDoc _xmlDescriptors,
61                               Logger _logger) {
62         super(_cv, _logger);
63         this.jdoClass = _jdoClass;
64         this.xmlDescriptors = _xmlDescriptors;
65     }
66
67     // IMPLEMENTATION OF THE ClassVisitor INTERFACE //
68
// ---------------------------------------------//
69

70     public void visit(final int version,
71                       final int access,
72                       final String JavaDoc name,
73                       final String JavaDoc superName,
74                       final String JavaDoc[] interfaces,
75                       final String JavaDoc sourceFile) {
76         cv.visit(version, access, name, superName, interfaces, sourceFile);
77
78         // Creates usable accessors for each jdo field
79
Iterator JavaDoc i = jdoClass.jdoField.values().iterator();
80         while (i.hasNext()) {
81             SpeedoField jdoField = (SpeedoField) i.next();
82             if (jdoField.name == null) {
83                 continue;
84             }
85             int acc = jdoField.access;
86             if (jdoField.persistenceModifier >= SpeedoModifier.transactional) {
87                 // fields that are persistent or transactional
88
if ((acc & Constants.ACC_STATIC) != 0) {
89                     throw new RuntimeException JavaDoc(
90                             "A static field cannot be defined as persistent");
91                 }
92                 genSetter(name, jdoField);
93                 if (jdoField.persistenceModifier == SpeedoModifier.persistent) {
94                     genGetter(name, jdoField);
95                 }
96             } else if ((acc &
97                     (Constants.ACC_TRANSIENT | Constants.ACC_FINAL)) != 0) {
98                 // transient and/or final field
99
genSetter(name, jdoField);
100                 genGetter(name, jdoField);
101             } else if (jdoField.persistenceModifier == SpeedoModifier.missing) {
102                 if (Util.isPersistentType(jdoField.desc, xmlDescriptors)) {
103                     // fields whose persistent-modifier isn't defined
104
genSetter(name, jdoField);
105                     genGetter(name, jdoField);
106                 }
107             }
108         }
109     }
110
111     public CodeVisitor visitMethod(final int access,
112                                    final String JavaDoc name,
113                                    final String JavaDoc desc,
114                                    final String JavaDoc[] exceptions,
115                                    final Attribute attrs) {
116         // optimization: do not create an empty code adapter for visited
117
// methods, as is done by default in ClassAdapter
118
return cv.visitMethod(access, name, desc, exceptions, attrs);
119     }
120
121     // OTHER METHODS //
122
// --------------//
123

124     /**
125      * Generates a getter method for the given field.
126      * public float jdoGetF1() {
127      * TotoField sa = (TotoField) this.jdoReadIntention(new long[]{O, ..., 0, x})
128      * return sa.f1
129      * }
130      * @param owner the internal name of the visited class
131      * @param jdoField the field for which the getter method must be generated
132      */

133     private void genGetter(final String JavaDoc owner, final SpeedoField jdoField) {
134         int flags = jdoField.access;
135         String JavaDoc gettername =
136                 NamingRules.getterName(jdoField.jdoClass, jdoField.name);
137         if (debug) {
138             logger.log(BasicLevel.DEBUG, "Generate the getter method '"
139                     + gettername + "' on the class '" + jdoField.jdoClass.name + "'");
140         }
141         String JavaDoc desc = jdoField.desc;
142         //generate method signature
143
CodeVisitor _cv = this.cv.visitMethod(flags, gettername, "()" + desc, null, null);
144
145         //load this for the readIntention call
146
_cv.visitVarInsn(Constants.ALOAD, 0);
147         
148         // define the long[] value such as new long[]{O, ..., 0, x}
149
int idx = (jdoField.number / 64);
150         int arraysize = idx + 1;
151         Util.visitIntConstant(_cv, arraysize);
152         _cv.visitIntInsn(NEWARRAY, 11);
153         for(int i=0; i<idx; i++) {
154             _cv.visitInsn(DUP);
155             Util.visitIntConstant(_cv, i);
156             Util.visitLongConstant(_cv, 0);
157             _cv.visitInsn(LASTORE);
158         }
159         _cv.visitInsn(DUP);
160         Util.visitIntConstant(_cv, idx);
161         Util.visitLongConstant(_cv, 1L << (jdoField.number % 64));
162         _cv.visitInsn(LASTORE);
163
164         //call the jdoReadIntention method
165
_cv.visitMethodInsn(
166                 Constants.INVOKEINTERFACE,
167                 "org/objectweb/speedo/mim/api/SpeedoProxy",
168                 "jdoReadIntention",
169                 "(Lorg/objectweb/speedo/mim/api/SpeedoAccessor;[J)V");
170         // generate code to return field from fields
171
String JavaDoc fieldsOwner = NamingRules.fieldsName(owner);
172         _cv.visitVarInsn(Constants.ALOAD, 1);
173         _cv.visitTypeInsn(Constants.CHECKCAST, fieldsOwner);
174         _cv.visitFieldInsn(Constants.GETFIELD, fieldsOwner, jdoField.name, desc);
175         Type returnType = Type.getType(desc);
176         _cv.visitInsn(returnType.getOpcode(Constants.IRETURN));
177         _cv.visitMaxs(0, 0);
178     }
179
180     /**
181      * Generates a setter method for the given field.
182      *
183      * @param owner the internal name of the visited class
184      * @param jdoField the field for which the setter method must be generated
185      */

186     private void genSetter(final String JavaDoc owner, final SpeedoField jdoField) {
187         int flags = jdoField.access;
188         String JavaDoc name =
189                 NamingRules.setterName(jdoField.jdoClass, jdoField.name);
190         if (debug) {
191             logger.log(BasicLevel.DEBUG, "Generate the setter method '"
192                     + name + "' on the class '" + jdoField.jdoClass.name + "'");
193         }
194         String JavaDoc desc = jdoField.desc;
195         CodeVisitor _cv =
196                 this.cv.visitMethod(flags, name, "(" + desc + ")V", null, null);
197         Type type = Type.getType(desc);
198         int params = type.getSize() + 1;
199         // generate code to call jdoWriteIntention
200
_cv.visitVarInsn(Constants.ALOAD, 0);
201
202         // define the long[] value such as new long[]{O, ..., 0, x}
203
int idx = (jdoField.number / 64);
204         int arraysize = idx + 1;
205         Util.visitIntConstant(_cv, arraysize);
206         _cv.visitIntInsn(NEWARRAY, T_LONG);
207         for(int i=0; i<idx; i++) {
208             _cv.visitInsn(DUP);
209             Util.visitIntConstant(_cv, i);
210             Util.visitLongConstant(_cv, 0);
211             _cv.visitInsn(LASTORE);
212         }
213         _cv.visitInsn(DUP);
214         Util.visitIntConstant(_cv, idx);
215         Util.visitLongConstant(_cv, 1L << (jdoField.number % 64));
216         _cv.visitInsn(LASTORE);
217
218         _cv.visitMethodInsn(
219                 Constants.INVOKEINTERFACE,
220                 "org/objectweb/speedo/mim/api/SpeedoProxy",
221                 "jdoWriteIntention",
222                 "[J)V");
223         // generate code to set field of state
224
String JavaDoc fieldsOwner = NamingRules.fieldsName(owner);
225         _cv.visitVarInsn(Constants.ALOAD, params);
226         _cv.visitTypeInsn(Constants.CHECKCAST, fieldsOwner);
227         _cv.visitVarInsn(type.getOpcode(Constants.ILOAD), 1);
228         _cv.visitFieldInsn(Constants.PUTFIELD, fieldsOwner, jdoField.name, desc);
229         _cv.visitInsn(Constants.RETURN);
230         _cv.visitMaxs(0, 0);
231     }
232 }
233
Popular Tags