KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > bcel > generic > ClassGen


1 /*
2  * Copyright 2000-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17 package org.apache.bcel.generic;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22 import org.apache.bcel.Constants;
23 import org.apache.bcel.classfile.AccessFlags;
24 import org.apache.bcel.classfile.Attribute;
25 import org.apache.bcel.classfile.ConstantPool;
26 import org.apache.bcel.classfile.Field;
27 import org.apache.bcel.classfile.JavaClass;
28 import org.apache.bcel.classfile.Method;
29 import org.apache.bcel.classfile.SourceFile;
30 import org.apache.bcel.util.BCELComparator;
31
32 /**
33  * Template class for building up a java class. May be initialized with an
34  * existing java class (file).
35  *
36  * @see JavaClass
37  * @version $Id: ClassGen.java 386056 2006-03-15 11:31:56Z tcurdt $
38  * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
39  */

40 public class ClassGen extends AccessFlags implements Cloneable JavaDoc {
41
42     /* Corresponds to the fields found in a JavaClass object.
43      */

44     private String JavaDoc class_name, super_class_name, file_name;
45     private int class_name_index = -1, superclass_name_index = -1;
46     private int major = Constants.MAJOR_1_1, minor = Constants.MINOR_1_1;
47     private ConstantPoolGen cp; // Template for building up constant pool
48
// ArrayLists instead of arrays to gather fields, methods, etc.
49
private List JavaDoc field_vec = new ArrayList JavaDoc();
50     private List JavaDoc method_vec = new ArrayList JavaDoc();
51     private List JavaDoc attribute_vec = new ArrayList JavaDoc();
52     private List JavaDoc interface_vec = new ArrayList JavaDoc();
53     private static BCELComparator _cmp = new BCELComparator() {
54
55         public boolean equals( Object JavaDoc o1, Object JavaDoc o2 ) {
56             ClassGen THIS = (ClassGen) o1;
57             ClassGen THAT = (ClassGen) o2;
58             return THIS.getClassName().equals(THAT.getClassName());
59         }
60
61
62         public int hashCode( Object JavaDoc o ) {
63             ClassGen THIS = (ClassGen) o;
64             return THIS.getClassName().hashCode();
65         }
66     };
67
68
69     /** Convenience constructor to set up some important values initially.
70      *
71      * @param class_name fully qualified class name
72      * @param super_class_name fully qualified superclass name
73      * @param file_name source file name
74      * @param access_flags access qualifiers
75      * @param interfaces implemented interfaces
76      * @param cp constant pool to use
77      */

78     public ClassGen(String JavaDoc class_name, String JavaDoc super_class_name, String JavaDoc file_name, int access_flags,
79             String JavaDoc[] interfaces, ConstantPoolGen cp) {
80         this.class_name = class_name;
81         this.super_class_name = super_class_name;
82         this.file_name = file_name;
83         this.access_flags = access_flags;
84         this.cp = cp;
85         // Put everything needed by default into the constant pool and the vectors
86
if (file_name != null) {
87             addAttribute(new SourceFile(cp.addUtf8("SourceFile"), 2, cp.addUtf8(file_name), cp
88                     .getConstantPool()));
89         }
90         class_name_index = cp.addClass(class_name);
91         superclass_name_index = cp.addClass(super_class_name);
92         if (interfaces != null) {
93             for (int i = 0; i < interfaces.length; i++) {
94                 addInterface(interfaces[i]);
95             }
96         }
97     }
98
99
100     /** Convenience constructor to set up some important values initially.
101      *
102      * @param class_name fully qualified class name
103      * @param super_class_name fully qualified superclass name
104      * @param file_name source file name
105      * @param access_flags access qualifiers
106      * @param interfaces implemented interfaces
107      */

108     public ClassGen(String JavaDoc class_name, String JavaDoc super_class_name, String JavaDoc file_name, int access_flags,
109             String JavaDoc[] interfaces) {
110         this(class_name, super_class_name, file_name, access_flags, interfaces,
111                 new ConstantPoolGen());
112     }
113
114
115     /**
116      * Initialize with existing class.
117      * @param clazz JavaClass object (e.g. read from file)
118      */

119     public ClassGen(JavaClass clazz) {
120         class_name_index = clazz.getClassNameIndex();
121         superclass_name_index = clazz.getSuperclassNameIndex();
122         class_name = clazz.getClassName();
123         super_class_name = clazz.getSuperclassName();
124         file_name = clazz.getSourceFileName();
125         access_flags = clazz.getAccessFlags();
126         cp = new ConstantPoolGen(clazz.getConstantPool());
127         major = clazz.getMajor();
128         minor = clazz.getMinor();
129         Attribute[] attributes = clazz.getAttributes();
130         Method[] methods = clazz.getMethods();
131         Field[] fields = clazz.getFields();
132         String JavaDoc[] interfaces = clazz.getInterfaceNames();
133         for (int i = 0; i < interfaces.length; i++) {
134             addInterface(interfaces[i]);
135         }
136         for (int i = 0; i < attributes.length; i++) {
137             addAttribute(attributes[i]);
138         }
139         for (int i = 0; i < methods.length; i++) {
140             addMethod(methods[i]);
141         }
142         for (int i = 0; i < fields.length; i++) {
143             addField(fields[i]);
144         }
145     }
146
147
148     /**
149      * @return the (finally) built up Java class object.
150      */

151     public JavaClass getJavaClass() {
152         int[] interfaces = getInterfaces();
153         Field[] fields = getFields();
154         Method[] methods = getMethods();
155         Attribute[] attributes = getAttributes();
156         // Must be last since the above calls may still add something to it
157
ConstantPool _cp = this.cp.getFinalConstantPool();
158         return new JavaClass(class_name_index, superclass_name_index, file_name, major, minor,
159                 access_flags, _cp, interfaces, fields, methods, attributes);
160     }
161
162
163     /**
164      * Add an interface to this class, i.e., this class has to implement it.
165      * @param name interface to implement (fully qualified class name)
166      */

167     public void addInterface( String JavaDoc name ) {
168         interface_vec.add(name);
169     }
170
171
172     /**
173      * Remove an interface from this class.
174      * @param name interface to remove (fully qualified name)
175      */

176     public void removeInterface( String JavaDoc name ) {
177         interface_vec.remove(name);
178     }
179
180
181     /**
182      * @return major version number of class file
183      */

184     public int getMajor() {
185         return major;
186     }
187
188
189     /** Set major version number of class file, default value is 45 (JDK 1.1)
190      * @param major major version number
191      */

192     public void setMajor( int major ) {
193         this.major = major;
194     }
195
196
197     /** Set minor version number of class file, default value is 3 (JDK 1.1)
198      * @param minor minor version number
199      */

200     public void setMinor( int minor ) {
201         this.minor = minor;
202     }
203
204
205     /**
206      * @return minor version number of class file
207      */

208     public int getMinor() {
209         return minor;
210     }
211
212
213     /**
214      * Add an attribute to this class.
215      * @param a attribute to add
216      */

217     public void addAttribute( Attribute a ) {
218         attribute_vec.add(a);
219     }
220
221
222     /**
223      * Add a method to this class.
224      * @param m method to add
225      */

226     public void addMethod( Method m ) {
227         method_vec.add(m);
228     }
229
230
231     /**
232      * Convenience method.
233      *
234      * Add an empty constructor to this class that does nothing but calling super().
235      * @param access_flags rights for constructor
236      */

237     public void addEmptyConstructor( int access_flags ) {
238         InstructionList il = new InstructionList();
239         il.append(InstructionConstants.THIS); // Push `this'
240
il.append(new INVOKESPECIAL(cp.addMethodref(super_class_name, "<init>", "()V")));
241         il.append(InstructionConstants.RETURN);
242         MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "<init>",
243                 class_name, il, cp);
244         mg.setMaxStack(1);
245         addMethod(mg.getMethod());
246     }
247
248
249     /**
250      * Add a field to this class.
251      * @param f field to add
252      */

253     public void addField( Field f ) {
254         field_vec.add(f);
255     }
256
257
258     public boolean containsField( Field f ) {
259         return field_vec.contains(f);
260     }
261
262
263     /** @return field object with given name, or null
264      */

265     public Field containsField( String JavaDoc name ) {
266         for (Iterator JavaDoc e = field_vec.iterator(); e.hasNext();) {
267             Field f = (Field) e.next();
268             if (f.getName().equals(name)) {
269                 return f;
270             }
271         }
272         return null;
273     }
274
275
276     /** @return method object with given name and signature, or null
277      */

278     public Method containsMethod( String JavaDoc name, String JavaDoc signature ) {
279         for (Iterator JavaDoc e = method_vec.iterator(); e.hasNext();) {
280             Method m = (Method) e.next();
281             if (m.getName().equals(name) && m.getSignature().equals(signature)) {
282                 return m;
283             }
284         }
285         return null;
286     }
287
288
289     /**
290      * Remove an attribute from this class.
291      * @param a attribute to remove
292      */

293     public void removeAttribute( Attribute a ) {
294         attribute_vec.remove(a);
295     }
296
297
298     /**
299      * Remove a method from this class.
300      * @param m method to remove
301      */

302     public void removeMethod( Method m ) {
303         method_vec.remove(m);
304     }
305
306
307     /** Replace given method with new one. If the old one does not exist
308      * add the new_ method to the class anyway.
309      */

310     public void replaceMethod( Method old, Method new_ ) {
311         if (new_ == null) {
312             throw new ClassGenException("Replacement method must not be null");
313         }
314         int i = method_vec.indexOf(old);
315         if (i < 0) {
316             method_vec.add(new_);
317         } else {
318             method_vec.set(i, new_);
319         }
320     }
321
322
323     /** Replace given field with new one. If the old one does not exist
324      * add the new_ field to the class anyway.
325      */

326     public void replaceField( Field old, Field new_ ) {
327         if (new_ == null) {
328             throw new ClassGenException("Replacement method must not be null");
329         }
330         int i = field_vec.indexOf(old);
331         if (i < 0) {
332             field_vec.add(new_);
333         } else {
334             field_vec.set(i, new_);
335         }
336     }
337
338
339     /**
340      * Remove a field to this class.
341      * @param f field to remove
342      */

343     public void removeField( Field f ) {
344         field_vec.remove(f);
345     }
346
347
348     public String JavaDoc getClassName() {
349         return class_name;
350     }
351
352
353     public String JavaDoc getSuperclassName() {
354         return super_class_name;
355     }
356
357
358     public String JavaDoc getFileName() {
359         return file_name;
360     }
361
362
363     public void setClassName( String JavaDoc name ) {
364         class_name = name.replace('/', '.');
365         class_name_index = cp.addClass(name);
366     }
367
368
369     public void setSuperclassName( String JavaDoc name ) {
370         super_class_name = name.replace('/', '.');
371         superclass_name_index = cp.addClass(name);
372     }
373
374
375     public Method[] getMethods() {
376         return (Method[]) method_vec.toArray(new Method[method_vec.size()]);
377     }
378
379
380     public void setMethods( Method[] methods ) {
381         method_vec.clear();
382         for (int m = 0; m < methods.length; m++) {
383             addMethod(methods[m]);
384         }
385     }
386
387
388     public void setMethodAt( Method method, int pos ) {
389         method_vec.set(pos, method);
390     }
391
392
393     public Method getMethodAt( int pos ) {
394         return (Method) method_vec.get(pos);
395     }
396
397
398     public String JavaDoc[] getInterfaceNames() {
399         int size = interface_vec.size();
400         String JavaDoc[] interfaces = new String JavaDoc[size];
401         interface_vec.toArray(interfaces);
402         return interfaces;
403     }
404
405
406     public int[] getInterfaces() {
407         int size = interface_vec.size();
408         int[] interfaces = new int[size];
409         for (int i = 0; i < size; i++) {
410             interfaces[i] = cp.addClass((String JavaDoc) interface_vec.get(i));
411         }
412         return interfaces;
413     }
414
415
416     public Field[] getFields() {
417         return (Field[]) field_vec.toArray(new Field[field_vec.size()]);
418     }
419
420
421     public Attribute[] getAttributes() {
422         return (Attribute[]) attribute_vec.toArray(new Attribute[attribute_vec.size()]);
423     }
424
425
426     public ConstantPoolGen getConstantPool() {
427         return cp;
428     }
429
430
431     public void setConstantPool( ConstantPoolGen constant_pool ) {
432         cp = constant_pool;
433     }
434
435
436     public void setClassNameIndex( int class_name_index ) {
437         this.class_name_index = class_name_index;
438         class_name = cp.getConstantPool().getConstantString(class_name_index,
439                 Constants.CONSTANT_Class).replace('/', '.');
440     }
441
442
443     public void setSuperclassNameIndex( int superclass_name_index ) {
444         this.superclass_name_index = superclass_name_index;
445         super_class_name = cp.getConstantPool().getConstantString(superclass_name_index,
446                 Constants.CONSTANT_Class).replace('/', '.');
447     }
448
449
450     public int getSuperclassNameIndex() {
451         return superclass_name_index;
452     }
453
454
455     public int getClassNameIndex() {
456         return class_name_index;
457     }
458
459     private ArrayList JavaDoc observers;
460
461
462     /** Add observer for this object.
463      */

464     public void addObserver( ClassObserver o ) {
465         if (observers == null) {
466             observers = new ArrayList JavaDoc();
467         }
468         observers.add(o);
469     }
470
471
472     /** Remove observer for this object.
473      */

474     public void removeObserver( ClassObserver o ) {
475         if (observers != null) {
476             observers.remove(o);
477         }
478     }
479
480
481     /** Call notify() method on all observers. This method is not called
482      * automatically whenever the state has changed, but has to be
483      * called by the user after he has finished editing the object.
484      */

485     public void update() {
486         if (observers != null) {
487             for (Iterator JavaDoc e = observers.iterator(); e.hasNext();) {
488                 ((ClassObserver) e.next()).notify(this);
489             }
490         }
491     }
492
493
494     public Object JavaDoc clone() {
495         try {
496             return super.clone();
497         } catch (CloneNotSupportedException JavaDoc e) {
498             System.err.println(e);
499             return null;
500         }
501     }
502
503
504     /**
505      * @return Comparison strategy object
506      */

507     public static BCELComparator getComparator() {
508         return _cmp;
509     }
510
511
512     /**
513      * @param comparator Comparison strategy object
514      */

515     public static void setComparator( BCELComparator comparator ) {
516         _cmp = comparator;
517     }
518
519
520     /**
521      * Return value as defined by given BCELComparator strategy.
522      * By default two ClassGen objects are said to be equal when
523      * their class names are equal.
524      *
525      * @see java.lang.Object#equals(java.lang.Object)
526      */

527     public boolean equals( Object JavaDoc obj ) {
528         return _cmp.equals(this, obj);
529     }
530
531
532     /**
533      * Return value as defined by given BCELComparator strategy.
534      * By default return the hashcode of the class name.
535      *
536      * @see java.lang.Object#hashCode()
537      */

538     public int hashCode() {
539         return _cmp.hashCode(this);
540     }
541 }
542
Popular Tags