Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

ClassGen.java

00001 package de.fub.bytecode.generic;
00002 
00003 import de.fub.bytecode.Constants;
00004 import de.fub.bytecode.classfile.*;
00005 import java.util.Vector;
00006 import java.util.Enumeration;
00007 
00008 /** 
00009  * Template class for building up a java class. May be initialized with an
00010  * existing java class (file).
00011  *
00012  * @see JavaClass
00013  * @version $Id: ClassGen.java,v 1.1.1.1 2002/01/24 03:41:38 pserver Exp $
00014  * @author  <A HREF="http://www.inf.fu-berlin.de/~dahm">M. Dahm</A>
00015  */
00016 public class ClassGen extends AccessFlags implements Cloneable {
00017   /* Corresponds to the fields found in a JavaClass object.
00018    */
00019   private String   class_name, super_class_name, file_name;
00020   private int      class_name_index = -1, superclass_name_index = -1;
00021   private int      major = Constants.MAJOR_1_1, minor = Constants.MINOR_1_1;
00022 
00023   private ConstantPoolGen cp; // Template for building up constant pool
00024 
00025   // Vectors instead of arrays to gather fields, methods, etc.
00026   private Vector   field_vec     = new Vector();
00027   private Vector   method_vec    = new Vector();
00028   private Vector   attribute_vec = new Vector();
00029   private Vector   interface_vec = new Vector();
00030 
00031   private Vector observers;
00032 
00033   /**
00034    * Initialize with existing class.
00035    * @param clazz JavaClass object (e.g. read from file)
00036    */
00037   public ClassGen(JavaClass clazz) {
00038     class_name_index      = clazz.getClassNameIndex();
00039     superclass_name_index = clazz.getSuperclassNameIndex();
00040     class_name            = clazz.getClassName();
00041     super_class_name      = clazz.getSuperclassName();
00042     file_name             = clazz.getSourceFileName();
00043     access_flags          = clazz.getAccessFlags();
00044     cp                    = new ConstantPoolGen(clazz.getConstantPool());
00045     major                 = clazz.getMajor();
00046     minor                 = clazz.getMinor();
00047 
00048     Attribute[] attributes = clazz.getAttributes();
00049     Method[]    methods    = clazz.getMethods();
00050     Field[]     fields     = clazz.getFields();
00051     String[]    interfaces = clazz.getInterfaceNames();
00052     
00053     for(int i=0; i < interfaces.length; i++)
00054       addInterface(interfaces[i]);
00055 
00056     for(int i=0; i < attributes.length; i++)
00057       addAttribute(attributes[i]);
00058 
00059     for(int i=0; i < methods.length; i++)
00060       addMethod(methods[i]);
00061 
00062     for(int i=0; i < fields.length; i++)
00063       addField(fields[i]);
00064   }  
00065   /** Convenience constructor to set up some important values initially.
00066    *
00067    * @param class_name fully qualified class name
00068    * @param super_class_name fully qualified superclass name
00069    * @param file_name source file name
00070    * @param access_flags access qualifiers
00071    * @param interfaces implemented interfaces
00072    */
00073   public ClassGen(String class_name, String super_class_name, String file_name,
00074           int access_flags, String[] interfaces) {
00075     this.class_name       = class_name;
00076     this.super_class_name = super_class_name;
00077     this.file_name        = file_name;
00078     this.access_flags     = access_flags;
00079     cp = new ConstantPoolGen(); // Create empty constant pool
00080 
00081     // Put everything needed by default into the constant pool and the vectors
00082     addAttribute(new SourceFile(cp.addUtf8("SourceFile"), 2,
00083                 cp.addUtf8(file_name), cp.getConstantPool()));
00084     class_name_index      = cp.addClass(class_name);
00085     superclass_name_index = cp.addClass(super_class_name);
00086 
00087     if(interfaces != null)
00088       for(int i=0; i < interfaces.length; i++)
00089     addInterface(interfaces[i]);
00090   }  
00091   /**
00092    * Add an attribute to this class.
00093    * @param a attribute to add
00094    */
00095   public void addAttribute(Attribute a)    { attribute_vec.addElement(a); }  
00096   /**
00097    * Convenience method.
00098    *
00099    * Add an empty constructor to this class that does nothing but calling super().
00100    * @param access rights for constructor
00101    */
00102   public void addEmptyConstructor(int access_flags) {
00103     InstructionList il = new InstructionList();
00104     il.append(InstructionConstants.THIS); // Push `this'
00105     il.append(new INVOKESPECIAL(cp.addMethodref(super_class_name,
00106                         "<init>", "()V")));
00107     il.append(InstructionConstants.RETURN);
00108 
00109     MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null,
00110                "<init>", class_name, il, cp);
00111     mg.setMaxStack(1);
00112     addMethod(mg.getMethod());
00113   }  
00114   /**
00115    * Add a field to this class.
00116    * @param f field to add
00117    */
00118   public void addField(Field f)            { field_vec.addElement(f); }  
00119   /**
00120    * Add an interface to this class, i.e., this class has to implement it.
00121    * @param name interface to implement (fully qualified class name)
00122    */
00123   public void addInterface(String name) {
00124     interface_vec.addElement(name);
00125   }  
00126   /**
00127    * Add a method to this class.
00128    * @param m method to add
00129    */
00130   public void addMethod(Method m)          { method_vec.addElement(m); }  
00131   /** Add observer for this object.
00132    */
00133   public void addObserver(ClassObserver o) {
00134     if(observers == null)
00135       observers = new Vector();
00136 
00137     observers.add(o);
00138   }  
00139   public Object clone() {
00140     try {
00141       return super.clone();
00142     } catch(CloneNotSupportedException e) {
00143       System.err.println(e);
00144       return null;
00145     }
00146   }  
00147   public boolean containsField(Field f)    { return field_vec.contains(f); }  
00148   /** @return field object with given name, or null
00149    */
00150   public Field containsField(String name) {
00151     for(Enumeration e=field_vec.elements(); e.hasMoreElements();) {
00152       Field f = (Field)e.nextElement();
00153       if(f.getName().equals(name))
00154     return f;
00155     }
00156 
00157     return null;
00158   }  
00159   /** @return method object with given name and signature, or null
00160    */
00161   public Method containsMethod(String name, String signature) {
00162     for(Enumeration e=method_vec.elements(); e.hasMoreElements();) {
00163       Method m = (Method)e.nextElement();
00164       if(m.getName().equals(name) && m.getSignature().equals(signature))
00165     return m;
00166     }
00167 
00168     return null;
00169   }  
00170   public Attribute[] getAttributes() {
00171     Attribute[] attributes = new Attribute[attribute_vec.size()];
00172     attribute_vec.copyInto(attributes);
00173     return attributes;
00174   }  
00175   public String getClassName()      { return class_name; }  
00176   public int getClassNameIndex()   { return class_name_index; }  
00177   public ConstantPoolGen getConstantPool() { return cp; }  
00178   public Field[] getFields() {
00179     Field[] fields = new Field[field_vec.size()];
00180     field_vec.copyInto(fields);
00181     return fields;
00182   }  
00183   public String getFileName()       { return file_name; }  
00184   public String[] getInterfaceNames() {
00185     int      size = interface_vec.size();
00186     String[] interfaces = new String[size];
00187 
00188     interface_vec.toArray(interfaces);
00189     return interfaces;
00190   }  
00191   public int[] getInterfaces() {
00192     int   size = interface_vec.size();
00193     int[] interfaces = new int[size];
00194 
00195     for(int i=0; i < size; i++)
00196       interfaces[i] = cp.addClass((String)interface_vec.elementAt(i));
00197 
00198     return interfaces;
00199   }  
00200   /**
00201    * @return the (finally) built up Java class object.
00202    */
00203   public JavaClass getJavaClass() {
00204     int[]        interfaces = getInterfaces();
00205     Field[]      fields     = getFields();
00206     Method[]     methods    = getMethods();
00207     Attribute[]  attributes = getAttributes();
00208 
00209     // Must be last since the above calls may still add something to it
00210     ConstantPool cp         = this.cp.getFinalConstantPool();
00211     
00212     return new JavaClass(class_name_index, superclass_name_index,
00213              file_name, major, minor, access_flags,
00214              cp, interfaces, fields, methods, attributes);
00215   }  
00216   /**
00217    * @return major version number of class file
00218    */
00219   public int  getMajor()      { return major; }  
00220   public Method getMethodAt(int pos) {
00221     return (Method)method_vec.elementAt(pos);
00222   }  
00223   public Method[] getMethods() {
00224     Method[] methods = new Method[method_vec.size()];
00225     method_vec.copyInto(methods);
00226     return methods;
00227   }  
00228   /**
00229    * @return minor version number of class file
00230    */
00231   public int  getMinor()      { return minor; }  
00232   public String getSuperclassName() { return super_class_name; }  
00233   public int getSuperclassNameIndex() { return superclass_name_index; }  
00234   /**
00235    * Remove an attribute from this class.
00236    * @param a attribute to remove
00237    */
00238   public void removeAttribute(Attribute a) { attribute_vec.removeElement(a); }  
00239   /**
00240    * Remove a field to this class.
00241    * @param f field to remove
00242    */
00243   public void removeField(Field f)         { field_vec.removeElement(f); }  
00244   /**
00245    * Remove an interface from this class.
00246    * @param name interface to remove (fully qualified name)
00247    */
00248   public void removeInterface(String name) {
00249     interface_vec.remove(name);
00250   }  
00251   /**
00252    * Remove a method from this class.
00253    * @param m method to remove
00254    */
00255   public void removeMethod(Method m)       { method_vec.removeElement(m); }  
00256   /** Remove observer for this object.
00257    */
00258   public void removeObserver(ClassObserver o) {
00259     if(observers != null)
00260       observers.removeElement(o);
00261   }  
00262   /** Replace given field with new one. If the old one does not exist
00263    * add the new_ field to the class anyway.
00264    */
00265   public void replaceField(Field old, Field new_) {
00266     if(new_ == null)
00267       throw new ClassGenException("Replacement method must not be null");
00268 
00269     int i = field_vec.indexOf(old);
00270 
00271     if(i < 0)
00272       field_vec.addElement(new_);
00273     else
00274       field_vec.setElementAt(new_, i);
00275   }  
00276   /** Replace given method with new one. If the old one does not exist
00277    * add the new_ method to the class anyway.
00278    */
00279   public void replaceMethod(Method old, Method new_) {
00280     if(new_ == null)
00281       throw new ClassGenException("Replacement method must not be null");
00282 
00283     int i = method_vec.indexOf(old);
00284 
00285     if(i < 0)
00286       method_vec.addElement(new_);
00287     else
00288       method_vec.setElementAt(new_, i);
00289   }  
00290   public void setClassName(String name) {
00291     class_name = name.replace('/', '.');
00292     class_name_index = cp.addClass(name);
00293   }  
00294   public void setClassNameIndex(int class_name_index) {
00295     this.class_name_index = class_name_index;
00296     class_name = cp.getConstantPool().
00297       getConstantString(class_name_index, Constants.CONSTANT_Class).replace('/', '.');
00298   }  
00299   public void setConstantPool(ConstantPoolGen constant_pool) {
00300     cp = constant_pool;
00301   }  
00302   /** Set major version number of class file, default value is 45 (JDK 1.1)
00303    * @param major major version number
00304    */
00305   public void setMajor(int major) {
00306     this.major = major;
00307   }  
00308   public void setMethodAt(Method method, int pos) {
00309     method_vec.setElementAt(method, pos);
00310   }  
00311   public void setMethods(Method[] methods) {
00312     method_vec.removeAllElements();
00313     for (int m=0; m<methods.length; m++)
00314       addMethod(methods[m]);
00315   }  
00316   /** Set minor version number of class file, default value is 3 (JDK 1.1)
00317    * @param minor minor version number
00318    */
00319   public void setMinor(int minor) {
00320     this.minor = minor;
00321   }  
00322   public void setSuperclassName(String name) {
00323     super_class_name = name.replace('/', '.');
00324     superclass_name_index = cp.addClass(name);
00325   }  
00326   public void setSuperclassNameIndex(int superclass_name_index) {
00327     this.superclass_name_index = superclass_name_index;
00328     super_class_name = cp.getConstantPool().
00329       getConstantString(superclass_name_index, Constants.CONSTANT_Class).replace('/', '.');
00330   }  
00331   /** Call notify() method on all observers. This method is not called
00332    * automatically whenever the state has changed, but has to be
00333    * called by the user after he has finished editing the object.
00334    */
00335   public void update() {
00336     if(observers != null)
00337       for(Enumeration e = observers.elements(); e.hasMoreElements(); )
00338     ((ClassObserver)e.nextElement()).notify(this);
00339   }  
00340 }

Generated at Thu Feb 7 06:42:19 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001