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