< prev index next >

src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java

Print this page




  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.bcel.internal.classfile;
  23 
  24 import java.io.DataInput;
  25 import java.io.DataOutputStream;
  26 import java.io.IOException;
  27 
  28 import com.sun.org.apache.bcel.internal.Const;
  29 
  30 /**
  31  * This class represents the constant pool, i.e., a table of constants, of
  32  * a parsed classfile. It may contain null references, due to the JVM
  33  * specification that skips an entry after an 8-byte constant (double,
  34  * long) entry.  Those interested in generating constant pools
  35  * programatically should see <a href="../generic/ConstantPoolGen.html">
  36  * ConstantPoolGen</a>.
  37 
  38  * @version $Id$
  39  * @see     Constant
  40  * @see     com.sun.org.apache.bcel.internal.generic.ConstantPoolGen
  41  */
  42 public class ConstantPool implements Cloneable, Node {
  43 
  44     private Constant[] constant_pool;
  45 
  46 
  47     /**
  48      * @param constant_pool Array of constants
  49      */
  50     public ConstantPool(final Constant[] constant_pool) {
  51         this.constant_pool = constant_pool;
  52     }
  53 
  54 
  55     /**
  56      * Read constants from given input stream.
  57      *
  58      * @param input Input stream
  59      * @throws IOException
  60      * @throws ClassFormatException
  61      */
  62     public ConstantPool(final DataInput input) throws IOException, ClassFormatException {
  63         byte tag;
  64         final int constant_pool_count = input.readUnsignedShort();
  65         constant_pool = new Constant[constant_pool_count];
  66         /* constant_pool[0] is unused by the compiler and may be used freely
  67          * by the implementation.
  68          */
  69         for (int i = 1; i < constant_pool_count; i++) {
  70             constant_pool[i] = Constant.readConstant(input);
  71             /* Quote from the JVM specification:
  72              * "All eight byte constants take up two spots in the constant pool.
  73              * If this is the n'th byte in the constant pool, then the next item
  74              * will be numbered n+2"
  75              *
  76              * Thus we have to increment the index counter.
  77              */
  78             tag = constant_pool[i].getTag();
  79             if ((tag == Const.CONSTANT_Double) || (tag == Const.CONSTANT_Long)) {
  80                 i++;
  81             }
  82         }
  83     }
  84 
  85 
  86     /**
  87      * Called by objects that are traversing the nodes of the tree implicitely
  88      * defined by the contents of a Java class. I.e., the hierarchy of methods,
  89      * fields, attributes, etc. spawns a tree of objects.
  90      *
  91      * @param v Visitor object
  92      */
  93     @Override
  94     public void accept( final Visitor v ) {
  95         v.visitConstantPool(this);
  96     }
  97 
  98 
  99     /**
 100      * Resolve constant to a string representation.
 101      *
 102      * @param  c Constant to be printed
 103      * @return String representation
 104      */
 105     public String constantToString( Constant c ) throws ClassFormatException {
 106         String str;
 107         int i;
 108         final byte tag = c.getTag();
 109         switch (tag) {
 110             case Const.CONSTANT_Class:
 111                 i = ((ConstantClass) c).getNameIndex();
 112                 c = getConstant(i, Const.CONSTANT_Utf8);
 113                 str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
 114                 break;
 115             case Const.CONSTANT_String:
 116                 i = ((ConstantString) c).getStringIndex();
 117                 c = getConstant(i, Const.CONSTANT_Utf8);
 118                 str = "\"" + escape(((ConstantUtf8) c).getBytes()) + "\"";
 119                 break;
 120             case Const.CONSTANT_Utf8:


 146                         Const.CONSTANT_NameAndType);
 147                 break;
 148             case Const.CONSTANT_MethodHandle:
 149                 // Note that the ReferenceIndex may point to a Fieldref, Methodref or
 150                 // InterfaceMethodref - so we need to peek ahead to get the actual type.
 151                 final ConstantMethodHandle cmh = (ConstantMethodHandle) c;
 152                 str = Const.getMethodHandleName(cmh.getReferenceKind())
 153                         + " " + constantToString(cmh.getReferenceIndex(),
 154                         getConstant(cmh.getReferenceIndex()).getTag());
 155                 break;
 156             case Const.CONSTANT_MethodType:
 157                 final ConstantMethodType cmt = (ConstantMethodType) c;
 158                 str = constantToString(cmt.getDescriptorIndex(), Const.CONSTANT_Utf8);
 159                 break;
 160             case Const.CONSTANT_InvokeDynamic:
 161                 final ConstantInvokeDynamic cid = (ConstantInvokeDynamic) c;
 162                 str = cid.getBootstrapMethodAttrIndex()
 163                         + ":" + constantToString(cid.getNameAndTypeIndex(),
 164                         Const.CONSTANT_NameAndType);
 165                 break;










 166             default: // Never reached
 167                 throw new RuntimeException("Unknown constant type " + tag);
 168         }
 169         return str;
 170     }
 171 
 172 
 173     private static String escape( final String str ) {
 174         final int len = str.length();
 175         final StringBuilder buf = new StringBuilder(len + 5);
 176         final char[] ch = str.toCharArray();
 177         for (int i = 0; i < len; i++) {
 178             switch (ch[i]) {
 179                 case '\n':
 180                     buf.append("\\n");
 181                     break;
 182                 case '\r':
 183                     buf.append("\\r");
 184                     break;
 185                 case '\t':
 186                     buf.append("\\t");
 187                     break;
 188                 case '\b':
 189                     buf.append("\\b");
 190                     break;
 191                 case '"':
 192                     buf.append("\\\"");
 193                     break;
 194                 default:
 195                     buf.append(ch[i]);
 196             }
 197         }
 198         return buf.toString();
 199     }
 200 
 201 
 202     /**
 203      * Retrieve constant at `index' from constant pool and resolve it to
 204      * a string representation.
 205      *
 206      * @param  index of constant in constant pool
 207      * @param  tag expected type
 208      * @return String representation
 209      */
 210     public String constantToString( final int index, final byte tag ) throws ClassFormatException {
 211         final Constant c = getConstant(index, tag);
 212         return constantToString(c);
 213     }
 214 
 215 
 216     /**
 217      * Dump constant pool to file stream in binary format.
 218      *
 219      * @param file Output file stream
 220      * @throws IOException
 221      */
 222     public void dump( final DataOutputStream file ) throws IOException {
 223         file.writeShort(constant_pool.length);
 224         for (int i = 1; i < constant_pool.length; i++) {
 225             if (constant_pool[i] != null) {
 226                 constant_pool[i].dump(file);
 227             }
 228         }
 229     }
 230 
 231 
 232     /**
 233      * Get constant from constant pool.
 234      *
 235      * @param  index Index in constant pool
 236      * @return Constant value
 237      * @see    Constant
 238      */
 239     public Constant getConstant( final int index ) {
 240         if (index >= constant_pool.length || index < 0) {
 241             throw new ClassFormatException("Invalid constant pool reference: " + index
 242                     + ". Constant pool size is: " + constant_pool.length);
 243         }
 244         return constant_pool[index];
 245     }
 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( final int index, final byte tag ) throws ClassFormatException {
 259         Constant c;
 260         c = getConstant(index);
 261         if (c == null) {
 262             throw new ClassFormatException("Constant pool at index " + index + " is null.");
 263         }
 264         if (c.getTag() != tag) {
 265             throw new ClassFormatException("Expected class `" + Const.getConstantName(tag)
 266                     + "' at index " + index + " and got " + c);
 267         }
 268         return c;
 269     }
 270 
 271 
 272     /**
 273      * @return Array of constants.
 274      * @see    Constant
 275      */
 276     public Constant[] getConstantPool() {
 277         return constant_pool;
 278     }
 279 
 280 
 281     /**
 282      * Get string from constant pool and bypass the indirection of
 283      * `ConstantClass' and `ConstantString' objects. I.e. these classes have
 284      * an index field that points to another entry of the constant pool of
 285      * type `ConstantUtf8' which contains the real data.
 286      *
 287      * @param  index Index in constant pool
 288      * @param  tag Tag of expected constant, either ConstantClass or ConstantString
 289      * @return Contents of string reference
 290      * @see    ConstantClass
 291      * @see    ConstantString
 292      * @throws  ClassFormatException
 293      */
 294     public String getConstantString( final int index, final byte tag ) throws ClassFormatException {
 295         Constant c;
 296         int i;
 297         c = getConstant(index, tag);
 298         /* This switch() is not that elegant, since the two classes have the
 299          * same contents, they just differ in the name of the index
 300          * field variable.
 301          * But we want to stick to the JVM naming conventions closely though
 302          * we could have solved these more elegantly by using the same
 303          * variable name or by subclassing.
 304          */
 305         switch (tag) {
 306             case Const.CONSTANT_Class:
 307                 i = ((ConstantClass) c).getNameIndex();
 308                 break;
 309             case Const.CONSTANT_String:
 310                 i = ((ConstantString) c).getStringIndex();






 311                 break;
 312             default:
 313                 throw new RuntimeException("getConstantString called with illegal tag " + tag);
 314         }
 315         // Finally get the string from the constant pool
 316         c = getConstant(i, Const.CONSTANT_Utf8);
 317         return ((ConstantUtf8) c).getBytes();
 318     }
 319 
 320 
 321     /**
 322      * @return Length of constant pool.
 323      */
 324     public int getLength() {
 325         return constant_pool == null ? 0 : constant_pool.length;
 326     }
 327 
 328 
 329     /**
 330      * @param constant Constant to set




  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.bcel.internal.classfile;
  23 
  24 import java.io.DataInput;
  25 import java.io.DataOutputStream;
  26 import java.io.IOException;
  27 
  28 import com.sun.org.apache.bcel.internal.Const;
  29 
  30 /**
  31  * This class represents the constant pool, i.e., a table of constants, of
  32  * a parsed classfile. It may contain null references, due to the JVM
  33  * specification that skips an entry after an 8-byte constant (double,
  34  * long) entry.  Those interested in generating constant pools
  35  * programatically should see <a href="../generic/ConstantPoolGen.html">
  36  * ConstantPoolGen</a>.
  37 

  38  * @see     Constant
  39  * @see     com.sun.org.apache.bcel.internal.generic.ConstantPoolGen
  40  */
  41 public class ConstantPool implements Cloneable, Node {
  42 
  43     private Constant[] constant_pool;
  44 

  45     /**
  46      * @param constant_pool Array of constants
  47      */
  48     public ConstantPool(final Constant[] constant_pool) {
  49         this.constant_pool = constant_pool;
  50     }
  51 

  52     /**
  53      * Reads constants from given input stream.
  54      *
  55      * @param input Input stream
  56      * @throws IOException
  57      * @throws ClassFormatException
  58      */
  59     public ConstantPool(final DataInput input) throws IOException, ClassFormatException {
  60         byte tag;
  61         final int constant_pool_count = input.readUnsignedShort();
  62         constant_pool = new Constant[constant_pool_count];
  63         /* constant_pool[0] is unused by the compiler and may be used freely
  64          * by the implementation.
  65          */
  66         for (int i = 1; i < constant_pool_count; i++) {
  67             constant_pool[i] = Constant.readConstant(input);
  68             /* Quote from the JVM specification:
  69              * "All eight byte constants take up two spots in the constant pool.
  70              * If this is the n'th byte in the constant pool, then the next item
  71              * will be numbered n+2"
  72              *
  73              * Thus we have to increment the index counter.
  74              */
  75             tag = constant_pool[i].getTag();
  76             if ((tag == Const.CONSTANT_Double) || (tag == Const.CONSTANT_Long)) {
  77                 i++;
  78             }
  79         }
  80     }
  81 

  82     /**
  83      * Called by objects that are traversing the nodes of the tree implicitely
  84      * defined by the contents of a Java class. I.e., the hierarchy of methods,
  85      * fields, attributes, etc. spawns a tree of objects.
  86      *
  87      * @param v Visitor object
  88      */
  89     @Override
  90     public void accept( final Visitor v ) {
  91         v.visitConstantPool(this);
  92     }
  93 

  94     /**
  95      * Resolves constant to a string representation.
  96      *
  97      * @param  c Constant to be printed
  98      * @return String representation
  99      */
 100     public String constantToString( Constant c ) throws ClassFormatException {
 101         String str;
 102         int i;
 103         final byte tag = c.getTag();
 104         switch (tag) {
 105             case Const.CONSTANT_Class:
 106                 i = ((ConstantClass) c).getNameIndex();
 107                 c = getConstant(i, Const.CONSTANT_Utf8);
 108                 str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
 109                 break;
 110             case Const.CONSTANT_String:
 111                 i = ((ConstantString) c).getStringIndex();
 112                 c = getConstant(i, Const.CONSTANT_Utf8);
 113                 str = "\"" + escape(((ConstantUtf8) c).getBytes()) + "\"";
 114                 break;
 115             case Const.CONSTANT_Utf8:


 141                         Const.CONSTANT_NameAndType);
 142                 break;
 143             case Const.CONSTANT_MethodHandle:
 144                 // Note that the ReferenceIndex may point to a Fieldref, Methodref or
 145                 // InterfaceMethodref - so we need to peek ahead to get the actual type.
 146                 final ConstantMethodHandle cmh = (ConstantMethodHandle) c;
 147                 str = Const.getMethodHandleName(cmh.getReferenceKind())
 148                         + " " + constantToString(cmh.getReferenceIndex(),
 149                         getConstant(cmh.getReferenceIndex()).getTag());
 150                 break;
 151             case Const.CONSTANT_MethodType:
 152                 final ConstantMethodType cmt = (ConstantMethodType) c;
 153                 str = constantToString(cmt.getDescriptorIndex(), Const.CONSTANT_Utf8);
 154                 break;
 155             case Const.CONSTANT_InvokeDynamic:
 156                 final ConstantInvokeDynamic cid = (ConstantInvokeDynamic) c;
 157                 str = cid.getBootstrapMethodAttrIndex()
 158                         + ":" + constantToString(cid.getNameAndTypeIndex(),
 159                         Const.CONSTANT_NameAndType);
 160                 break;
 161             case Const.CONSTANT_Module:
 162                 i = ((ConstantModule) c).getNameIndex();
 163                 c = getConstant(i, Const.CONSTANT_Utf8);
 164                 str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
 165                 break;
 166             case Const.CONSTANT_Package:
 167                 i = ((ConstantPackage) c).getNameIndex();
 168                 c = getConstant(i, Const.CONSTANT_Utf8);
 169                 str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
 170                 break;
 171             default: // Never reached
 172                 throw new RuntimeException("Unknown constant type " + tag);
 173         }
 174         return str;
 175     }
 176 

 177     private static String escape( final String str ) {
 178         final int len = str.length();
 179         final StringBuilder buf = new StringBuilder(len + 5);
 180         final char[] ch = str.toCharArray();
 181         for (int i = 0; i < len; i++) {
 182             switch (ch[i]) {
 183                 case '\n':
 184                     buf.append("\\n");
 185                     break;
 186                 case '\r':
 187                     buf.append("\\r");
 188                     break;
 189                 case '\t':
 190                     buf.append("\\t");
 191                     break;
 192                 case '\b':
 193                     buf.append("\\b");
 194                     break;
 195                 case '"':
 196                     buf.append("\\\"");
 197                     break;
 198                 default:
 199                     buf.append(ch[i]);
 200             }
 201         }
 202         return buf.toString();
 203     }
 204 

 205     /**
 206      * Retrieves constant at `index' from constant pool and resolve it to
 207      * a string representation.
 208      *
 209      * @param  index of constant in constant pool
 210      * @param  tag expected type
 211      * @return String representation
 212      */
 213     public String constantToString( final int index, final byte tag ) throws ClassFormatException {
 214         final 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( final DataOutputStream file ) throws IOException {
 225         file.writeShort(constant_pool.length);
 226         for (int i = 1; i < constant_pool.length; i++) {
 227             if (constant_pool[i] != null) {
 228                 constant_pool[i].dump(file);
 229             }
 230         }
 231     }
 232 

 233     /**
 234      * Gets constant from constant pool.
 235      *
 236      * @param  index Index in constant pool
 237      * @return Constant value
 238      * @see    Constant
 239      */
 240     public Constant getConstant( final int index ) {
 241         if (index >= constant_pool.length || index < 0) {
 242             throw new ClassFormatException("Invalid constant pool reference: " + index
 243                     + ". Constant pool size is: " + constant_pool.length);
 244         }
 245         return constant_pool[index];
 246     }
 247 

 248     /**
 249      * Gets 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( final int index, final byte tag ) throws ClassFormatException {
 259         Constant c;
 260         c = getConstant(index);
 261         if (c == null) {
 262             throw new ClassFormatException("Constant pool at index " + index + " is null.");
 263         }
 264         if (c.getTag() != tag) {
 265             throw new ClassFormatException("Expected class `" + Const.getConstantName(tag)
 266                     + "' at index " + index + " and got " + c);
 267         }
 268         return c;
 269     }
 270 

 271     /**
 272      * @return Array of constants.
 273      * @see    Constant
 274      */
 275     public Constant[] getConstantPool() {
 276         return constant_pool;
 277     }
 278 

 279     /**
 280      * Gets string from constant pool and bypass the indirection of
 281      * `ConstantClass' and `ConstantString' objects. I.e. these classes have
 282      * an index field that points to another entry of the constant pool of
 283      * type `ConstantUtf8' which contains the real data.
 284      *
 285      * @param  index Index in constant pool
 286      * @param  tag Tag of expected constant, either ConstantClass or ConstantString
 287      * @return Contents of string reference
 288      * @see    ConstantClass
 289      * @see    ConstantString
 290      * @throws  ClassFormatException
 291      */
 292     public String getConstantString( final int index, final byte tag ) throws ClassFormatException {
 293         Constant c;
 294         int i;
 295         c = getConstant(index, tag);
 296         /* This switch() is not that elegant, since the four classes have the
 297          * same contents, they just differ in the name of the index
 298          * field variable.
 299          * But we want to stick to the JVM naming conventions closely though
 300          * we could have solved these more elegantly by using the same
 301          * variable name or by subclassing.
 302          */
 303         switch (tag) {
 304             case Const.CONSTANT_Class:
 305                 i = ((ConstantClass) c).getNameIndex();
 306                 break;
 307             case Const.CONSTANT_String:
 308                 i = ((ConstantString) c).getStringIndex();
 309                 break;
 310             case Const.CONSTANT_Module:
 311                 i = ((ConstantModule) c).getNameIndex();
 312                 break;
 313             case Const.CONSTANT_Package:
 314                 i = ((ConstantPackage) c).getNameIndex();
 315                 break;
 316             default:
 317                 throw new RuntimeException("getConstantString called with illegal tag " + tag);
 318         }
 319         // Finally get the string from the constant pool
 320         c = getConstant(i, Const.CONSTANT_Utf8);
 321         return ((ConstantUtf8) c).getBytes();
 322     }
 323 
 324 
 325     /**
 326      * @return Length of constant pool.
 327      */
 328     public int getLength() {
 329         return constant_pool == null ? 0 : constant_pool.length;
 330     }
 331 
 332 
 333     /**
 334      * @param constant Constant to set


< prev index next >