    View Javadoc
    1   package org.apache.bcel.classfile;
    2
    3   /* ====================================================================
    4    * The Apache Software License, Version 1.1
    5    *
    6    * Copyright (c) 2001 The Apache Software Foundation.  All rights
    7    * reserved.
    8    *
    9    * Redistribution and use in source and binary forms, with or without
    10   * modification, are permitted provided that the following conditions
    11   * are met:
    12   *
    13   * 1. Redistributions of source code must retain the above copyright
    14   *    notice, this list of conditions and the following disclaimer.
    15   *
    16   * 2. Redistributions in binary form must reproduce the above copyright
    17   *    notice, this list of conditions and the following disclaimer in
    18   *    the documentation and/or other materials provided with the
    19   *    distribution.
    20   *
    21   * 3. The end-user documentation included with the redistribution,
    22   *    if any, must include the following acknowledgment:
    23   *       "This product includes software developed by the
    24   *        Apache Software Foundation (http://www.apache.org/)."
    25   *    Alternately, this acknowledgment may appear in the software itself,
    26   *    if and wherever such third-party acknowledgments normally appear.
    27   *
    28   * 4. The names "Apache" and "Apache Software Foundation" and
    29   *    "Apache BCEL" must not be used to endorse or promote products
    30   *    derived from this software without prior written permission. For
    31   *    written permission, please contact apache@apache.org.
    32   *
    33   * 5. Products derived from this software may not be called "Apache",
    34   *    "Apache BCEL", nor may "Apache" appear in their name, without
    35   *    prior written permission of the Apache Software Foundation.
    36   *
    37   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
    38   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    39   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    40   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
    41   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    42   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    43   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
    44   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    45   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    46   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    47   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    48   * SUCH DAMAGE.
    49   * ====================================================================
    50   *
    51   * This software consists of voluntary contributions made by many
    52   * individuals on behalf of the Apache Software Foundation.  For more
    53   * information on the Apache Software Foundation, please see
    54   * <http://www.apache.org/>;.
    55   */
    56
    57  import  org.apache.bcel.Constants;
    58  import  java.io.*;
    59
    60  /***
    61   * This class represents the constant pool, i.e., a table of constants, of
    62   * a parsed classfile. It may contain null references, due to the JVM
    63   * specification that skips an entry after an 8-byte constant (double,
    64   * long) entry.  Those interested in generating constant pools
    65   * programatically should see <a href="../generic/ConstantPoolGen.html">
    66   * ConstantPoolGen</a>.
    67
    68   * @version $Id: ConstantPool.java,v 1.6 2002/07/11 19:39:04 mdahm Exp $
    69   * @see     Constant
    70   * @see     org.apache.bcel.generic.ConstantPoolGen
    71   * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
    72   */
    73  public class ConstantPool implements Cloneable, Node, Serializable {
    74    private int        constant_pool_count;
    75    private Constant[] constant_pool;
    76
    77    /***
    78     * @param constant_pool Array of constants
    79     */
    80    public ConstantPool(Constant[] constant_pool)
    81    {
    82      setConstantPool(constant_pool);
    83    }
    84
    85    /***
    86     * Read constants from given file stream.
    87     *
    88     * @param file Input stream
    89     * @throws IOException
    90     * @throws ClassFormatException
    91     */
    92    ConstantPool(DataInputStream file) throws IOException, ClassFormatException
    93    {
    94      byte tag;
    95
    96      constant_pool_count = file.readUnsignedShort();
    97      constant_pool       = new Constant[constant_pool_count];
    98
    99      /* constant_pool[0] is unused by the compiler and may be used freely
    100      * by the implementation.
    101      */
    102     for(int i=1; i < constant_pool_count; i++) {
    103       constant_pool[i] = Constant.readConstant(file);
    104
    105       /* Quote from the JVM specification:
    106        * "All eight byte constants take up two spots in the constant pool.
    107        * If this is the n'th byte in the constant pool, then the next item
    108        * will be numbered n+2"
    109        *
    110        * Thus we have to increment the index counter.
    111        */
    112       tag = constant_pool[i].getTag();
    113       if((tag == Constants.CONSTANT_Double) || (tag == Constants.CONSTANT_Long))
    114 	i++;
    115     }
    116   }
    117
    118   /***
    119    * Called by objects that are traversing the nodes of the tree implicitely
    120    * defined by the contents of a Java class. I.e., the hierarchy of methods,
    121    * fields, attributes, etc. spawns a tree of objects.
    122    *
    123    * @param v Visitor object
    124    */
    125   public void accept(Visitor v) {
    126     v.visitConstantPool(this);
    127   }
    128
    129   /***
    130    * Resolve constant to a string representation.
    131    *
    132    * @param  constant Constant to be printed
    133    * @return String representation
    134    */
    135   public String constantToString(Constant c)
    136        throws ClassFormatException
    137   {
    138     String   str;
    139     int      i;
    140     byte     tag = c.getTag();
    141
    142     switch(tag) {
    143     case Constants.CONSTANT_Class:
    144       i   = ((ConstantClass)c).getNameIndex();
    145       c   = getConstant(i, Constants.CONSTANT_Utf8);
    146       str = Utility.compactClassName(((ConstantUtf8)c).getBytes(), false);
    147       break;
    148
    149     case Constants.CONSTANT_String:
    150       i   = ((ConstantString)c).getStringIndex();
    151       c   = getConstant(i, Constants.CONSTANT_Utf8);
    152       str = "\"" + escape(((ConstantUtf8)c).getBytes()) + "\"";
    153       break;
    154
    155     case Constants.CONSTANT_Utf8:    str = ((ConstantUtf8)c).getBytes();         break;
    156     case Constants.CONSTANT_Double:  str = "" + ((ConstantDouble)c).getBytes();  break;
    157     case Constants.CONSTANT_Float:   str = "" + ((ConstantFloat)c).getBytes();   break;
    158     case Constants.CONSTANT_Long:    str = "" + ((ConstantLong)c).getBytes();    break;
    159     case Constants.CONSTANT_Integer: str = "" + ((ConstantInteger)c).getBytes(); break;
    160
    161     case Constants.CONSTANT_NameAndType:
    162       str = (constantToString(((ConstantNameAndType)c).getNameIndex(),
    163 			      Constants.CONSTANT_Utf8) + " " +
    164 	     constantToString(((ConstantNameAndType)c).getSignatureIndex(),
    165 			      Constants.CONSTANT_Utf8));
    166       break;
    167
    168     case Constants.CONSTANT_InterfaceMethodref: case Constants.CONSTANT_Methodref:
    169     case Constants.CONSTANT_Fieldref:
    170       str = (constantToString(((ConstantCP)c).getClassIndex(),
    171 			      Constants.CONSTANT_Class) + "." +
    172 	     constantToString(((ConstantCP)c).getNameAndTypeIndex(),
    173 			      Constants.CONSTANT_NameAndType));
    174       break;
    175
    176     default: // Never reached
    177       throw new RuntimeException("Unknown constant type " + tag);
    178     }
    179
    180     return str;
    181   }
    182
    183   private static final String escape(String str) {
    184     int          len = str.length();
    185     StringBuffer buf = new StringBuffer(len + 5);
    186     char[]       ch  = str.toCharArray();
    187
    188     for(int i=0; i < len; i++) {
    189       switch(ch[i]) {
    190       case '\n' : buf.append("//n"); break;
    191       case '\r' : buf.append("//r"); break;
    192       case '\t' : buf.append("//t"); break;
    193       case '\b' : buf.append("//b"); break;
    194       case '"'  : buf.append("//\""); break;
    195       default: buf.append(ch[i]);
    196       }
    197     }
    198
    199     return buf.toString();
    200   }
    201
    202
    203   /***
    204    * Retrieve constant at `index' from constant pool and resolve it to
    205    * a string representation.
    206    *
    207    * @param  index of constant in constant pool
    208    * @param  tag expected type
    209    * @return String representation
    210    */
    211   public String constantToString(int index, byte tag)
    212        throws ClassFormatException
    213   {
    214     Constant c = getConstant(index, tag);
    215     return constantToString(c);
    216   }
    217
    218   /***
    219    * Dump constant pool to file stream in binary format.
    220    *
    221    * @param file Output file stream
    222    * @throws IOException
    223    */
    224   public void dump(DataOutputStream file) throws IOException
    225   {
    226     file.writeShort(constant_pool_count);
    227
    228     for(int i=1; i < constant_pool_count; i++)
    229       if(constant_pool[i] != null)
    230 	constant_pool[i].dump(file);
    231   }
    232
    233   /***
    234    * Get constant from constant pool.
    235    *
    236    * @param  index Index in constant pool
    237    * @return Constant value
    238    * @see    Constant
    239    */
    240   public Constant getConstant(int index) {
    241     if (index >= constant_pool.length || index < 0)
    242       throw new ClassFormatException("Invalid constant pool reference: " +
    243 				 index + ". Constant pool size is: " +
    244 				 constant_pool.length);
    245     return constant_pool[index];
    246   }
    247
    248   /***
    249    * Get constant from constant pool and check whether it has the
    250    * expected type.
    251    *
    252    * @param  index Index in constant pool
    253    * @param  tag Tag of expected constant, i.e., its type
    254    * @return Constant value
    255    * @see    Constant
    256    * @throws  ClassFormatException
    257    */
    258   public Constant getConstant(int index, byte tag)
    259        throws ClassFormatException
    260   {
    261     Constant c;
    262
    263     c = getConstant(index);
    264
    265     if(c == null)
    266       throw new ClassFormatException("Constant pool at index " + index + " is null.");
    267
    268     if(c.getTag() == tag)
    269       return c;
    270     else
    271       throw new ClassFormatException("Expected class `" + Constants.CONSTANT_NAMES[tag] +
    272 				 "' at index " + index + " and got " + c);
    273   }
    274
    275   /***
    276    * @return Array of constants.
    277    * @see    Constant
    278    */
    279   public Constant[] getConstantPool() { return constant_pool;  }
    280   /***
    281    * Get string from constant pool and bypass the indirection of
    282    * `ConstantClass' and `ConstantString' objects. I.e. these classes have
    283    * an index field that points to another entry of the constant pool of
    284    * type `ConstantUtf8' which contains the real data.
    285    *
    286    * @param  index Index in constant pool
    287    * @param  tag Tag of expected constant, either ConstantClass or ConstantString
    288    * @return Contents of string reference
    289    * @see    ConstantClass
    290    * @see    ConstantString
    291    * @throws  ClassFormatException
    292    */
    293   public String getConstantString(int index, byte tag)
    294        throws ClassFormatException
    295   {
    296     Constant c;
    297     int    i;
    298
    299     c = getConstant(index, tag);
    300
    301     /* This switch() is not that elegant, since the two classes have the
    302      * same contents, they just differ in the name of the index
    303      * field variable.
    304      * But we want to stick to the JVM naming conventions closely though
    305      * we could have solved these more elegantly by using the same
    306      * variable name or by subclassing.
    307      */
    308     switch(tag) {
    309     case Constants.CONSTANT_Class:  i = ((ConstantClass)c).getNameIndex();    break;
    310     case Constants.CONSTANT_String: i = ((ConstantString)c).getStringIndex(); break;
    311     default:
    312       throw new RuntimeException("getConstantString called with illegal tag " + tag);
    313     }
    314
    315     // Finally get the string from the constant pool
    316     c = getConstant(i, Constants.CONSTANT_Utf8);
    317     return ((ConstantUtf8)c).getBytes();
    318   }
    319   /***
    320    * @return Length of constant pool.
    321    */
    322   public int getLength()
    323   {
    324     return constant_pool_count;
    325   }
    326
    327   /***
    328    * @param constant Constant to set
    329    */
    330   public void setConstant(int index, Constant constant) {
    331     constant_pool[index] = constant;
    332   }
    333
    334   /***
    335    * @param constant_pool
    336    */
    337   public void setConstantPool(Constant[] constant_pool) {
    338     this.constant_pool = constant_pool;
    339     constant_pool_count = (constant_pool == null)? 0 : constant_pool.length;
    340   }
    341   /***
    342    * @return String representation.
    343    */
    344   public String toString() {
    345     StringBuffer buf = new StringBuffer();
    346
    347     for(int i=1; i < constant_pool_count; i++)
    348       buf.append(i + ")" + constant_pool[i] + "\n");
    349
    350     return buf.toString();
    351   }
    352
    353   /***
    354    * @return deep copy of this constant pool
    355    */
    356   public ConstantPool copy() {
    357     ConstantPool c = null;
    358
    359     try {
    360       c = (ConstantPool)clone();
    361     } catch(CloneNotSupportedException e) {}
    362
    363     c.constant_pool = new Constant[constant_pool_count];
    364
    365     for(int i=1; i < constant_pool_count; i++) {
    366       if(constant_pool[i] != null)
    367 	c.constant_pool[i] = constant_pool[i].copy();
    368     }
    369
    370     return c;
    371   }
    372 }

This page was automatically generated by Maven