src/share/classes/com/sun/tools/javap/ClassWriter.java

Tue, 28 Jul 2009 10:36:25 -0700

author
jjg
date
Tue, 28 Jul 2009 10:36:25 -0700
changeset 338
777a3efad0d5
parent 300
ed989c347b3c
child 348
743f17b55b44
permissions
-rw-r--r--

6855990: javap InstructionDetailWriter should support new 308 annotations attribute
Reviewed-by: mcimadamore

jjg@46 1 /*
xdono@54 2 * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
jjg@46 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@46 4 *
jjg@46 5 * This code is free software; you can redistribute it and/or modify it
jjg@46 6 * under the terms of the GNU General Public License version 2 only, as
jjg@46 7 * published by the Free Software Foundation. Sun designates this
jjg@46 8 * particular file as subject to the "Classpath" exception as provided
jjg@46 9 * by Sun in the LICENSE file that accompanied this code.
jjg@46 10 *
jjg@46 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@46 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@46 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@46 14 * version 2 for more details (a copy is included in the LICENSE file that
jjg@46 15 * accompanied this code).
jjg@46 16 *
jjg@46 17 * You should have received a copy of the GNU General Public License version
jjg@46 18 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@46 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@46 20 *
jjg@46 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
jjg@46 22 * CA 95054 USA or visit www.sun.com if you need additional information or
jjg@46 23 * have any questions.
jjg@46 24 */
jjg@46 25
jjg@46 26 package com.sun.tools.javap;
jjg@46 27
jjg@88 28 import java.net.URI;
jjg@283 29 import java.text.DateFormat;
jjg@46 30 import java.util.Collection;
jjg@283 31 import java.util.Date;
jjg@46 32 import java.util.List;
jjg@46 33
jjg@46 34 import com.sun.tools.classfile.AccessFlags;
jjg@46 35 import com.sun.tools.classfile.Attribute;
jjg@46 36 import com.sun.tools.classfile.Attributes;
jjg@46 37 import com.sun.tools.classfile.ClassFile;
jjg@46 38 import com.sun.tools.classfile.Code_attribute;
jjg@46 39 import com.sun.tools.classfile.ConstantPool;
jjg@46 40 import com.sun.tools.classfile.ConstantPoolException;
jjg@87 41 import com.sun.tools.classfile.ConstantValue_attribute;
jjg@46 42 import com.sun.tools.classfile.Descriptor;
jjg@46 43 import com.sun.tools.classfile.DescriptorException;
jjg@46 44 import com.sun.tools.classfile.Exceptions_attribute;
jjg@46 45 import com.sun.tools.classfile.Field;
jjg@46 46 import com.sun.tools.classfile.Method;
jjg@46 47 import com.sun.tools.classfile.Signature;
jjg@46 48 import com.sun.tools.classfile.Signature_attribute;
jjg@46 49 import com.sun.tools.classfile.SourceFile_attribute;
jjg@46 50 import com.sun.tools.classfile.Type;
jjg@46 51
jjg@46 52 import static com.sun.tools.classfile.AccessFlags.*;
jjg@46 53
jjg@46 54 /*
jjg@46 55 * The main javap class to write the contents of a class file as text.
jjg@46 56 *
jjg@46 57 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
jjg@46 58 * you write code that depends on this, you do so at your own risk.
jjg@46 59 * This code and its internal interfaces are subject to change or
jjg@46 60 * deletion without notice.</b>
jjg@46 61 */
jjg@46 62 public class ClassWriter extends BasicWriter {
jjg@46 63 static ClassWriter instance(Context context) {
jjg@46 64 ClassWriter instance = context.get(ClassWriter.class);
jjg@46 65 if (instance == null)
jjg@46 66 instance = new ClassWriter(context);
jjg@46 67 return instance;
jjg@46 68 }
jjg@46 69
jjg@46 70 protected ClassWriter(Context context) {
jjg@46 71 super(context);
jjg@46 72 context.put(ClassWriter.class, this);
jjg@46 73 options = Options.instance(context);
jjg@46 74 attrWriter = AttributeWriter.instance(context);
jjg@46 75 codeWriter = CodeWriter.instance(context);
jjg@46 76 constantWriter = ConstantWriter.instance(context);
jjg@46 77 }
jjg@46 78
jjg@88 79 void setDigest(String name, byte[] digest) {
jjg@88 80 this.digestName = name;
jjg@88 81 this.digest = digest;
jjg@88 82 }
jjg@88 83
jjg@88 84 void setFile(URI uri) {
jjg@88 85 this.uri = uri;
jjg@88 86 }
jjg@88 87
jjg@88 88 void setFileSize(int size) {
jjg@88 89 this.size = size;
jjg@88 90 }
jjg@88 91
jjg@88 92 void setLastModified(long lastModified) {
jjg@88 93 this.lastModified = lastModified;
jjg@88 94 }
jjg@88 95
jjg@300 96 protected ClassFile getClassFile() {
jjg@46 97 return classFile;
jjg@46 98 }
jjg@46 99
jjg@300 100 protected void setClassFile(ClassFile cf) {
jjg@300 101 classFile = cf;
jjg@300 102 constant_pool = classFile.constant_pool;
jjg@300 103 }
jjg@300 104
jjg@300 105 protected Method getMethod() {
jjg@46 106 return method;
jjg@46 107 }
jjg@46 108
jjg@300 109 protected void setMethod(Method m) {
jjg@300 110 method = m;
jjg@300 111 }
jjg@300 112
jjg@46 113 public void write(ClassFile cf) {
jjg@300 114 setClassFile(cf);
jjg@46 115
jjg@88 116 if ((options.sysInfo || options.verbose) && !options.compat) {
jjg@88 117 if (uri != null) {
jjg@88 118 if (uri.getScheme().equals("file"))
jjg@88 119 println("Classfile " + uri.getPath());
jjg@88 120 else
jjg@88 121 println("Classfile " + uri);
jjg@88 122 }
jjg@88 123 if (lastModified != -1) {
jjg@88 124 Date lm = new Date(lastModified);
jjg@88 125 DateFormat df = DateFormat.getDateInstance();
jjg@88 126 if (size > 0) {
jjg@88 127 println("Last modified " + df.format(lm) + "; size " + size + " bytes");
jjg@88 128 } else {
jjg@88 129 println("Last modified " + df.format(lm));
jjg@88 130 }
jjg@88 131 } else if (size > 0) {
jjg@88 132 println("Size " + size + " bytes");
jjg@88 133 }
jjg@88 134 if (digestName != null && digest != null) {
jjg@88 135 StringBuilder sb = new StringBuilder();
jjg@88 136 for (byte b: digest)
jjg@88 137 sb.append(String.format("%02x", b));
jjg@88 138 println(digestName + " checksum " + sb);
jjg@88 139 }
jjg@88 140 }
jjg@88 141
jjg@46 142 Attribute sfa = cf.getAttribute(Attribute.SourceFile);
jjg@46 143 if (sfa instanceof SourceFile_attribute) {
jjg@46 144 println("Compiled from \"" + getSourceFile((SourceFile_attribute) sfa) + "\"");
jjg@46 145 }
jjg@46 146
jjg@46 147 String name = getJavaName(classFile);
jjg@46 148 AccessFlags flags = cf.access_flags;
jjg@46 149
jjg@46 150 writeModifiers(flags.getClassModifiers());
jjg@46 151
jjg@46 152 if (classFile.isClass())
jjg@46 153 print("class ");
jjg@46 154 else if (classFile.isInterface())
jjg@46 155 print("interface ");
jjg@46 156
jjg@46 157 print(name);
jjg@46 158
jjg@46 159 Signature_attribute sigAttr = getSignature(cf.attributes);
jjg@46 160 if (sigAttr == null) {
jjg@46 161 // use info from class file header
jjg@65 162 if (classFile.isClass() && classFile.super_class != 0 ) {
jjg@65 163 String sn = getJavaSuperclassName(cf);
jjg@65 164 print(" extends ");
jjg@65 165 print(sn);
jjg@46 166 }
jjg@46 167 for (int i = 0; i < classFile.interfaces.length; i++) {
jjg@46 168 print(i == 0 ? (classFile.isClass() ? " implements " : " extends ") : ",");
jjg@46 169 print(getJavaInterfaceName(classFile, i));
jjg@46 170 }
jjg@46 171 } else {
jjg@46 172 try {
jjg@46 173 Type t = sigAttr.getParsedSignature().getType(constant_pool);
jjg@46 174 // The signature parser cannot disambiguate between a
jjg@46 175 // FieldType and a ClassSignatureType that only contains a superclass type.
jjg@46 176 if (t instanceof Type.ClassSigType)
jjg@46 177 print(t);
jjg@65 178 else {
jjg@46 179 print(" extends ");
jjg@46 180 print(t);
jjg@46 181 }
jjg@46 182 } catch (ConstantPoolException e) {
jjg@46 183 print(report(e));
jjg@46 184 }
jjg@46 185 }
jjg@46 186
jjg@46 187 if (options.verbose) {
jjg@46 188 println();
jjg@46 189 attrWriter.write(cf, cf.attributes, constant_pool);
jjg@46 190 println(" minor version: " + cf.minor_version);
jjg@46 191 println(" major version: " + cf.major_version);
jjg@46 192 if (!options.compat)
jjg@46 193 writeList(" flags: ", flags.getClassFlags(), NEWLINE);
jjg@46 194 constantWriter.writeConstantPool();
jjg@46 195 println();
jjg@46 196 } else {
jjg@46 197 if (!options.compat)
jjg@46 198 print(" ");
jjg@46 199 }
jjg@46 200
jjg@46 201 println("{");
jjg@46 202 writeFields();
jjg@46 203 writeMethods();
jjg@46 204 println("}");
jjg@46 205 println();
jjg@46 206 }
jjg@46 207
jjg@300 208 protected void writeFields() {
jjg@46 209 for (Field f: classFile.fields) {
jjg@46 210 writeField(f);
jjg@46 211 }
jjg@46 212 }
jjg@46 213
jjg@300 214 protected void writeField(Field f) {
jjg@46 215 if (!options.checkAccess(f.access_flags))
jjg@46 216 return;
jjg@46 217
jjg@46 218 if (!(options.showLineAndLocalVariableTables
jjg@46 219 || options.showDisassembled
jjg@46 220 || options.verbose
jjg@46 221 || options.showInternalSignatures
jjg@46 222 || options.showAllAttrs)) {
jjg@46 223 print(" ");
jjg@46 224 }
jjg@46 225
jjg@46 226 AccessFlags flags = f.access_flags;
jjg@46 227 writeModifiers(flags.getFieldModifiers());
jjg@46 228 Signature_attribute sigAttr = getSignature(f.attributes);
jjg@46 229 if (sigAttr == null)
jjg@46 230 print(getFieldType(f.descriptor));
jjg@46 231 else {
jjg@46 232 try {
jjg@46 233 Type t = sigAttr.getParsedSignature().getType(constant_pool);
jjg@46 234 print(t);
jjg@46 235 } catch (ConstantPoolException e) {
jjg@46 236 // report error?
jjg@46 237 // fall back on non-generic descriptor
jjg@46 238 print(getFieldType(f.descriptor));
jjg@46 239 }
jjg@46 240 }
jjg@46 241 print(" ");
jjg@46 242 print(getFieldName(f));
jjg@87 243 if (options.showConstants && !options.compat) { // BUG 4111861 print static final field contents
jjg@87 244 Attribute a = f.attributes.get(Attribute.ConstantValue);
jjg@87 245 if (a instanceof ConstantValue_attribute) {
jjg@87 246 print(" = ");
jjg@87 247 ConstantValue_attribute cv = (ConstantValue_attribute) a;
jjg@87 248 print(getConstantValue(f.descriptor, cv.constantvalue_index));
jjg@87 249 }
jjg@87 250 }
jjg@46 251 print(";");
jjg@46 252 println();
jjg@46 253
jjg@46 254 if (options.showInternalSignatures)
jjg@46 255 println(" Signature: " + getValue(f.descriptor));
jjg@46 256
jjg@46 257 if (options.verbose && !options.compat)
jjg@46 258 writeList(" flags: ", flags.getFieldFlags(), NEWLINE);
jjg@46 259
jjg@46 260 if (options.showAllAttrs) {
jjg@46 261 for (Attribute attr: f.attributes)
jjg@46 262 attrWriter.write(f, attr, constant_pool);
jjg@46 263 println();
jjg@46 264 }
jjg@46 265
jjg@46 266 if (options.showDisassembled || options.showLineAndLocalVariableTables)
jjg@46 267 println();
jjg@46 268 }
jjg@46 269
jjg@300 270 protected void writeMethods() {
jjg@46 271 for (Method m: classFile.methods)
jjg@46 272 writeMethod(m);
jjg@46 273 }
jjg@46 274
jjg@300 275 protected void writeMethod(Method m) {
jjg@46 276 if (!options.checkAccess(m.access_flags))
jjg@46 277 return;
jjg@46 278
jjg@46 279 method = m;
jjg@46 280
jjg@46 281 if (!(options.showLineAndLocalVariableTables
jjg@46 282 || options.showDisassembled
jjg@46 283 || options.verbose
jjg@46 284 || options.showInternalSignatures
jjg@46 285 || options.showAllAttrs)) {
jjg@46 286 print(" ");
jjg@46 287 }
jjg@46 288
jjg@46 289 AccessFlags flags = m.access_flags;
jjg@46 290
jjg@46 291 Descriptor d;
jjg@46 292 Type.MethodType methodType;
jjg@46 293 List<? extends Type> methodExceptions;
jjg@46 294
jjg@46 295 Signature_attribute sigAttr = getSignature(m.attributes);
jjg@46 296 if (sigAttr == null) {
jjg@46 297 d = m.descriptor;
jjg@46 298 methodType = null;
jjg@46 299 methodExceptions = null;
jjg@46 300 } else {
jjg@46 301 Signature methodSig = sigAttr.getParsedSignature();
jjg@46 302 d = methodSig;
jjg@46 303 try {
jjg@46 304 methodType = (Type.MethodType) methodSig.getType(constant_pool);
jjg@46 305 methodExceptions = methodType.throwsTypes;
jjg@46 306 if (methodExceptions != null && methodExceptions.size() == 0)
jjg@46 307 methodExceptions = null;
jjg@46 308 } catch (ConstantPoolException e) {
jjg@46 309 // report error?
jjg@46 310 // fall back on standard descriptor
jjg@46 311 methodType = null;
jjg@46 312 methodExceptions = null;
jjg@46 313 }
jjg@46 314 }
jjg@46 315
jjg@46 316 writeModifiers(flags.getMethodModifiers());
jjg@46 317 if (methodType != null) {
jjg@46 318 writeListIfNotEmpty("<", methodType.typeArgTypes, "> ");
jjg@46 319 }
jjg@46 320 if (getName(m).equals("<init>")) {
jjg@46 321 print(getJavaName(classFile));
jjg@46 322 print(getParameterTypes(d, flags));
jjg@46 323 } else if (getName(m).equals("<clinit>")) {
jjg@46 324 print("{}");
jjg@46 325 } else {
jjg@46 326 print(getReturnType(d));
jjg@46 327 print(" ");
jjg@46 328 print(getName(m));
jjg@46 329 print(getParameterTypes(d, flags));
jjg@46 330 }
jjg@46 331
jjg@46 332 Attribute e_attr = m.attributes.get(Attribute.Exceptions);
jjg@46 333 if (e_attr != null) { // if there are generic exceptions, there must be erased exceptions
jjg@46 334 if (e_attr instanceof Exceptions_attribute) {
jjg@46 335 Exceptions_attribute exceptions = (Exceptions_attribute) e_attr;
jjg@46 336 if (options.compat) { // Bug XXXXXXX whitespace
jjg@46 337 if (!(options.showLineAndLocalVariableTables
jjg@46 338 || options.showDisassembled
jjg@46 339 || options.verbose
jjg@46 340 || options.showInternalSignatures
jjg@46 341 || options.showAllAttrs)) {
jjg@46 342 print(" ");
jjg@46 343 }
jjg@46 344 print(" ");
jjg@46 345 }
jjg@46 346 print(" throws ");
jjg@46 347 if (methodExceptions != null) { // use generic list if available
jjg@46 348 writeList("", methodExceptions, "");
jjg@46 349 } else {
jjg@46 350 for (int i = 0; i < exceptions.number_of_exceptions; i++) {
jjg@46 351 if (i > 0)
jjg@46 352 print(", ");
jjg@52 353 print(getJavaException(exceptions, i));
jjg@46 354 }
jjg@46 355 }
jjg@46 356 } else {
jjg@46 357 report("Unexpected or invalid value for Exceptions attribute");
jjg@46 358 }
jjg@46 359 }
jjg@46 360
jjg@46 361 print(";");
jjg@46 362 println();
jjg@46 363
jjg@46 364 if (options.showInternalSignatures)
jjg@46 365 println(" Signature: " + getValue(m.descriptor));
jjg@46 366
jjg@46 367 if (options.verbose && !options.compat)
jjg@46 368 writeList(" flags: ", flags.getMethodFlags(), NEWLINE);
jjg@46 369
jjg@46 370 Code_attribute code = null;
jjg@46 371 Attribute c_attr = m.attributes.get(Attribute.Code);
jjg@46 372 if (c_attr != null) {
jjg@46 373 if (c_attr instanceof Code_attribute)
jjg@46 374 code = (Code_attribute) c_attr;
jjg@46 375 else
jjg@46 376 report("Unexpected or invalid value for Code attribute");
jjg@46 377 }
jjg@46 378
jjg@46 379 if (options.showDisassembled && !options.showAllAttrs) {
jjg@46 380 if (code != null) {
jjg@46 381 println(" Code:");
jjg@46 382 codeWriter.writeInstrs(code);
jjg@46 383 codeWriter.writeExceptionTable(code);
jjg@46 384 }
jjg@46 385 println();
jjg@46 386 }
jjg@46 387
jjg@46 388 if (options.showLineAndLocalVariableTables) {
jjg@46 389 if (code != null)
jjg@46 390 attrWriter.write(code, code.attributes.get(Attribute.LineNumberTable), constant_pool);
jjg@46 391 println();
jjg@46 392 if (code != null)
jjg@46 393 attrWriter.write(code, code.attributes.get(Attribute.LocalVariableTable), constant_pool);
jjg@46 394 println();
jjg@46 395 println();
jjg@46 396 }
jjg@46 397
jjg@46 398 if (options.showAllAttrs) {
jjg@46 399 Attribute[] attrs = m.attributes.attrs;
jjg@46 400 for (Attribute attr: attrs)
jjg@46 401 attrWriter.write(m, attr, constant_pool);
jjg@46 402
jjg@46 403 // // the following condition is to mimic old javap
jjg@46 404 // if (!(attrs.length > 0 &&
jjg@46 405 // attrs[attrs.length - 1] instanceof Exceptions_attribute))
jjg@46 406 println();
jjg@46 407 }
jjg@46 408 }
jjg@46 409
jjg@46 410 void writeModifiers(Collection<String> items) {
jjg@46 411 for (Object item: items) {
jjg@46 412 print(item);
jjg@46 413 print(" ");
jjg@46 414 }
jjg@46 415 }
jjg@46 416
jjg@46 417 void writeList(String prefix, Collection<?> items, String suffix) {
jjg@46 418 print(prefix);
jjg@46 419 String sep = "";
jjg@46 420 for (Object item: items) {
jjg@46 421 print(sep);
jjg@46 422 print(item);
jjg@46 423 sep = ", ";
jjg@46 424 }
jjg@46 425 print(suffix);
jjg@46 426 }
jjg@46 427
jjg@46 428 void writeListIfNotEmpty(String prefix, List<?> items, String suffix) {
jjg@46 429 if (items != null && items.size() > 0)
jjg@46 430 writeList(prefix, items, suffix);
jjg@46 431 }
jjg@46 432
jjg@46 433 Signature_attribute getSignature(Attributes attributes) {
jjg@46 434 if (options.compat) // javap does not recognize recent attributes
jjg@46 435 return null;
jjg@46 436 return (Signature_attribute) attributes.get(Attribute.Signature);
jjg@46 437 }
jjg@46 438
jjg@46 439 String adjustVarargs(AccessFlags flags, String params) {
jjg@46 440 if (flags.is(ACC_VARARGS) && !options.compat) {
jjg@46 441 int i = params.lastIndexOf("[]");
jjg@46 442 if (i > 0)
jjg@46 443 return params.substring(0, i) + "..." + params.substring(i+2);
jjg@46 444 }
jjg@46 445
jjg@46 446 return params;
jjg@46 447 }
jjg@46 448
jjg@46 449 String getJavaName(ClassFile cf) {
jjg@46 450 try {
jjg@46 451 return getJavaName(cf.getName());
jjg@46 452 } catch (ConstantPoolException e) {
jjg@46 453 return report(e);
jjg@46 454 }
jjg@46 455 }
jjg@46 456
jjg@46 457 String getJavaSuperclassName(ClassFile cf) {
jjg@46 458 try {
jjg@46 459 return getJavaName(cf.getSuperclassName());
jjg@46 460 } catch (ConstantPoolException e) {
jjg@46 461 return report(e);
jjg@46 462 }
jjg@46 463 }
jjg@46 464
jjg@46 465 String getJavaInterfaceName(ClassFile cf, int index) {
jjg@46 466 try {
jjg@46 467 return getJavaName(cf.getInterfaceName(index));
jjg@46 468 } catch (ConstantPoolException e) {
jjg@46 469 return report(e);
jjg@46 470 }
jjg@46 471 }
jjg@46 472
jjg@46 473 String getFieldType(Descriptor d) {
jjg@46 474 try {
jjg@46 475 return d.getFieldType(constant_pool);
jjg@46 476 } catch (ConstantPoolException e) {
jjg@46 477 return report(e);
jjg@46 478 } catch (DescriptorException e) {
jjg@46 479 return report(e);
jjg@46 480 }
jjg@46 481 }
jjg@46 482
jjg@46 483 String getReturnType(Descriptor d) {
jjg@46 484 try {
jjg@46 485 return d.getReturnType(constant_pool);
jjg@46 486 } catch (ConstantPoolException e) {
jjg@46 487 return report(e);
jjg@46 488 } catch (DescriptorException e) {
jjg@46 489 return report(e);
jjg@46 490 }
jjg@46 491 }
jjg@46 492
jjg@46 493 String getParameterTypes(Descriptor d, AccessFlags flags) {
jjg@46 494 try {
jjg@46 495 return adjustVarargs(flags, d.getParameterTypes(constant_pool));
jjg@46 496 } catch (ConstantPoolException e) {
jjg@46 497 return report(e);
jjg@46 498 } catch (DescriptorException e) {
jjg@46 499 return report(e);
jjg@46 500 }
jjg@46 501 }
jjg@46 502
jjg@52 503 String getJavaException(Exceptions_attribute attr, int index) {
jjg@52 504 try {
jjg@52 505 return getJavaName(attr.getException(index, constant_pool));
jjg@52 506 } catch (ConstantPoolException e) {
jjg@52 507 return report(e);
jjg@52 508 }
jjg@52 509 }
jjg@52 510
jjg@46 511 String getValue(Descriptor d) {
jjg@46 512 try {
jjg@46 513 return d.getValue(constant_pool);
jjg@46 514 } catch (ConstantPoolException e) {
jjg@46 515 return report(e);
jjg@46 516 }
jjg@46 517 }
jjg@46 518
jjg@46 519 String getFieldName(Field f) {
jjg@46 520 try {
jjg@46 521 return f.getName(constant_pool);
jjg@46 522 } catch (ConstantPoolException e) {
jjg@46 523 return report(e);
jjg@46 524 }
jjg@46 525 }
jjg@46 526
jjg@46 527 String getName(Method m) {
jjg@46 528 try {
jjg@46 529 return m.getName(constant_pool);
jjg@46 530 } catch (ConstantPoolException e) {
jjg@46 531 return report(e);
jjg@46 532 }
jjg@46 533 }
jjg@46 534
jjg@46 535 static String getJavaName(String name) {
jjg@46 536 return name.replace('/', '.');
jjg@46 537 }
jjg@46 538
jjg@46 539 String getSourceFile(SourceFile_attribute attr) {
jjg@46 540 try {
jjg@46 541 return attr.getSourceFile(constant_pool);
jjg@46 542 } catch (ConstantPoolException e) {
jjg@46 543 return report(e);
jjg@46 544 }
jjg@46 545 }
jjg@46 546
jjg@87 547 /**
jjg@87 548 * Get the value of an entry in the constant pool as a Java constant.
jjg@87 549 * Characters and booleans are represented by CONSTANT_Intgere entries.
jjg@87 550 * Character and string values are processed to escape characters outside
jjg@87 551 * the basic printable ASCII set.
jjg@87 552 * @param d the descriptor, giving the expected type of the constant
jjg@87 553 * @param index the index of the value in the constant pool
jjg@87 554 * @return a printable string containing the value of the constant.
jjg@87 555 */
jjg@87 556 String getConstantValue(Descriptor d, int index) {
jjg@87 557 try {
jjg@87 558 ConstantPool.CPInfo cpInfo = constant_pool.get(index);
jjg@87 559
jjg@87 560 switch (cpInfo.getTag()) {
jjg@87 561 case ConstantPool.CONSTANT_Integer: {
jjg@87 562 ConstantPool.CONSTANT_Integer_info info =
jjg@87 563 (ConstantPool.CONSTANT_Integer_info) cpInfo;
jjg@87 564 String t = d.getValue(constant_pool);
jjg@87 565 if (t.equals("C")) { // character
jjg@87 566 return getConstantCharValue((char) info.value);
jjg@87 567 } else if (t.equals("Z")) { // boolean
jjg@87 568 return String.valueOf(info.value == 1);
jjg@87 569 } else { // other: assume integer
jjg@87 570 return String.valueOf(info.value);
jjg@87 571 }
jjg@87 572 }
jjg@87 573
jjg@87 574 case ConstantPool.CONSTANT_String: {
jjg@87 575 ConstantPool.CONSTANT_String_info info =
jjg@87 576 (ConstantPool.CONSTANT_String_info) cpInfo;
jjg@87 577 return getConstantStringValue(info.getString());
jjg@87 578 }
jjg@87 579
jjg@87 580 default:
jjg@87 581 return constantWriter.stringValue(cpInfo);
jjg@87 582 }
jjg@87 583 } catch (ConstantPoolException e) {
jjg@87 584 return "#" + index;
jjg@87 585 }
jjg@87 586 }
jjg@87 587
jjg@87 588 private String getConstantCharValue(char c) {
jjg@87 589 StringBuilder sb = new StringBuilder();
jjg@87 590 sb.append('\'');
jjg@87 591 sb.append(esc(c, '\''));
jjg@87 592 sb.append('\'');
jjg@87 593 return sb.toString();
jjg@87 594 }
jjg@87 595
jjg@87 596 private String getConstantStringValue(String s) {
jjg@87 597 StringBuilder sb = new StringBuilder();
jjg@87 598 sb.append("\"");
jjg@87 599 for (int i = 0; i < s.length(); i++) {
jjg@87 600 sb.append(esc(s.charAt(i), '"'));
jjg@87 601 }
jjg@87 602 sb.append("\"");
jjg@87 603 return sb.toString();
jjg@87 604 }
jjg@87 605
jjg@87 606 private String esc(char c, char quote) {
jjg@87 607 if (32 <= c && c <= 126 && c != quote)
jjg@87 608 return String.valueOf(c);
jjg@87 609 else switch (c) {
jjg@87 610 case '\b': return "\\b";
jjg@87 611 case '\n': return "\\n";
jjg@87 612 case '\t': return "\\t";
jjg@87 613 case '\f': return "\\f";
jjg@87 614 case '\r': return "\\r";
jjg@87 615 case '\\': return "\\\\";
jjg@87 616 case '\'': return "\\'";
jjg@87 617 case '\"': return "\\\"";
jjg@87 618 default: return String.format("\\u%04x", (int) c);
jjg@87 619 }
jjg@87 620 }
jjg@87 621
jjg@46 622 private Options options;
jjg@46 623 private AttributeWriter attrWriter;
jjg@46 624 private CodeWriter codeWriter;
jjg@46 625 private ConstantWriter constantWriter;
jjg@46 626 private ClassFile classFile;
jjg@88 627 private URI uri;
jjg@88 628 private long lastModified;
jjg@88 629 private String digestName;
jjg@88 630 private byte[] digest;
jjg@88 631 private int size;
jjg@46 632 private ConstantPool constant_pool;
jjg@46 633 private Method method;
jjg@46 634 private static final String NEWLINE = System.getProperty("line.separator", "\n");
jjg@46 635 }

mercurial