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

ConstantPoolGen.java

00001 package de.fub.bytecode.generic;
00002 
00003 import de.fub.bytecode.Constants;
00004 import de.fub.bytecode.classfile.*;
00005 import java.util.Hashtable;
00006 
00007 /** 
00008  * This class is used to build up a constant pool. The user adds
00009  * constants via `addXXX' methods, `addString', `addClass',
00010  * etc.. These methods return an index into the constant
00011  * pool. Finally, `getFinalConstantPool()' returns the constant pool
00012  * built up. Intermediate versions of the constant pool can be
00013  * obtained with `getConstantPool()'. A constant pool has capacity for
00014  * Constants.MAX_SHORT entries. Note that the first (0) is used by the
00015  * JVM and that Double and Long constants need two slots.
00016  *
00017  * @version $Id: ConstantPoolGen.java,v 1.1.1.1 2002/01/24 03:44:04 pserver Exp $
00018  * @author  <A HREF="http://www.inf.fu-berlin.de/~dahm">M. Dahm</A>
00019  * @see Constant
00020  */
00021 public class ConstantPoolGen implements Constants {
00022   protected int        size      = 1024; // Inital size, sufficient in most cases
00023   protected Constant[] constants = new Constant[size];
00024   protected int        index     = 1; // First entry (0) used by JVM
00025 
00026   private static class Index {
00027     int index;
00028     Index(int i) { index = i; }
00029   }
00030 
00031   private Hashtable string_table = new Hashtable();
00032 
00033   private Hashtable class_table = new Hashtable();
00034 
00035   private Hashtable n_a_t_table = new Hashtable();
00036 
00037   private Hashtable cp_table = new Hashtable();
00038 
00039   /**
00040    * Create empty constant pool.
00041    */
00042   public ConstantPoolGen() {}  
00043   /**
00044    * Initialize with given array of constants.
00045    *
00046    * @param c array of given constants, new ones will be appended
00047    */
00048   public ConstantPoolGen(Constant[] cs) {
00049     if(cs.length > size) {
00050       size      = cs.length;
00051       constants = new Constant[size];
00052     }
00053 
00054     System.arraycopy(cs, 0, constants, 0, cs.length);
00055 
00056     if(cs.length > 0)
00057       index = cs.length;
00058 
00059     for(int i=1; i < index; i++) {
00060       Constant c = constants[i];
00061 
00062       if(c instanceof ConstantString) {
00063     ConstantString s  = (ConstantString)c;
00064     ConstantUtf8   u8 = (ConstantUtf8)constants[s.getStringIndex()];
00065 
00066     string_table.put(u8.getBytes(), new Index(i));
00067       } else if(c instanceof ConstantClass) {
00068     ConstantClass s  = (ConstantClass)c;
00069     ConstantUtf8  u8 = (ConstantUtf8)constants[s.getNameIndex()];
00070 
00071     class_table.put(u8.getBytes(), new Index(i));
00072       } else if(c instanceof ConstantNameAndType) {
00073     ConstantNameAndType n    = (ConstantNameAndType)c;
00074     ConstantUtf8        u8   = (ConstantUtf8)constants[n.getNameIndex()];
00075     ConstantUtf8        u8_2 = (ConstantUtf8)constants[n.getSignatureIndex()];
00076 
00077     n_a_t_table.put(u8.getBytes() + ":" + u8_2.getBytes(), new Index(i));
00078       } else if(c instanceof ConstantCP) {
00079     ConstantCP          m     = (ConstantCP)c;
00080     ConstantClass       clazz = (ConstantClass)constants[m.getClassIndex()];
00081     ConstantNameAndType n     = (ConstantNameAndType)constants[m.getNameAndTypeIndex()];
00082     
00083         ConstantUtf8 u8         = (ConstantUtf8)constants[clazz.getNameIndex()];
00084         String       class_name = u8.getBytes().replace('/', '.');
00085 
00086     u8 = (ConstantUtf8)constants[n.getNameIndex()];
00087     String method_name = u8.getBytes();
00088 
00089     u8 = (ConstantUtf8)constants[n.getSignatureIndex()];
00090     String signature = u8.getBytes();
00091 
00092     cp_table.put(class_name + ":" + method_name + ":" + signature, new Index(i));
00093       }
00094     }
00095   }  
00096   /**
00097    * Initialize with given constant pool.
00098    */
00099   public ConstantPoolGen(ConstantPool cp) {
00100     this(cp.getConstantPool());
00101   }  
00102   /**
00103    * Add a reference to an array class (e.g. String[][]) as needed by MULTIANEWARRAY
00104    * instruction, e.g. to the ConstantPool.
00105    *
00106    * @param type type of array class
00107    * @return index of entry
00108    */
00109   public int addArrayClass(ArrayType type) {
00110     return addClass_(type.getSignature());
00111   }  
00112   /**
00113    * Add a new Class reference to the ConstantPool for a given type.
00114    *
00115    * @param str Class to add
00116    * @return index of entry
00117    */
00118   public int addClass(ObjectType type) {
00119     return addClass(type.getClassName());
00120   }  
00121   /**
00122    * Add a new Class reference to the ConstantPool, if it is not already in there.
00123    *
00124    * @param str Class to add
00125    * @return index of entry
00126    */
00127   public int addClass(String str) {
00128     return addClass_(str.replace('.', '/'));
00129   }  
00130   private int addClass_(String clazz) {
00131     int    ret;
00132 
00133     if((ret = lookupClass(clazz)) != -1)
00134       return ret; // Already in CP
00135 
00136     adjustSize();
00137 
00138     ConstantUtf8  u8 = new ConstantUtf8(clazz);
00139     ConstantClass c  = new ConstantClass(index);
00140 
00141     constants[index++] = u8;
00142     ret = index;
00143     constants[index++] = c;
00144 
00145     class_table.put(clazz, new Index(ret));
00146 
00147     return ret;
00148   }  
00149   /**
00150    * Add a new double constant to the ConstantPool, if it is not already in there.
00151    *
00152    * @param n Double number to add
00153    * @return index of entry
00154    */
00155   public int addDouble(double n) {
00156     int  ret;
00157 
00158     if((ret = lookupDouble(n)) != -1)
00159       return ret; // Already in CP
00160 
00161     adjustSize();
00162 
00163     ret = index;
00164     constants[index] = new ConstantDouble(n);
00165     index += 2;   // Wastes one entry according to spec
00166 
00167     return ret;
00168   }  
00169   /**
00170    * Add a new Fieldref constant to the ConstantPool, if it is not already 
00171    * in there.
00172    *
00173    * @param n Fieldref string to add
00174    * @return index of entry
00175    */
00176   public int addFieldref(String class_name, String field_name,
00177                    String signature) {
00178     int  ret;
00179     int  class_index, name_and_type_index;
00180 
00181     if((ret = lookupFieldref(class_name, field_name, signature)) != -1)
00182       return ret; // Already in CP
00183 
00184     adjustSize();
00185 
00186     class_index         = addClass(class_name);
00187     name_and_type_index = addNameAndType(field_name, signature);
00188     ret = index;
00189     constants[index++] = new ConstantFieldref(class_index, name_and_type_index);
00190 
00191     cp_table.put(class_name + "&" + field_name + "&" + signature, new Index(ret));
00192 
00193     return ret;
00194   }  
00195   /**
00196    * Add a new Float constant to the ConstantPool, if it is not already in there.
00197    *
00198    * @param n Float number to add
00199    * @return index of entry
00200    */
00201   public int addFloat(float n) {
00202     int  ret;
00203 
00204     if((ret = lookupFloat(n)) != -1)
00205       return ret; // Already in CP
00206 
00207     adjustSize();
00208 
00209     ret = index;
00210     constants[index++] = new ConstantFloat(n);
00211 
00212     return ret;
00213   }  
00214   /* Suggested ...
00215      public final int addConstant(Constant c)
00216   {
00217     int  ret;
00218 
00219     adjustSize();
00220 
00221     ret = index;
00222     constants[index++] = c;
00223 
00224     return ret;
00225   }
00226   */
00227 
00228   /**
00229    * Add a new Integer constant to the ConstantPool, if it is not already in there.
00230    *
00231    * @param n integer number to add
00232    * @return index of entry
00233    */
00234   public int addInteger(int n) {
00235     int  ret;
00236 
00237     if((ret = lookupInteger(n)) != -1)
00238       return ret; // Already in CP
00239 
00240     adjustSize();
00241 
00242     ret = index;
00243     constants[index++] = new ConstantInteger(n);
00244 
00245     return ret;
00246   }  
00247   public int addInterfaceMethodref(MethodGen method) {
00248     return addInterfaceMethodref(method.getClassName(), method.getMethodName(),
00249                  method.getMethodSignature());
00250   }  
00251   /**
00252    * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already 
00253    * in there.
00254    *
00255    * @param n InterfaceMethodref string to add
00256    * @return index of entry
00257    */
00258   public int addInterfaceMethodref(String class_name, String method_name, String signature) {
00259     int ret, class_index, name_and_type_index;
00260 
00261     if((ret = lookupInterfaceMethodref(class_name, method_name, signature)) != -1)
00262       return ret; // Already in CP
00263 
00264     adjustSize();
00265 
00266     class_index         = addClass(class_name);
00267     name_and_type_index = addNameAndType(method_name, signature);
00268     ret = index;
00269     constants[index++] = new ConstantInterfaceMethodref(class_index, name_and_type_index);
00270 
00271     cp_table.put(class_name + "#" + method_name + "#" + signature, new Index(ret));
00272 
00273     return ret;
00274   }  
00275   /**
00276    * Add a new long constant to the ConstantPool, if it is not already in there.
00277    *
00278    * @param n Long number to add
00279    * @return index of entry
00280    */
00281   public int addLong(long n) {
00282     int  ret;
00283 
00284     if((ret = lookupLong(n)) != -1)
00285       return ret; // Already in CP
00286 
00287     adjustSize();
00288 
00289     ret = index;
00290     constants[index] = new ConstantLong(n);
00291     index += 2;   // Wastes one entry according to spec
00292 
00293     return ret;
00294   }  
00295   public int addMethodref(MethodGen method) {
00296     return addMethodref(method.getClassName(), method.getMethodName(),
00297             method.getMethodSignature());
00298   }  
00299   /**
00300    * Add a new Methodref constant to the ConstantPool, if it is not already 
00301    * in there.
00302    *
00303    * @param n Methodref string to add
00304    * @return index of entry
00305    */
00306   public int addMethodref(String class_name, String method_name, String signature) {
00307     int  ret, class_index, name_and_type_index;
00308 
00309     if((ret = lookupMethodref(class_name, method_name, signature)) != -1)
00310       return ret; // Already in CP
00311 
00312     adjustSize();
00313 
00314     name_and_type_index = addNameAndType(method_name, signature);
00315     class_index         = addClass(class_name);
00316     ret = index;
00317     constants[index++] = new ConstantMethodref(class_index, name_and_type_index);
00318 
00319     cp_table.put(class_name + ":" + method_name + ":" + signature, new Index(ret));
00320 
00321     return ret;
00322   }  
00323   /**
00324    * Add a new NameAndType constant to the ConstantPool if it is not already 
00325    * in there.
00326    *
00327    * @param n NameAndType string to add
00328    * @return index of entry
00329    */
00330   public int addNameAndType(String name, String signature) {
00331     int  ret;
00332     int  name_index, signature_index;
00333 
00334     if((ret = lookupNameAndType(name, signature)) != -1)
00335       return ret; // Already in CP
00336 
00337     adjustSize();
00338 
00339     name_index      = addUtf8(name);
00340     signature_index = addUtf8(signature);
00341     ret = index;
00342     constants[index++] = new ConstantNameAndType(name_index, signature_index);
00343 
00344     n_a_t_table.put(name + ":" + signature, new Index(ret));
00345     return ret;
00346   }  
00347   /**
00348    * Add a new String constant to the ConstantPool, if it is not already in there.
00349    *
00350    * @param str String to add
00351    * @return index of entry
00352    */
00353   public int addString(String str) {
00354     int ret;
00355     
00356     if((ret = lookupString(str)) != -1)
00357       return ret; // Already in CP
00358 
00359     adjustSize();
00360 
00361     ConstantUtf8   u8 = new ConstantUtf8(str);
00362     ConstantString s  = new ConstantString(index);
00363        
00364     constants[index++] = u8;
00365     ret = index;
00366     constants[index++] = s;
00367 
00368     string_table.put(str, new Index(ret));
00369 
00370     return ret;
00371   }  
00372   /**
00373    * Add a new Utf8 constant to the ConstantPool, if it is not already in there.
00374    *
00375    * @param n Utf8 string to add
00376    * @return index of entry
00377    */
00378   public int addUtf8(String n) {
00379     int  ret;
00380 
00381     if((ret = lookupUtf8(n)) != -1)
00382       return ret; // Already in CP
00383 
00384     adjustSize();
00385 
00386     ret = index;
00387     constants[index++] = new ConstantUtf8(n);
00388 
00389     return ret;
00390   }  
00391   /** Resize internal array of constants.
00392    */
00393   protected void adjustSize() {
00394     if(index + 3 >= size) {
00395       Constant[] cs = constants;
00396 
00397       size      *= 2;
00398       constants  = new Constant[size];
00399       System.arraycopy(cs, 0, constants, 0, index);
00400     }
00401   }  
00402   /**
00403    * @param i index in constant pool
00404    * @return constant pool entry at index i
00405    */
00406   public Constant getConstant(int i) { return constants[i]; }  
00407   /**
00408    * @return intermediate constant pool
00409    */
00410   public ConstantPool getConstantPool() {
00411     return new ConstantPool(constants);
00412   }  
00413   /**
00414    * @return constant pool with proper length
00415    */
00416   public ConstantPool getFinalConstantPool() { 
00417     Constant[] cs = new Constant[index];
00418     
00419     System.arraycopy(constants, 0, cs, 0, index);
00420 
00421     return new ConstantPool(cs); 
00422   }  
00423   /**
00424    * @return current size of constant pool
00425    */
00426   public int getSize() {
00427     return index;
00428   }  
00429   /**
00430    * Look for ConstantClass in ConstantPool named `str'.
00431    *
00432    * @param str String to search for
00433    * @return index on success, -1 otherwise
00434    */
00435   public int lookupClass(String str) {
00436     Index index = (Index)class_table.get(str);
00437     return (index != null)? index.index : -1;
00438   }  
00439   /** 
00440    * Look for ConstantDouble in ConstantPool.
00441    *
00442    * @param n Double number to look for
00443    * @return index on success, -1 otherwise
00444    */
00445   public int lookupDouble(double n) {
00446     for(int i=1; i < index; i++) {
00447       if(constants[i] instanceof ConstantDouble) {
00448     ConstantDouble c = (ConstantDouble)constants[i];
00449 
00450     if(c.getBytes() == n)
00451       return i;
00452       }
00453     }
00454 
00455     return -1;
00456   }  
00457   /** 
00458    * Look for ConstantFieldref in ConstantPool.
00459    *
00460    * @param class_name Where to find method
00461    * @param field_name Guess what
00462    * @param signature return and argument types
00463    * @return index on success, -1 otherwise
00464    */
00465   public int lookupFieldref(String class_name, String field_name, String signature) {
00466     Index index = (Index)cp_table.get(class_name + "&" + field_name + "&" + signature);
00467     return (index != null)? index.index : -1;
00468   }  
00469   /** 
00470    * Look for ConstantFloat in ConstantPool.
00471    *
00472    * @param n Float number to look for
00473    * @return index on success, -1 otherwise
00474    */
00475   public int lookupFloat(float n) {
00476     for(int i=1; i < index; i++) {
00477       if(constants[i] instanceof ConstantFloat) {
00478     ConstantFloat c = (ConstantFloat)constants[i];
00479 
00480     if(c.getBytes() == n)
00481       return i;
00482       }
00483     }
00484 
00485     return -1;
00486   }  
00487   /** 
00488    * Look for ConstantInteger in ConstantPool.
00489    *
00490    * @param n integer number to look for
00491    * @return index on success, -1 otherwise
00492    */
00493   public int lookupInteger(int n) {
00494     for(int i=1; i < index; i++) {
00495       if(constants[i] instanceof ConstantInteger) {
00496     ConstantInteger c = (ConstantInteger)constants[i];
00497 
00498     if(c.getBytes() == n)
00499       return i;
00500       }
00501     }
00502 
00503     return -1;
00504   }  
00505   public int lookupInterfaceMethodref(MethodGen method) {
00506     return lookupInterfaceMethodref(method.getClassName(), method.getMethodName(),
00507                     method.getMethodSignature());
00508   }  
00509   /** 
00510    * Look for ConstantInterfaceMethodref in ConstantPool.
00511    *
00512    * @param class_name Where to find method
00513    * @param method_name Guess what
00514    * @param signature return and argument types
00515    * @return index on success, -1 otherwise
00516    */
00517   public int lookupInterfaceMethodref(String class_name, String method_name, String signature) {
00518     Index index = (Index)cp_table.get(class_name + "#" + method_name + "#" + signature);
00519     return (index != null)? index.index : -1;
00520   }  
00521   /** 
00522    * Look for ConstantLong in ConstantPool.
00523    *
00524    * @param n Long number to look for
00525    * @return index on success, -1 otherwise
00526    */
00527   public int lookupLong(long n) {
00528     for(int i=1; i < index; i++) {
00529       if(constants[i] instanceof ConstantLong) {
00530     ConstantLong c = (ConstantLong)constants[i];
00531 
00532     if(c.getBytes() == n)
00533       return i;
00534       }
00535     }
00536 
00537     return -1;
00538   }  
00539   public int lookupMethodref(MethodGen method) {
00540     return lookupMethodref(method.getClassName(), method.getMethodName(),
00541               method.getMethodSignature());
00542   }  
00543   /** 
00544    * Look for ConstantMethodref in ConstantPool.
00545    *
00546    * @param class_name Where to find method
00547    * @param method_name Guess what
00548    * @param signature return and argument types
00549    * @return index on success, -1 otherwise
00550    */
00551   public int lookupMethodref(String class_name, String method_name, String signature) {
00552     Index index = (Index)cp_table.get(class_name + ":" + method_name + ":" + signature);
00553     return (index != null)? index.index : -1;
00554   }  
00555   /** 
00556    * Look for ConstantNameAndType in ConstantPool.
00557    *
00558    * @param name of variable/method
00559    * @param signature of variable/method
00560    * @return index on success, -1 otherwise
00561    */
00562   public int lookupNameAndType(String name, String signature) {
00563     Index index = (Index)n_a_t_table.get(name + ":" + signature);
00564     return (index != null)? index.index : -1;
00565   }  
00566   /** 
00567    * Look for ConstantString in ConstantPool containing String `str'.
00568    *
00569    * @param str String to search for
00570    * @return index on success, -1 otherwise
00571    */
00572   public int lookupString(String str) {
00573     Index index = (Index)string_table.get(str);
00574     return (index != null)? index.index : -1;
00575   }  
00576   /** 
00577    * Look for ConstantUtf8 in ConstantPool.
00578    *
00579    * @param n Utf8 string to look for
00580    * @return index on success, -1 otherwise
00581    */
00582   public int lookupUtf8(String n) {
00583     for(int i=1; i < index; i++) {
00584       if(constants[i] instanceof ConstantUtf8) {
00585     ConstantUtf8 c = (ConstantUtf8)constants[i];
00586 
00587     if(c.getBytes().equals(n))
00588       return i;
00589       }
00590     }
00591 
00592     return -1;
00593   }  
00594   /**
00595    * Use with care!
00596    *
00597    * @param i index in constant pool
00598    * @param c new constant pool entry at index i
00599    */
00600   public void setConstant(int i, Constant c) { constants[i] = c; }  
00601   /**
00602    * @return String representation.
00603    */
00604   public String toString() {
00605     StringBuffer buf = new StringBuffer();
00606 
00607     for(int i=1; i < index; i++)
00608       buf.append(i + ")" + constants[i] + "\n");
00609 
00610     return buf.toString();
00611   }  
00612 }

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