KickJava   Java API By Example, From Geeks To Geeks.

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


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.ClassVisitor;
21 import org.objectweb.asm.CodeVisitor;
22 import org.objectweb.asm.Constants;
23 import org.objectweb.asm.ClassReader;
24 import org.objectweb.asm.Attribute;
25 import org.objectweb.speedo.metadata.SpeedoClass;
26 import org.objectweb.speedo.metadata.SpeedoField;
27 import org.objectweb.speedo.metadata.SpeedoModifier;
28 import org.objectweb.speedo.generation.api.SpeedoCompilerParameter;
29 import org.objectweb.util.monolog.api.Logger;
30 import org.objectweb.util.monolog.api.BasicLevel;
31
32 import java.io.ObjectStreamClass JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.Collection JavaDoc;
36
37 /**
38  * Analyzes a class and updates the Speedo meta information accordingly.
39  *
40  * Adapted from storeClassInfo, verify and getField methods in EnhancerTool.
41  */

42 public class ClassInfoAnalyzer extends LoggedClass implements ClassVisitor {
43
44     /**
45      * The access enhancer, used to load the super class(es) of the class, if
46      * necessary.
47      */

48     final EnhancerComponent enhancer;
49
50     /**
51      * The Speedo meta information for the visited class.
52      */

53     final SpeedoClass jdoClass;
54
55     /**
56      * A collection of SpeedoXMLDescriptor describing known persistent classes
57      */

58     private final Collection JavaDoc xmlDescriptors;
59
60     /**
61      * Creates a new {@link ClassInfoAnalyzer}.
62      *
63      * @param enhancer the access enhancer, used to load the super class(es) of
64      * the class, if necessary.
65      * @param jdoClass the Speedo meta information for the visited class.
66      */

67     public ClassInfoAnalyzer(final EnhancerComponent enhancer,
68                              final SpeedoClass jdoClass,
69                              final Collection JavaDoc xmlDescriptors,
70                              Logger logger) {
71         super(logger);
72         this.enhancer = enhancer;
73         this.jdoClass = jdoClass;
74         this.xmlDescriptors = xmlDescriptors;
75     }
76
77     // IMPLEMENTATION OF THE ClassVisitor INTERFACE //
78
// ---------------------------------------------//
79

80     public void visit(final int version, final int access,
81                       final String JavaDoc name,
82                       final String JavaDoc superName,
83                       final String JavaDoc[] interfaces,
84                       final String JavaDoc sourceFile) {
85         // Stores class's signature
86
jdoClass.signature = Util.modifier(access & ~Constants.ACC_SUPER);
87         jdoClass.isAbstract = (access & Constants.ACC_ABSTRACT) != 0;
88
89         // Verifies inheritance
90
String JavaDoc superClass = jdoClass.superClassName;
91         if (superClass != null && !superClass.equals("") &&
92                 !superClass.equals(superName.replace('/', '.'))) {
93             throw new RuntimeException JavaDoc("Class " + name + " has actually " +
94                     superName + " as super class, whereas the .jdo file spcifies '"
95                     + jdoClass.superClassName + "'");
96         }
97         // Gets implemented interfaces
98
for (int i = 0; i < interfaces.length; i++) {
99             if (interfaces[i].equals("javax/jdo/InstanceCallbacks"))
100                 jdoClass.isInstanceCallbacks = true;
101             if (interfaces[i].equals("java/io/Serializable"))
102                 jdoClass.isSerializable = true;
103         }
104
105         // Looks for fields defined in the jdoClass in the Java class and
106
// assigns the corresponding modifier if missing
107
ClassFieldFinder finder = new ClassFieldFinder();
108         Iterator JavaDoc i = jdoClass.jdoField.values().iterator();
109         //System.out.println("field names: " + jdoClass.jdoField.keySet());
110
//System.out.println("fields [" + jdoClass.jdoField.values().size() + "]: " + jdoClass.jdoField.values());
111
while (i.hasNext()) {
112             SpeedoField current = (SpeedoField) i.next();
113             //System.out.println("treat field " + current.name);
114
if (!finder.fillInfo(current))
115                 throw new RuntimeException JavaDoc(
116                         "Persistent Field " + current.name +
117                         " not defined in class " + name);
118             if (current.persistenceModifier == SpeedoModifier.missing)
119                 current.persistenceModifier =
120                         (Util.isPersistentType(current.desc, xmlDescriptors)) ?
121                         SpeedoModifier.persistent :
122                         SpeedoModifier.none;
123         }
124         // Stores the serial version uid for serializable classes
125
if (jdoClass.isSerializable) {
126             try {
127                 ObjectStreamClass JavaDoc oserial = ObjectStreamClass.lookup(
128                         Class.forName(name.replace('/', '.')));
129                 jdoClass.VersionUID = oserial.getSerialVersionUID();
130             } catch (Exception JavaDoc e) {
131             }
132         }
133     }
134
135     public void visitInnerClass(final String JavaDoc name,
136                                 final String JavaDoc outerName,
137                                 final String JavaDoc innerName,
138                                 final int access) {
139         // does nothing
140
}
141
142     public void visitField(final int access,
143                            final String JavaDoc name,
144                            final String JavaDoc desc,
145                            final Object JavaDoc value,
146                            final Attribute attrs) {
147         // Adds in the object model fields whose type is known as
148
// Persistence Capable
149
if ((access & Constants.ACC_STATIC) == 0
150                 && (access & Constants.ACC_FINAL) == 0
151               && (access & Constants.ACC_SYNTHETIC) == 0) {
152             SpeedoField jdoField = (SpeedoField) jdoClass.jdoField.get(name);
153             if (jdoField == null
154                     && Util.isAutomaticPersistentType(desc, xmlDescriptors)) {
155                 jdoField = new SpeedoField();
156                 jdoField.persistenceModifier = SpeedoModifier.persistent;
157                 jdoField.name = name;
158                 jdoField.access = access;
159                 jdoField.desc = desc;
160                 jdoClass.add(jdoField);
161             }
162         }
163     }
164
165     public CodeVisitor visitMethod(final int access,
166                                    final String JavaDoc name,
167                                    final String JavaDoc desc,
168                                    final String JavaDoc[] exceptions,
169                                    final Attribute attrs) {
170         if ("<init>".equals(name) && "()V".equals(desc)) {
171             jdoClass.noArgConstructorStatus = ((access & Constants.ACC_PUBLIC) == 0
172                 ? SpeedoClass.NON_PUBLIC_NO_ARG_CONSTRUCTOR
173                 : SpeedoClass.PUBLIC_NO_ARG_CONSTRUCTOR);
174             if (logger.isLoggable(BasicLevel.DEBUG)) {
175                 logger.log(BasicLevel.DEBUG, jdoClass.getFQName()
176                     + ".noArgConstructorStatus=" + jdoClass.noArgConstructorStatus);
177             }
178         }
179         return null;
180     }
181
182     public void visitAttribute(Attribute attribute) {
183         // does nothing
184
}
185
186     public void visitEnd() {
187         // Removes from the object model all fields that are not defined as
188
// persistent
189

190         for (Iterator JavaDoc it = jdoClass.jdoField.entrySet().iterator();it.hasNext();) {
191             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
192             SpeedoField field = (SpeedoField) entry.getValue();
193             if (field.persistenceModifier != SpeedoModifier.persistent) {
194                 it.remove();
195             }
196         }
197     }
198
199     /**
200      * Looks for a field in a class, and in its (persistent) super classes.
201      */

202     class ClassFieldFinder implements ClassVisitor {
203
204         /**
205          * Information about this field, if found.
206          */

207         private SpeedoField result;
208         boolean find = false;
209
210         public boolean fillInfo(SpeedoField sf) {
211             this.result = sf;
212             String JavaDoc className = sf.jdoClass.getFQName();
213             SpeedoCompilerParameter scp = enhancer.getSpeedoCompilerParameter();
214             try {
215                 find = false;
216                 while (true) {
217                     // lookup in the class if the field exists
218
ClassReader cr = enhancer.loadJavaClass(enhancer.isSrcJar,
219                                 className, scp.output, false);
220                     cr.accept(this, true);
221                     if (find) {
222                         return true;
223                     }
224
225                     // lookup in the super class, if applicable
226
className = jdoClass.superClassName;
227                     if (className == null || className.length() == 0) {
228                         // The current class has not a superclasses and the
229
// field has not been found
230
return false;
231                     }
232                 }
233             } catch (Exception JavaDoc e) {
234                 e.printStackTrace();
235                 return false;
236             }
237         }
238
239         public void visit(final int version,
240                           final int access,
241                           final String JavaDoc name,
242                           final String JavaDoc superName,
243                           final String JavaDoc[] interfaces,
244                           final String JavaDoc sourceFile) {
245             // does nothing
246
}
247
248         public void visitInnerClass(final String JavaDoc name,
249                                     final String JavaDoc outerName,
250                                     final String JavaDoc innerName,
251                                     final int access) {
252             // does nothing
253
}
254
255         public void visitField(final int access,
256                                final String JavaDoc name,
257                                final String JavaDoc desc,
258                                final Object JavaDoc value,
259                                final Attribute attrs) {
260             if (name.equals(result.name)) {
261                 // we have found the field we are looking for
262
result.access = access;
263                 result.desc = desc;
264                 find = true;
265             }
266         }
267
268         public CodeVisitor visitMethod(final int access,
269                                        final String JavaDoc name,
270                                        final String JavaDoc desc,
271                                        final String JavaDoc[] exceptions,
272                                        final Attribute attrs) {
273             // this visitor does not need to visit the code of methods
274
return null;
275         }
276
277         public void visitAttribute(Attribute attribute) {
278             // does nothing
279
}
280
281         public void visitEnd() {
282             // does nothing
283
}
284     }
285 }
286
Popular Tags