jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ConstantPoolGen.java
changeset 25868 686eef1e7a79
parent 12457 c348e06f0e82
child 44797 8b3b3b911b8a
equal deleted inserted replaced
25867:3d364c870c90 25868:686eef1e7a79
       
     1 /*
       
     2  * reserved comment block
       
     3  * DO NOT REMOVE OR ALTER!
       
     4  */
       
     5 package com.sun.org.apache.bcel.internal.generic;
       
     6 
       
     7 /* ====================================================================
       
     8  * The Apache Software License, Version 1.1
       
     9  *
       
    10  * Copyright (c) 2001 The Apache Software Foundation.  All rights
       
    11  * reserved.
       
    12  *
       
    13  * Redistribution and use in source and binary forms, with or without
       
    14  * modification, are permitted provided that the following conditions
       
    15  * are met:
       
    16  *
       
    17  * 1. Redistributions of source code must retain the above copyright
       
    18  *    notice, this list of conditions and the following disclaimer.
       
    19  *
       
    20  * 2. Redistributions in binary form must reproduce the above copyright
       
    21  *    notice, this list of conditions and the following disclaimer in
       
    22  *    the documentation and/or other materials provided with the
       
    23  *    distribution.
       
    24  *
       
    25  * 3. The end-user documentation included with the redistribution,
       
    26  *    if any, must include the following acknowledgment:
       
    27  *       "This product includes software developed by the
       
    28  *        Apache Software Foundation (http://www.apache.org/)."
       
    29  *    Alternately, this acknowledgment may appear in the software itself,
       
    30  *    if and wherever such third-party acknowledgments normally appear.
       
    31  *
       
    32  * 4. The names "Apache" and "Apache Software Foundation" and
       
    33  *    "Apache BCEL" must not be used to endorse or promote products
       
    34  *    derived from this software without prior written permission. For
       
    35  *    written permission, please contact apache@apache.org.
       
    36  *
       
    37  * 5. Products derived from this software may not be called "Apache",
       
    38  *    "Apache BCEL", nor may "Apache" appear in their name, without
       
    39  *    prior written permission of the Apache Software Foundation.
       
    40  *
       
    41  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
       
    42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
       
    43  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       
    44  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
       
    45  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    46  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    47  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
       
    48  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
       
    49  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
       
    50  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
       
    51  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
       
    52  * SUCH DAMAGE.
       
    53  * ====================================================================
       
    54  *
       
    55  * This software consists of voluntary contributions made by many
       
    56  * individuals on behalf of the Apache Software Foundation.  For more
       
    57  * information on the Apache Software Foundation, please see
       
    58  * <http://www.apache.org/>.
       
    59  */
       
    60 
       
    61 import com.sun.org.apache.bcel.internal.Constants;
       
    62 import com.sun.org.apache.bcel.internal.classfile.*;
       
    63 import java.util.HashMap;
       
    64 
       
    65 /**
       
    66  * This class is used to build up a constant pool. The user adds
       
    67  * constants via `addXXX' methods, `addString', `addClass',
       
    68  * etc.. These methods return an index into the constant
       
    69  * pool. Finally, `getFinalConstantPool()' returns the constant pool
       
    70  * built up. Intermediate versions of the constant pool can be
       
    71  * obtained with `getConstantPool()'. A constant pool has capacity for
       
    72  * Constants.MAX_SHORT entries. Note that the first (0) is used by the
       
    73  * JVM and that Double and Long constants need two slots.
       
    74  *
       
    75  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
       
    76  * @see Constant
       
    77  */
       
    78 public class ConstantPoolGen implements java.io.Serializable {
       
    79   protected int        size      = 1024; // Inital size, sufficient in most cases
       
    80   protected Constant[] constants = new Constant[size];
       
    81   protected int        index     = 1; // First entry (0) used by JVM
       
    82 
       
    83   private static final String METHODREF_DELIM  = ":";
       
    84   private static final String IMETHODREF_DELIM = "#";
       
    85   private static final String FIELDREF_DELIM   = "&";
       
    86   private static final String NAT_DELIM        = "%";
       
    87 
       
    88   private static class Index implements java.io.Serializable {
       
    89     int index;
       
    90     Index(int i) { index = i; }
       
    91   }
       
    92 
       
    93   /**
       
    94    * Initialize with given array of constants.
       
    95    *
       
    96    * @param c array of given constants, new ones will be appended
       
    97    */
       
    98   public ConstantPoolGen(Constant[] cs) {
       
    99     if(cs.length > size) {
       
   100       size      = cs.length;
       
   101       constants = new Constant[size];
       
   102     }
       
   103 
       
   104     System.arraycopy(cs, 0, constants, 0, cs.length);
       
   105 
       
   106     if(cs.length > 0)
       
   107       index = cs.length;
       
   108 
       
   109     for(int i=1; i < index; i++) {
       
   110       Constant c = constants[i];
       
   111 
       
   112       if(c instanceof ConstantString) {
       
   113         ConstantString s  = (ConstantString)c;
       
   114         ConstantUtf8   u8 = (ConstantUtf8)constants[s.getStringIndex()];
       
   115 
       
   116         string_table.put(u8.getBytes(), new Index(i));
       
   117       } else if(c instanceof ConstantClass) {
       
   118         ConstantClass s  = (ConstantClass)c;
       
   119         ConstantUtf8  u8 = (ConstantUtf8)constants[s.getNameIndex()];
       
   120 
       
   121         class_table.put(u8.getBytes(), new Index(i));
       
   122       } else if(c instanceof ConstantNameAndType) {
       
   123         ConstantNameAndType n    = (ConstantNameAndType)c;
       
   124         ConstantUtf8        u8   = (ConstantUtf8)constants[n.getNameIndex()];
       
   125         ConstantUtf8        u8_2 = (ConstantUtf8)constants[n.getSignatureIndex()];
       
   126 
       
   127         n_a_t_table.put(u8.getBytes() + NAT_DELIM + u8_2.getBytes(), new Index(i));
       
   128        } else if(c instanceof ConstantUtf8) {
       
   129          ConstantUtf8 u = (ConstantUtf8)c;
       
   130 
       
   131          utf8_table.put(u.getBytes(), new Index(i));
       
   132       } else if(c instanceof ConstantCP) {
       
   133         ConstantCP          m     = (ConstantCP)c;
       
   134         ConstantClass       clazz = (ConstantClass)constants[m.getClassIndex()];
       
   135         ConstantNameAndType n     = (ConstantNameAndType)constants[m.getNameAndTypeIndex()];
       
   136 
       
   137         ConstantUtf8 u8         = (ConstantUtf8)constants[clazz.getNameIndex()];
       
   138         String       class_name = u8.getBytes().replace('/', '.');
       
   139 
       
   140         u8 = (ConstantUtf8)constants[n.getNameIndex()];
       
   141         String method_name = u8.getBytes();
       
   142 
       
   143         u8 = (ConstantUtf8)constants[n.getSignatureIndex()];
       
   144         String signature = u8.getBytes();
       
   145 
       
   146         String delim = METHODREF_DELIM;
       
   147 
       
   148         if(c instanceof ConstantInterfaceMethodref)
       
   149           delim = IMETHODREF_DELIM;
       
   150         else if(c instanceof ConstantFieldref)
       
   151           delim = FIELDREF_DELIM;
       
   152 
       
   153         cp_table.put(class_name + delim + method_name + delim + signature, new Index(i));
       
   154       }
       
   155     }
       
   156   }
       
   157 
       
   158   /**
       
   159    * Initialize with given constant pool.
       
   160    */
       
   161   public ConstantPoolGen(ConstantPool cp) {
       
   162     this(cp.getConstantPool());
       
   163   }
       
   164 
       
   165   /**
       
   166    * Create empty constant pool.
       
   167    */
       
   168   public ConstantPoolGen() {}
       
   169 
       
   170   /** Resize internal array of constants.
       
   171    */
       
   172   protected void adjustSize() {
       
   173     if(index + 3 >= size) {
       
   174       Constant[] cs = constants;
       
   175 
       
   176       size      *= 2;
       
   177       constants  = new Constant[size];
       
   178       System.arraycopy(cs, 0, constants, 0, index);
       
   179     }
       
   180   }
       
   181 
       
   182   private HashMap string_table = new HashMap();
       
   183 
       
   184   /**
       
   185    * Look for ConstantString in ConstantPool containing String `str'.
       
   186    *
       
   187    * @param str String to search for
       
   188    * @return index on success, -1 otherwise
       
   189    */
       
   190   public int lookupString(String str) {
       
   191     Index index = (Index)string_table.get(str);
       
   192     return (index != null)? index.index : -1;
       
   193   }
       
   194 
       
   195   /**
       
   196    * Add a new String constant to the ConstantPool, if it is not already in there.
       
   197    *
       
   198    * @param str String to add
       
   199    * @return index of entry
       
   200    */
       
   201   public int addString(String str) {
       
   202     int ret;
       
   203 
       
   204     if((ret = lookupString(str)) != -1)
       
   205       return ret; // Already in CP
       
   206 
       
   207     int utf8 = addUtf8(str);
       
   208 
       
   209     adjustSize();
       
   210 
       
   211     ConstantString s  = new ConstantString(utf8);
       
   212 
       
   213     ret = index;
       
   214     constants[index++] = s;
       
   215 
       
   216     string_table.put(str, new Index(ret));
       
   217 
       
   218     return ret;
       
   219   }
       
   220 
       
   221   private HashMap class_table = new HashMap();
       
   222 
       
   223   /**
       
   224    * Look for ConstantClass in ConstantPool named `str'.
       
   225    *
       
   226    * @param str String to search for
       
   227    * @return index on success, -1 otherwise
       
   228    */
       
   229   public int lookupClass(String str) {
       
   230     Index index = (Index)class_table.get(str.replace('.', '/'));
       
   231     return (index != null)? index.index : -1;
       
   232   }
       
   233 
       
   234   private int addClass_(String clazz) {
       
   235     int    ret;
       
   236 
       
   237     if((ret = lookupClass(clazz)) != -1)
       
   238       return ret; // Already in CP
       
   239 
       
   240     adjustSize();
       
   241 
       
   242     ConstantClass c = new ConstantClass(addUtf8(clazz));
       
   243 
       
   244     ret = index;
       
   245     constants[index++] = c;
       
   246 
       
   247     class_table.put(clazz, new Index(ret));
       
   248 
       
   249     return ret;
       
   250   }
       
   251 
       
   252   /**
       
   253    * Add a new Class reference to the ConstantPool, if it is not already in there.
       
   254    *
       
   255    * @param str Class to add
       
   256    * @return index of entry
       
   257    */
       
   258   public int addClass(String str) {
       
   259     return addClass_(str.replace('.', '/'));
       
   260   }
       
   261 
       
   262   /**
       
   263    * Add a new Class reference to the ConstantPool for a given type.
       
   264    *
       
   265    * @param str Class to add
       
   266    * @return index of entry
       
   267    */
       
   268   public int addClass(ObjectType type) {
       
   269     return addClass(type.getClassName());
       
   270   }
       
   271 
       
   272   /**
       
   273    * Add a reference to an array class (e.g. String[][]) as needed by MULTIANEWARRAY
       
   274    * instruction, e.g. to the ConstantPool.
       
   275    *
       
   276    * @param type type of array class
       
   277    * @return index of entry
       
   278    */
       
   279   public int addArrayClass(ArrayType type) {
       
   280     return addClass_(type.getSignature());
       
   281   }
       
   282 
       
   283   /**
       
   284    * Look for ConstantInteger in ConstantPool.
       
   285    *
       
   286    * @param n integer number to look for
       
   287    * @return index on success, -1 otherwise
       
   288    */
       
   289   public int lookupInteger(int n) {
       
   290     for(int i=1; i < index; i++) {
       
   291       if(constants[i] instanceof ConstantInteger) {
       
   292         ConstantInteger c = (ConstantInteger)constants[i];
       
   293 
       
   294         if(c.getBytes() == n)
       
   295           return i;
       
   296       }
       
   297     }
       
   298 
       
   299     return -1;
       
   300   }
       
   301 
       
   302   /**
       
   303    * Add a new Integer constant to the ConstantPool, if it is not already in there.
       
   304    *
       
   305    * @param n integer number to add
       
   306    * @return index of entry
       
   307    */
       
   308   public int addInteger(int n) {
       
   309     int  ret;
       
   310 
       
   311     if((ret = lookupInteger(n)) != -1)
       
   312       return ret; // Already in CP
       
   313 
       
   314     adjustSize();
       
   315 
       
   316     ret = index;
       
   317     constants[index++] = new ConstantInteger(n);
       
   318 
       
   319     return ret;
       
   320   }
       
   321 
       
   322   /**
       
   323    * Look for ConstantFloat in ConstantPool.
       
   324    *
       
   325    * @param n Float number to look for
       
   326    * @return index on success, -1 otherwise
       
   327    */
       
   328   public int lookupFloat(float n) {
       
   329     int bits = Float.floatToIntBits(n);
       
   330 
       
   331     for(int i=1; i < index; i++) {
       
   332       if(constants[i] instanceof ConstantFloat) {
       
   333         ConstantFloat c = (ConstantFloat)constants[i];
       
   334 
       
   335         if(Float.floatToIntBits(c.getBytes()) == bits)
       
   336           return i;
       
   337       }
       
   338     }
       
   339 
       
   340     return -1;
       
   341   }
       
   342 
       
   343   /**
       
   344    * Add a new Float constant to the ConstantPool, if it is not already in there.
       
   345    *
       
   346    * @param n Float number to add
       
   347    * @return index of entry
       
   348    */
       
   349   public int addFloat(float n) {
       
   350     int  ret;
       
   351 
       
   352     if((ret = lookupFloat(n)) != -1)
       
   353       return ret; // Already in CP
       
   354 
       
   355     adjustSize();
       
   356 
       
   357     ret = index;
       
   358     constants[index++] = new ConstantFloat(n);
       
   359 
       
   360     return ret;
       
   361   }
       
   362 
       
   363   private HashMap utf8_table = new HashMap();
       
   364 
       
   365   /**
       
   366    * Look for ConstantUtf8 in ConstantPool.
       
   367    *
       
   368    * @param n Utf8 string to look for
       
   369    * @return index on success, -1 otherwise
       
   370    */
       
   371   public int lookupUtf8(String n) {
       
   372     Index index = (Index)utf8_table.get(n);
       
   373 
       
   374     return (index != null)? index.index : -1;
       
   375   }
       
   376 
       
   377   /**
       
   378    * Add a new Utf8 constant to the ConstantPool, if it is not already in there.
       
   379    *
       
   380    * @param n Utf8 string to add
       
   381    * @return index of entry
       
   382    */
       
   383   public int addUtf8(String n) {
       
   384     int  ret;
       
   385 
       
   386     if((ret = lookupUtf8(n)) != -1)
       
   387       return ret; // Already in CP
       
   388 
       
   389     adjustSize();
       
   390 
       
   391     ret = index;
       
   392     constants[index++] = new ConstantUtf8(n);
       
   393 
       
   394     utf8_table.put(n, new Index(ret));
       
   395 
       
   396     return ret;
       
   397   }
       
   398 
       
   399   /**
       
   400    * Look for ConstantLong in ConstantPool.
       
   401    *
       
   402    * @param n Long number to look for
       
   403    * @return index on success, -1 otherwise
       
   404    */
       
   405   public int lookupLong(long n) {
       
   406     for(int i=1; i < index; i++) {
       
   407       if(constants[i] instanceof ConstantLong) {
       
   408         ConstantLong c = (ConstantLong)constants[i];
       
   409 
       
   410         if(c.getBytes() == n)
       
   411           return i;
       
   412       }
       
   413     }
       
   414 
       
   415     return -1;
       
   416   }
       
   417 
       
   418   /**
       
   419    * Add a new long constant to the ConstantPool, if it is not already in there.
       
   420    *
       
   421    * @param n Long number to add
       
   422    * @return index of entry
       
   423    */
       
   424   public int addLong(long n) {
       
   425     int  ret;
       
   426 
       
   427     if((ret = lookupLong(n)) != -1)
       
   428       return ret; // Already in CP
       
   429 
       
   430     adjustSize();
       
   431 
       
   432     ret = index;
       
   433     constants[index] = new ConstantLong(n);
       
   434     index += 2;   // Wastes one entry according to spec
       
   435 
       
   436     return ret;
       
   437   }
       
   438 
       
   439   /**
       
   440    * Look for ConstantDouble in ConstantPool.
       
   441    *
       
   442    * @param n Double number to look for
       
   443    * @return index on success, -1 otherwise
       
   444    */
       
   445   public int lookupDouble(double n) {
       
   446     long bits = Double.doubleToLongBits(n);
       
   447 
       
   448     for(int i=1; i < index; i++) {
       
   449       if(constants[i] instanceof ConstantDouble) {
       
   450         ConstantDouble c = (ConstantDouble)constants[i];
       
   451 
       
   452         if(Double.doubleToLongBits(c.getBytes()) == bits)
       
   453           return i;
       
   454       }
       
   455     }
       
   456 
       
   457     return -1;
       
   458   }
       
   459 
       
   460   /**
       
   461    * Add a new double constant to the ConstantPool, if it is not already in there.
       
   462    *
       
   463    * @param n Double number to add
       
   464    * @return index of entry
       
   465    */
       
   466   public int addDouble(double n) {
       
   467     int  ret;
       
   468 
       
   469     if((ret = lookupDouble(n)) != -1)
       
   470       return ret; // Already in CP
       
   471 
       
   472     adjustSize();
       
   473 
       
   474     ret = index;
       
   475     constants[index] = new ConstantDouble(n);
       
   476     index += 2;   // Wastes one entry according to spec
       
   477 
       
   478     return ret;
       
   479   }
       
   480 
       
   481   private HashMap n_a_t_table = new HashMap();
       
   482 
       
   483   /**
       
   484    * Look for ConstantNameAndType in ConstantPool.
       
   485    *
       
   486    * @param name of variable/method
       
   487    * @param signature of variable/method
       
   488    * @return index on success, -1 otherwise
       
   489    */
       
   490   public int lookupNameAndType(String name, String signature) {
       
   491     Index index = (Index)n_a_t_table.get(name + NAT_DELIM + signature);
       
   492     return (index != null)? index.index : -1;
       
   493   }
       
   494 
       
   495   /**
       
   496    * Add a new NameAndType constant to the ConstantPool if it is not already
       
   497    * in there.
       
   498    *
       
   499    * @param n NameAndType string to add
       
   500    * @return index of entry
       
   501    */
       
   502   public int addNameAndType(String name, String signature) {
       
   503     int  ret;
       
   504     int  name_index, signature_index;
       
   505 
       
   506     if((ret = lookupNameAndType(name, signature)) != -1)
       
   507       return ret; // Already in CP
       
   508 
       
   509     adjustSize();
       
   510 
       
   511     name_index      = addUtf8(name);
       
   512     signature_index = addUtf8(signature);
       
   513     ret = index;
       
   514     constants[index++] = new ConstantNameAndType(name_index, signature_index);
       
   515 
       
   516     n_a_t_table.put(name + NAT_DELIM + signature, new Index(ret));
       
   517     return ret;
       
   518   }
       
   519 
       
   520   private HashMap cp_table = new HashMap();
       
   521 
       
   522   /**
       
   523    * Look for ConstantMethodref in ConstantPool.
       
   524    *
       
   525    * @param class_name Where to find method
       
   526    * @param method_name Guess what
       
   527    * @param signature return and argument types
       
   528    * @return index on success, -1 otherwise
       
   529    */
       
   530   public int lookupMethodref(String class_name, String method_name, String signature) {
       
   531     Index index = (Index)cp_table.get(class_name + METHODREF_DELIM + method_name +
       
   532                                       METHODREF_DELIM + signature);
       
   533     return (index != null)? index.index : -1;
       
   534   }
       
   535 
       
   536   public int lookupMethodref(MethodGen method) {
       
   537     return lookupMethodref(method.getClassName(), method.getName(),
       
   538                           method.getSignature());
       
   539   }
       
   540 
       
   541   /**
       
   542    * Add a new Methodref constant to the ConstantPool, if it is not already
       
   543    * in there.
       
   544    *
       
   545    * @param n Methodref string to add
       
   546    * @return index of entry
       
   547    */
       
   548   public int addMethodref(String class_name, String method_name, String signature) {
       
   549     int  ret, class_index, name_and_type_index;
       
   550 
       
   551     if((ret = lookupMethodref(class_name, method_name, signature)) != -1)
       
   552       return ret; // Already in CP
       
   553 
       
   554     adjustSize();
       
   555 
       
   556     name_and_type_index = addNameAndType(method_name, signature);
       
   557     class_index         = addClass(class_name);
       
   558     ret = index;
       
   559     constants[index++] = new ConstantMethodref(class_index, name_and_type_index);
       
   560 
       
   561     cp_table.put(class_name + METHODREF_DELIM + method_name +
       
   562                  METHODREF_DELIM + signature, new Index(ret));
       
   563 
       
   564     return ret;
       
   565   }
       
   566 
       
   567   public int addMethodref(MethodGen method) {
       
   568     return addMethodref(method.getClassName(), method.getName(),
       
   569                         method.getSignature());
       
   570   }
       
   571 
       
   572   /**
       
   573    * Look for ConstantInterfaceMethodref in ConstantPool.
       
   574    *
       
   575    * @param class_name Where to find method
       
   576    * @param method_name Guess what
       
   577    * @param signature return and argument types
       
   578    * @return index on success, -1 otherwise
       
   579    */
       
   580   public int lookupInterfaceMethodref(String class_name, String method_name, String signature) {
       
   581     Index index = (Index)cp_table.get(class_name + IMETHODREF_DELIM + method_name +
       
   582                                       IMETHODREF_DELIM + signature);
       
   583     return (index != null)? index.index : -1;
       
   584   }
       
   585 
       
   586   public int lookupInterfaceMethodref(MethodGen method) {
       
   587     return lookupInterfaceMethodref(method.getClassName(), method.getName(),
       
   588                                     method.getSignature());
       
   589   }
       
   590 
       
   591   /**
       
   592    * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already
       
   593    * in there.
       
   594    *
       
   595    * @param n InterfaceMethodref string to add
       
   596    * @return index of entry
       
   597    */
       
   598   public int addInterfaceMethodref(String class_name, String method_name, String signature) {
       
   599     int ret, class_index, name_and_type_index;
       
   600 
       
   601     if((ret = lookupInterfaceMethodref(class_name, method_name, signature)) != -1)
       
   602       return ret; // Already in CP
       
   603 
       
   604     adjustSize();
       
   605 
       
   606     class_index         = addClass(class_name);
       
   607     name_and_type_index = addNameAndType(method_name, signature);
       
   608     ret = index;
       
   609     constants[index++] = new ConstantInterfaceMethodref(class_index, name_and_type_index);
       
   610 
       
   611     cp_table.put(class_name + IMETHODREF_DELIM + method_name +
       
   612                  IMETHODREF_DELIM + signature, new Index(ret));
       
   613 
       
   614     return ret;
       
   615   }
       
   616 
       
   617   public int addInterfaceMethodref(MethodGen method) {
       
   618     return addInterfaceMethodref(method.getClassName(), method.getName(),
       
   619                                  method.getSignature());
       
   620   }
       
   621 
       
   622   /**
       
   623    * Look for ConstantFieldref in ConstantPool.
       
   624    *
       
   625    * @param class_name Where to find method
       
   626    * @param field_name Guess what
       
   627    * @param signature return and argument types
       
   628    * @return index on success, -1 otherwise
       
   629    */
       
   630   public int lookupFieldref(String class_name, String field_name, String signature) {
       
   631     Index index = (Index)cp_table.get(class_name + FIELDREF_DELIM + field_name +
       
   632                                       FIELDREF_DELIM + signature);
       
   633     return (index != null)? index.index : -1;
       
   634   }
       
   635 
       
   636   /**
       
   637    * Add a new Fieldref constant to the ConstantPool, if it is not already
       
   638    * in there.
       
   639    *
       
   640    * @param n Fieldref string to add
       
   641    * @return index of entry
       
   642    */
       
   643   public int addFieldref(String class_name, String field_name, String signature) {
       
   644     int  ret;
       
   645     int  class_index, name_and_type_index;
       
   646 
       
   647     if((ret = lookupFieldref(class_name, field_name, signature)) != -1)
       
   648       return ret; // Already in CP
       
   649 
       
   650     adjustSize();
       
   651 
       
   652     class_index         = addClass(class_name);
       
   653     name_and_type_index = addNameAndType(field_name, signature);
       
   654     ret = index;
       
   655     constants[index++] = new ConstantFieldref(class_index, name_and_type_index);
       
   656 
       
   657     cp_table.put(class_name + FIELDREF_DELIM + field_name + FIELDREF_DELIM + signature, new Index(ret));
       
   658 
       
   659     return ret;
       
   660   }
       
   661 
       
   662   /**
       
   663    * @param i index in constant pool
       
   664    * @return constant pool entry at index i
       
   665    */
       
   666   public Constant getConstant(int i) { return constants[i]; }
       
   667 
       
   668   /**
       
   669    * Use with care!
       
   670    *
       
   671    * @param i index in constant pool
       
   672    * @param c new constant pool entry at index i
       
   673    */
       
   674   public void setConstant(int i, Constant c) { constants[i] = c; }
       
   675 
       
   676   /**
       
   677    * @return intermediate constant pool
       
   678    */
       
   679   public ConstantPool getConstantPool() {
       
   680     return new ConstantPool(constants);
       
   681   }
       
   682 
       
   683   /**
       
   684    * @return current size of constant pool
       
   685    */
       
   686   public int getSize() {
       
   687     return index;
       
   688   }
       
   689 
       
   690   /**
       
   691    * @return constant pool with proper length
       
   692    */
       
   693   public ConstantPool getFinalConstantPool() {
       
   694     Constant[] cs = new Constant[index];
       
   695 
       
   696     System.arraycopy(constants, 0, cs, 0, index);
       
   697 
       
   698     return new ConstantPool(cs);
       
   699   }
       
   700 
       
   701   /**
       
   702    * @return String representation.
       
   703    */
       
   704   public String toString() {
       
   705     StringBuffer buf = new StringBuffer();
       
   706 
       
   707     for(int i=1; i < index; i++)
       
   708       buf.append(i + ")" + constants[i] + "\n");
       
   709 
       
   710     return buf.toString();
       
   711   }
       
   712 
       
   713   /** Import constant from another ConstantPool and return new index.
       
   714    */
       
   715   public int addConstant(Constant c, ConstantPoolGen cp) {
       
   716     Constant[] constants = cp.getConstantPool().getConstantPool();
       
   717 
       
   718     switch(c.getTag()) {
       
   719     case Constants.CONSTANT_String: {
       
   720       ConstantString s  = (ConstantString)c;
       
   721       ConstantUtf8   u8 = (ConstantUtf8)constants[s.getStringIndex()];
       
   722 
       
   723       return addString(u8.getBytes());
       
   724     }
       
   725 
       
   726     case Constants.CONSTANT_Class: {
       
   727       ConstantClass s  = (ConstantClass)c;
       
   728       ConstantUtf8  u8 = (ConstantUtf8)constants[s.getNameIndex()];
       
   729 
       
   730       return addClass(u8.getBytes());
       
   731     }
       
   732 
       
   733     case Constants.CONSTANT_NameAndType: {
       
   734       ConstantNameAndType n    = (ConstantNameAndType)c;
       
   735       ConstantUtf8        u8   = (ConstantUtf8)constants[n.getNameIndex()];
       
   736       ConstantUtf8        u8_2 = (ConstantUtf8)constants[n.getSignatureIndex()];
       
   737 
       
   738       return addNameAndType(u8.getBytes(), u8_2.getBytes());
       
   739     }
       
   740 
       
   741     case Constants.CONSTANT_Utf8:
       
   742       return addUtf8(((ConstantUtf8)c).getBytes());
       
   743 
       
   744     case Constants.CONSTANT_Double:
       
   745       return addDouble(((ConstantDouble)c).getBytes());
       
   746 
       
   747     case Constants.CONSTANT_Float:
       
   748       return addFloat(((ConstantFloat)c).getBytes());
       
   749 
       
   750     case Constants.CONSTANT_Long:
       
   751       return addLong(((ConstantLong)c).getBytes());
       
   752 
       
   753     case Constants.CONSTANT_Integer:
       
   754       return addInteger(((ConstantInteger)c).getBytes());
       
   755 
       
   756     case Constants.CONSTANT_InterfaceMethodref: case Constants.CONSTANT_Methodref:
       
   757     case Constants.CONSTANT_Fieldref: {
       
   758       ConstantCP          m     = (ConstantCP)c;
       
   759       ConstantClass       clazz = (ConstantClass)constants[m.getClassIndex()];
       
   760       ConstantNameAndType n     = (ConstantNameAndType)constants[m.getNameAndTypeIndex()];
       
   761       ConstantUtf8 u8           = (ConstantUtf8)constants[clazz.getNameIndex()];
       
   762       String       class_name   = u8.getBytes().replace('/', '.');
       
   763 
       
   764       u8 = (ConstantUtf8)constants[n.getNameIndex()];
       
   765       String name = u8.getBytes();
       
   766 
       
   767       u8 = (ConstantUtf8)constants[n.getSignatureIndex()];
       
   768       String signature = u8.getBytes();
       
   769 
       
   770       switch(c.getTag()) {
       
   771       case Constants.CONSTANT_InterfaceMethodref:
       
   772         return addInterfaceMethodref(class_name, name, signature);
       
   773 
       
   774       case Constants.CONSTANT_Methodref:
       
   775         return addMethodref(class_name, name, signature);
       
   776 
       
   777       case Constants.CONSTANT_Fieldref:
       
   778         return addFieldref(class_name, name, signature);
       
   779 
       
   780       default: // Never reached
       
   781         throw new RuntimeException("Unknown constant type " + c);
       
   782       }
       
   783     }
       
   784 
       
   785     default: // Never reached
       
   786       throw new RuntimeException("Unknown constant type " + c);
       
   787     }
       
   788   }
       
   789 }