1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javap/ClassWriter.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,756 @@ 1.4 +/* 1.5 + * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.javap; 1.30 + 1.31 +import java.net.URI; 1.32 +import java.text.DateFormat; 1.33 +import java.util.Collection; 1.34 +import java.util.Date; 1.35 +import java.util.List; 1.36 + 1.37 +import com.sun.tools.classfile.AccessFlags; 1.38 +import com.sun.tools.classfile.Attribute; 1.39 +import com.sun.tools.classfile.Attributes; 1.40 +import com.sun.tools.classfile.ClassFile; 1.41 +import com.sun.tools.classfile.Code_attribute; 1.42 +import com.sun.tools.classfile.ConstantPool; 1.43 +import com.sun.tools.classfile.ConstantPoolException; 1.44 +import com.sun.tools.classfile.ConstantValue_attribute; 1.45 +import com.sun.tools.classfile.Descriptor; 1.46 +import com.sun.tools.classfile.DescriptorException; 1.47 +import com.sun.tools.classfile.Exceptions_attribute; 1.48 +import com.sun.tools.classfile.Field; 1.49 +import com.sun.tools.classfile.Method; 1.50 +import com.sun.tools.classfile.Signature; 1.51 +import com.sun.tools.classfile.Signature_attribute; 1.52 +import com.sun.tools.classfile.SourceFile_attribute; 1.53 +import com.sun.tools.classfile.Type; 1.54 +import com.sun.tools.classfile.Type.ArrayType; 1.55 +import com.sun.tools.classfile.Type.ClassSigType; 1.56 +import com.sun.tools.classfile.Type.ClassType; 1.57 +import com.sun.tools.classfile.Type.MethodType; 1.58 +import com.sun.tools.classfile.Type.SimpleType; 1.59 +import com.sun.tools.classfile.Type.TypeParamType; 1.60 +import com.sun.tools.classfile.Type.WildcardType; 1.61 + 1.62 +import static com.sun.tools.classfile.AccessFlags.*; 1.63 + 1.64 +/* 1.65 + * The main javap class to write the contents of a class file as text. 1.66 + * 1.67 + * <p><b>This is NOT part of any supported API. 1.68 + * If you write code that depends on this, you do so at your own risk. 1.69 + * This code and its internal interfaces are subject to change or 1.70 + * deletion without notice.</b> 1.71 + */ 1.72 +public class ClassWriter extends BasicWriter { 1.73 + static ClassWriter instance(Context context) { 1.74 + ClassWriter instance = context.get(ClassWriter.class); 1.75 + if (instance == null) 1.76 + instance = new ClassWriter(context); 1.77 + return instance; 1.78 + } 1.79 + 1.80 + protected ClassWriter(Context context) { 1.81 + super(context); 1.82 + context.put(ClassWriter.class, this); 1.83 + options = Options.instance(context); 1.84 + attrWriter = AttributeWriter.instance(context); 1.85 + codeWriter = CodeWriter.instance(context); 1.86 + constantWriter = ConstantWriter.instance(context); 1.87 + } 1.88 + 1.89 + void setDigest(String name, byte[] digest) { 1.90 + this.digestName = name; 1.91 + this.digest = digest; 1.92 + } 1.93 + 1.94 + void setFile(URI uri) { 1.95 + this.uri = uri; 1.96 + } 1.97 + 1.98 + void setFileSize(int size) { 1.99 + this.size = size; 1.100 + } 1.101 + 1.102 + void setLastModified(long lastModified) { 1.103 + this.lastModified = lastModified; 1.104 + } 1.105 + 1.106 + protected ClassFile getClassFile() { 1.107 + return classFile; 1.108 + } 1.109 + 1.110 + protected void setClassFile(ClassFile cf) { 1.111 + classFile = cf; 1.112 + constant_pool = classFile.constant_pool; 1.113 + } 1.114 + 1.115 + protected Method getMethod() { 1.116 + return method; 1.117 + } 1.118 + 1.119 + protected void setMethod(Method m) { 1.120 + method = m; 1.121 + } 1.122 + 1.123 + public void write(ClassFile cf) { 1.124 + setClassFile(cf); 1.125 + 1.126 + if (options.sysInfo || options.verbose) { 1.127 + if (uri != null) { 1.128 + if (uri.getScheme().equals("file")) 1.129 + println("Classfile " + uri.getPath()); 1.130 + else 1.131 + println("Classfile " + uri); 1.132 + } 1.133 + indent(+1); 1.134 + if (lastModified != -1) { 1.135 + Date lm = new Date(lastModified); 1.136 + DateFormat df = DateFormat.getDateInstance(); 1.137 + if (size > 0) { 1.138 + println("Last modified " + df.format(lm) + "; size " + size + " bytes"); 1.139 + } else { 1.140 + println("Last modified " + df.format(lm)); 1.141 + } 1.142 + } else if (size > 0) { 1.143 + println("Size " + size + " bytes"); 1.144 + } 1.145 + if (digestName != null && digest != null) { 1.146 + StringBuilder sb = new StringBuilder(); 1.147 + for (byte b: digest) 1.148 + sb.append(String.format("%02x", b)); 1.149 + println(digestName + " checksum " + sb); 1.150 + } 1.151 + } 1.152 + 1.153 + Attribute sfa = cf.getAttribute(Attribute.SourceFile); 1.154 + if (sfa instanceof SourceFile_attribute) { 1.155 + println("Compiled from \"" + getSourceFile((SourceFile_attribute) sfa) + "\""); 1.156 + } 1.157 + 1.158 + if (options.sysInfo || options.verbose) { 1.159 + indent(-1); 1.160 + } 1.161 + 1.162 + String name = getJavaName(classFile); 1.163 + AccessFlags flags = cf.access_flags; 1.164 + 1.165 + writeModifiers(flags.getClassModifiers()); 1.166 + 1.167 + if (classFile.isClass()) 1.168 + print("class "); 1.169 + else if (classFile.isInterface()) 1.170 + print("interface "); 1.171 + 1.172 + print(name); 1.173 + 1.174 + Signature_attribute sigAttr = getSignature(cf.attributes); 1.175 + if (sigAttr == null) { 1.176 + // use info from class file header 1.177 + if (classFile.isClass() && classFile.super_class != 0 ) { 1.178 + String sn = getJavaSuperclassName(cf); 1.179 + if (!sn.equals("java.lang.Object")) { 1.180 + print(" extends "); 1.181 + print(sn); 1.182 + } 1.183 + } 1.184 + for (int i = 0; i < classFile.interfaces.length; i++) { 1.185 + print(i == 0 ? (classFile.isClass() ? " implements " : " extends ") : ","); 1.186 + print(getJavaInterfaceName(classFile, i)); 1.187 + } 1.188 + } else { 1.189 + try { 1.190 + Type t = sigAttr.getParsedSignature().getType(constant_pool); 1.191 + JavaTypePrinter p = new JavaTypePrinter(classFile.isInterface()); 1.192 + // The signature parser cannot disambiguate between a 1.193 + // FieldType and a ClassSignatureType that only contains a superclass type. 1.194 + if (t instanceof Type.ClassSigType) { 1.195 + print(p.print(t)); 1.196 + } else if (options.verbose || !t.isObject()) { 1.197 + print(" extends "); 1.198 + print(p.print(t)); 1.199 + } 1.200 + } catch (ConstantPoolException e) { 1.201 + print(report(e)); 1.202 + } 1.203 + } 1.204 + 1.205 + if (options.verbose) { 1.206 + println(); 1.207 + indent(+1); 1.208 + println("minor version: " + cf.minor_version); 1.209 + println("major version: " + cf.major_version); 1.210 + writeList("flags: ", flags.getClassFlags(), "\n"); 1.211 + indent(-1); 1.212 + constantWriter.writeConstantPool(); 1.213 + } else { 1.214 + print(" "); 1.215 + } 1.216 + 1.217 + println("{"); 1.218 + indent(+1); 1.219 + writeFields(); 1.220 + writeMethods(); 1.221 + indent(-1); 1.222 + println("}"); 1.223 + 1.224 + if (options.verbose) { 1.225 + attrWriter.write(cf, cf.attributes, constant_pool); 1.226 + } 1.227 + } 1.228 + // where 1.229 + class JavaTypePrinter implements Type.Visitor<StringBuilder,StringBuilder> { 1.230 + boolean isInterface; 1.231 + 1.232 + JavaTypePrinter(boolean isInterface) { 1.233 + this.isInterface = isInterface; 1.234 + } 1.235 + 1.236 + String print(Type t) { 1.237 + return t.accept(this, new StringBuilder()).toString(); 1.238 + } 1.239 + 1.240 + String printTypeArgs(List<? extends TypeParamType> typeParamTypes) { 1.241 + StringBuilder builder = new StringBuilder(); 1.242 + appendIfNotEmpty(builder, "<", typeParamTypes, "> "); 1.243 + return builder.toString(); 1.244 + } 1.245 + 1.246 + public StringBuilder visitSimpleType(SimpleType type, StringBuilder sb) { 1.247 + sb.append(getJavaName(type.name)); 1.248 + return sb; 1.249 + } 1.250 + 1.251 + public StringBuilder visitArrayType(ArrayType type, StringBuilder sb) { 1.252 + append(sb, type.elemType); 1.253 + sb.append("[]"); 1.254 + return sb; 1.255 + } 1.256 + 1.257 + public StringBuilder visitMethodType(MethodType type, StringBuilder sb) { 1.258 + appendIfNotEmpty(sb, "<", type.typeParamTypes, "> "); 1.259 + append(sb, type.returnType); 1.260 + append(sb, " (", type.paramTypes, ")"); 1.261 + appendIfNotEmpty(sb, " throws ", type.throwsTypes, ""); 1.262 + return sb; 1.263 + } 1.264 + 1.265 + public StringBuilder visitClassSigType(ClassSigType type, StringBuilder sb) { 1.266 + appendIfNotEmpty(sb, "<", type.typeParamTypes, ">"); 1.267 + if (isInterface) { 1.268 + appendIfNotEmpty(sb, " extends ", type.superinterfaceTypes, ""); 1.269 + } else { 1.270 + if (type.superclassType != null 1.271 + && (options.verbose || !type.superclassType.isObject())) { 1.272 + sb.append(" extends "); 1.273 + append(sb, type.superclassType); 1.274 + } 1.275 + appendIfNotEmpty(sb, " implements ", type.superinterfaceTypes, ""); 1.276 + } 1.277 + return sb; 1.278 + } 1.279 + 1.280 + public StringBuilder visitClassType(ClassType type, StringBuilder sb) { 1.281 + if (type.outerType != null) { 1.282 + append(sb, type.outerType); 1.283 + sb.append("."); 1.284 + } 1.285 + sb.append(getJavaName(type.name)); 1.286 + appendIfNotEmpty(sb, "<", type.typeArgs, ">"); 1.287 + return sb; 1.288 + } 1.289 + 1.290 + public StringBuilder visitTypeParamType(TypeParamType type, StringBuilder sb) { 1.291 + sb.append(type.name); 1.292 + String sep = " extends "; 1.293 + if (type.classBound != null 1.294 + && (options.verbose || !type.classBound.isObject())) { 1.295 + sb.append(sep); 1.296 + append(sb, type.classBound); 1.297 + sep = " & "; 1.298 + } 1.299 + if (type.interfaceBounds != null) { 1.300 + for (Type bound: type.interfaceBounds) { 1.301 + sb.append(sep); 1.302 + append(sb, bound); 1.303 + sep = " & "; 1.304 + } 1.305 + } 1.306 + return sb; 1.307 + } 1.308 + 1.309 + public StringBuilder visitWildcardType(WildcardType type, StringBuilder sb) { 1.310 + switch (type.kind) { 1.311 + case UNBOUNDED: 1.312 + sb.append("?"); 1.313 + break; 1.314 + case EXTENDS: 1.315 + sb.append("? extends "); 1.316 + append(sb, type.boundType); 1.317 + break; 1.318 + case SUPER: 1.319 + sb.append("? super "); 1.320 + append(sb, type.boundType); 1.321 + break; 1.322 + default: 1.323 + throw new AssertionError(); 1.324 + } 1.325 + return sb; 1.326 + } 1.327 + 1.328 + private void append(StringBuilder sb, Type t) { 1.329 + t.accept(this, sb); 1.330 + } 1.331 + 1.332 + private void append(StringBuilder sb, String prefix, List<? extends Type> list, String suffix) { 1.333 + sb.append(prefix); 1.334 + String sep = ""; 1.335 + for (Type t: list) { 1.336 + sb.append(sep); 1.337 + append(sb, t); 1.338 + sep = ", "; 1.339 + } 1.340 + sb.append(suffix); 1.341 + } 1.342 + 1.343 + private void appendIfNotEmpty(StringBuilder sb, String prefix, List<? extends Type> list, String suffix) { 1.344 + if (!isEmpty(list)) 1.345 + append(sb, prefix, list, suffix); 1.346 + } 1.347 + 1.348 + private boolean isEmpty(List<? extends Type> list) { 1.349 + return (list == null || list.isEmpty()); 1.350 + } 1.351 + } 1.352 + 1.353 + protected void writeFields() { 1.354 + for (Field f: classFile.fields) { 1.355 + writeField(f); 1.356 + } 1.357 + } 1.358 + 1.359 + protected void writeField(Field f) { 1.360 + if (!options.checkAccess(f.access_flags)) 1.361 + return; 1.362 + 1.363 + AccessFlags flags = f.access_flags; 1.364 + writeModifiers(flags.getFieldModifiers()); 1.365 + Signature_attribute sigAttr = getSignature(f.attributes); 1.366 + if (sigAttr == null) 1.367 + print(getJavaFieldType(f.descriptor)); 1.368 + else { 1.369 + try { 1.370 + Type t = sigAttr.getParsedSignature().getType(constant_pool); 1.371 + print(getJavaName(t.toString())); 1.372 + } catch (ConstantPoolException e) { 1.373 + // report error? 1.374 + // fall back on non-generic descriptor 1.375 + print(getJavaFieldType(f.descriptor)); 1.376 + } 1.377 + } 1.378 + print(" "); 1.379 + print(getFieldName(f)); 1.380 + if (options.showConstants) { 1.381 + Attribute a = f.attributes.get(Attribute.ConstantValue); 1.382 + if (a instanceof ConstantValue_attribute) { 1.383 + print(" = "); 1.384 + ConstantValue_attribute cv = (ConstantValue_attribute) a; 1.385 + print(getConstantValue(f.descriptor, cv.constantvalue_index)); 1.386 + } 1.387 + } 1.388 + print(";"); 1.389 + println(); 1.390 + 1.391 + indent(+1); 1.392 + 1.393 + boolean showBlank = false; 1.394 + 1.395 + if (options.showDescriptors) 1.396 + println("descriptor: " + getValue(f.descriptor)); 1.397 + 1.398 + if (options.verbose) 1.399 + writeList("flags: ", flags.getFieldFlags(), "\n"); 1.400 + 1.401 + if (options.showAllAttrs) { 1.402 + for (Attribute attr: f.attributes) 1.403 + attrWriter.write(f, attr, constant_pool); 1.404 + showBlank = true; 1.405 + } 1.406 + 1.407 + indent(-1); 1.408 + 1.409 + if (showBlank || options.showDisassembled || options.showLineAndLocalVariableTables) 1.410 + println(); 1.411 + } 1.412 + 1.413 + protected void writeMethods() { 1.414 + for (Method m: classFile.methods) 1.415 + writeMethod(m); 1.416 + setPendingNewline(false); 1.417 + } 1.418 + 1.419 + protected void writeMethod(Method m) { 1.420 + if (!options.checkAccess(m.access_flags)) 1.421 + return; 1.422 + 1.423 + method = m; 1.424 + 1.425 + AccessFlags flags = m.access_flags; 1.426 + 1.427 + Descriptor d; 1.428 + Type.MethodType methodType; 1.429 + List<? extends Type> methodExceptions; 1.430 + 1.431 + Signature_attribute sigAttr = getSignature(m.attributes); 1.432 + if (sigAttr == null) { 1.433 + d = m.descriptor; 1.434 + methodType = null; 1.435 + methodExceptions = null; 1.436 + } else { 1.437 + Signature methodSig = sigAttr.getParsedSignature(); 1.438 + d = methodSig; 1.439 + try { 1.440 + methodType = (Type.MethodType) methodSig.getType(constant_pool); 1.441 + methodExceptions = methodType.throwsTypes; 1.442 + if (methodExceptions != null && methodExceptions.isEmpty()) 1.443 + methodExceptions = null; 1.444 + } catch (ConstantPoolException e) { 1.445 + // report error? 1.446 + // fall back on standard descriptor 1.447 + methodType = null; 1.448 + methodExceptions = null; 1.449 + } 1.450 + } 1.451 + 1.452 + writeModifiers(flags.getMethodModifiers()); 1.453 + if (methodType != null) { 1.454 + print(new JavaTypePrinter(false).printTypeArgs(methodType.typeParamTypes)); 1.455 + } 1.456 + if (getName(m).equals("<init>")) { 1.457 + print(getJavaName(classFile)); 1.458 + print(getJavaParameterTypes(d, flags)); 1.459 + } else if (getName(m).equals("<clinit>")) { 1.460 + print("{}"); 1.461 + } else { 1.462 + print(getJavaReturnType(d)); 1.463 + print(" "); 1.464 + print(getName(m)); 1.465 + print(getJavaParameterTypes(d, flags)); 1.466 + } 1.467 + 1.468 + Attribute e_attr = m.attributes.get(Attribute.Exceptions); 1.469 + if (e_attr != null) { // if there are generic exceptions, there must be erased exceptions 1.470 + if (e_attr instanceof Exceptions_attribute) { 1.471 + Exceptions_attribute exceptions = (Exceptions_attribute) e_attr; 1.472 + print(" throws "); 1.473 + if (methodExceptions != null) { // use generic list if available 1.474 + writeList("", methodExceptions, ""); 1.475 + } else { 1.476 + for (int i = 0; i < exceptions.number_of_exceptions; i++) { 1.477 + if (i > 0) 1.478 + print(", "); 1.479 + print(getJavaException(exceptions, i)); 1.480 + } 1.481 + } 1.482 + } else { 1.483 + report("Unexpected or invalid value for Exceptions attribute"); 1.484 + } 1.485 + } 1.486 + 1.487 + println(";"); 1.488 + 1.489 + indent(+1); 1.490 + 1.491 + if (options.showDescriptors) { 1.492 + println("descriptor: " + getValue(m.descriptor)); 1.493 + } 1.494 + 1.495 + if (options.verbose) { 1.496 + writeList("flags: ", flags.getMethodFlags(), "\n"); 1.497 + } 1.498 + 1.499 + Code_attribute code = null; 1.500 + Attribute c_attr = m.attributes.get(Attribute.Code); 1.501 + if (c_attr != null) { 1.502 + if (c_attr instanceof Code_attribute) 1.503 + code = (Code_attribute) c_attr; 1.504 + else 1.505 + report("Unexpected or invalid value for Code attribute"); 1.506 + } 1.507 + 1.508 + if (options.showAllAttrs) { 1.509 + Attribute[] attrs = m.attributes.attrs; 1.510 + for (Attribute attr: attrs) 1.511 + attrWriter.write(m, attr, constant_pool); 1.512 + } else if (code != null) { 1.513 + if (options.showDisassembled) { 1.514 + println("Code:"); 1.515 + codeWriter.writeInstrs(code); 1.516 + codeWriter.writeExceptionTable(code); 1.517 + } 1.518 + 1.519 + if (options.showLineAndLocalVariableTables) { 1.520 + attrWriter.write(code, code.attributes.get(Attribute.LineNumberTable), constant_pool); 1.521 + attrWriter.write(code, code.attributes.get(Attribute.LocalVariableTable), constant_pool); 1.522 + } 1.523 + } 1.524 + 1.525 + indent(-1); 1.526 + 1.527 + // set pendingNewline to write a newline before the next method (if any) 1.528 + // if a separator is desired 1.529 + setPendingNewline( 1.530 + options.showDisassembled || 1.531 + options.showAllAttrs || 1.532 + options.showDescriptors || 1.533 + options.showLineAndLocalVariableTables || 1.534 + options.verbose); 1.535 + } 1.536 + 1.537 + void writeModifiers(Collection<String> items) { 1.538 + for (Object item: items) { 1.539 + print(item); 1.540 + print(" "); 1.541 + } 1.542 + } 1.543 + 1.544 + void writeList(String prefix, Collection<?> items, String suffix) { 1.545 + print(prefix); 1.546 + String sep = ""; 1.547 + for (Object item: items) { 1.548 + print(sep); 1.549 + print(item); 1.550 + sep = ", "; 1.551 + } 1.552 + print(suffix); 1.553 + } 1.554 + 1.555 + void writeListIfNotEmpty(String prefix, List<?> items, String suffix) { 1.556 + if (items != null && items.size() > 0) 1.557 + writeList(prefix, items, suffix); 1.558 + } 1.559 + 1.560 + Signature_attribute getSignature(Attributes attributes) { 1.561 + return (Signature_attribute) attributes.get(Attribute.Signature); 1.562 + } 1.563 + 1.564 + String adjustVarargs(AccessFlags flags, String params) { 1.565 + if (flags.is(ACC_VARARGS)) { 1.566 + int i = params.lastIndexOf("[]"); 1.567 + if (i > 0) 1.568 + return params.substring(0, i) + "..." + params.substring(i+2); 1.569 + } 1.570 + 1.571 + return params; 1.572 + } 1.573 + 1.574 + String getJavaName(ClassFile cf) { 1.575 + try { 1.576 + return getJavaName(cf.getName()); 1.577 + } catch (ConstantPoolException e) { 1.578 + return report(e); 1.579 + } 1.580 + } 1.581 + 1.582 + String getJavaSuperclassName(ClassFile cf) { 1.583 + try { 1.584 + return getJavaName(cf.getSuperclassName()); 1.585 + } catch (ConstantPoolException e) { 1.586 + return report(e); 1.587 + } 1.588 + } 1.589 + 1.590 + String getJavaInterfaceName(ClassFile cf, int index) { 1.591 + try { 1.592 + return getJavaName(cf.getInterfaceName(index)); 1.593 + } catch (ConstantPoolException e) { 1.594 + return report(e); 1.595 + } 1.596 + } 1.597 + 1.598 + String getJavaFieldType(Descriptor d) { 1.599 + try { 1.600 + return getJavaName(d.getFieldType(constant_pool)); 1.601 + } catch (ConstantPoolException e) { 1.602 + return report(e); 1.603 + } catch (DescriptorException e) { 1.604 + return report(e); 1.605 + } 1.606 + } 1.607 + 1.608 + String getJavaReturnType(Descriptor d) { 1.609 + try { 1.610 + return getJavaName(d.getReturnType(constant_pool)); 1.611 + } catch (ConstantPoolException e) { 1.612 + return report(e); 1.613 + } catch (DescriptorException e) { 1.614 + return report(e); 1.615 + } 1.616 + } 1.617 + 1.618 + String getJavaParameterTypes(Descriptor d, AccessFlags flags) { 1.619 + try { 1.620 + return getJavaName(adjustVarargs(flags, d.getParameterTypes(constant_pool))); 1.621 + } catch (ConstantPoolException e) { 1.622 + return report(e); 1.623 + } catch (DescriptorException e) { 1.624 + return report(e); 1.625 + } 1.626 + } 1.627 + 1.628 + String getJavaException(Exceptions_attribute attr, int index) { 1.629 + try { 1.630 + return getJavaName(attr.getException(index, constant_pool)); 1.631 + } catch (ConstantPoolException e) { 1.632 + return report(e); 1.633 + } 1.634 + } 1.635 + 1.636 + String getValue(Descriptor d) { 1.637 + try { 1.638 + return d.getValue(constant_pool); 1.639 + } catch (ConstantPoolException e) { 1.640 + return report(e); 1.641 + } 1.642 + } 1.643 + 1.644 + String getFieldName(Field f) { 1.645 + try { 1.646 + return f.getName(constant_pool); 1.647 + } catch (ConstantPoolException e) { 1.648 + return report(e); 1.649 + } 1.650 + } 1.651 + 1.652 + String getName(Method m) { 1.653 + try { 1.654 + return m.getName(constant_pool); 1.655 + } catch (ConstantPoolException e) { 1.656 + return report(e); 1.657 + } 1.658 + } 1.659 + 1.660 + static String getJavaName(String name) { 1.661 + return name.replace('/', '.'); 1.662 + } 1.663 + 1.664 + String getSourceFile(SourceFile_attribute attr) { 1.665 + try { 1.666 + return attr.getSourceFile(constant_pool); 1.667 + } catch (ConstantPoolException e) { 1.668 + return report(e); 1.669 + } 1.670 + } 1.671 + 1.672 + /** 1.673 + * Get the value of an entry in the constant pool as a Java constant. 1.674 + * Characters and booleans are represented by CONSTANT_Intgere entries. 1.675 + * Character and string values are processed to escape characters outside 1.676 + * the basic printable ASCII set. 1.677 + * @param d the descriptor, giving the expected type of the constant 1.678 + * @param index the index of the value in the constant pool 1.679 + * @return a printable string containing the value of the constant. 1.680 + */ 1.681 + String getConstantValue(Descriptor d, int index) { 1.682 + try { 1.683 + ConstantPool.CPInfo cpInfo = constant_pool.get(index); 1.684 + 1.685 + switch (cpInfo.getTag()) { 1.686 + case ConstantPool.CONSTANT_Integer: { 1.687 + ConstantPool.CONSTANT_Integer_info info = 1.688 + (ConstantPool.CONSTANT_Integer_info) cpInfo; 1.689 + String t = d.getValue(constant_pool); 1.690 + if (t.equals("C")) { // character 1.691 + return getConstantCharValue((char) info.value); 1.692 + } else if (t.equals("Z")) { // boolean 1.693 + return String.valueOf(info.value == 1); 1.694 + } else { // other: assume integer 1.695 + return String.valueOf(info.value); 1.696 + } 1.697 + } 1.698 + 1.699 + case ConstantPool.CONSTANT_String: { 1.700 + ConstantPool.CONSTANT_String_info info = 1.701 + (ConstantPool.CONSTANT_String_info) cpInfo; 1.702 + return getConstantStringValue(info.getString()); 1.703 + } 1.704 + 1.705 + default: 1.706 + return constantWriter.stringValue(cpInfo); 1.707 + } 1.708 + } catch (ConstantPoolException e) { 1.709 + return "#" + index; 1.710 + } 1.711 + } 1.712 + 1.713 + private String getConstantCharValue(char c) { 1.714 + StringBuilder sb = new StringBuilder(); 1.715 + sb.append('\''); 1.716 + sb.append(esc(c, '\'')); 1.717 + sb.append('\''); 1.718 + return sb.toString(); 1.719 + } 1.720 + 1.721 + private String getConstantStringValue(String s) { 1.722 + StringBuilder sb = new StringBuilder(); 1.723 + sb.append("\""); 1.724 + for (int i = 0; i < s.length(); i++) { 1.725 + sb.append(esc(s.charAt(i), '"')); 1.726 + } 1.727 + sb.append("\""); 1.728 + return sb.toString(); 1.729 + } 1.730 + 1.731 + private String esc(char c, char quote) { 1.732 + if (32 <= c && c <= 126 && c != quote) 1.733 + return String.valueOf(c); 1.734 + else switch (c) { 1.735 + case '\b': return "\\b"; 1.736 + case '\n': return "\\n"; 1.737 + case '\t': return "\\t"; 1.738 + case '\f': return "\\f"; 1.739 + case '\r': return "\\r"; 1.740 + case '\\': return "\\\\"; 1.741 + case '\'': return "\\'"; 1.742 + case '\"': return "\\\""; 1.743 + default: return String.format("\\u%04x", (int) c); 1.744 + } 1.745 + } 1.746 + 1.747 + private Options options; 1.748 + private AttributeWriter attrWriter; 1.749 + private CodeWriter codeWriter; 1.750 + private ConstantWriter constantWriter; 1.751 + private ClassFile classFile; 1.752 + private URI uri; 1.753 + private long lastModified; 1.754 + private String digestName; 1.755 + private byte[] digest; 1.756 + private int size; 1.757 + private ConstantPool constant_pool; 1.758 + private Method method; 1.759 +}