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