45N/A/*
952N/A * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
45N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45N/A *
45N/A * This code is free software; you can redistribute it and/or modify it
45N/A * under the terms of the GNU General Public License version 2 only, as
553N/A * published by the Free Software Foundation. Oracle designates this
45N/A * particular file as subject to the "Classpath" exception as provided
553N/A * by Oracle in the LICENSE file that accompanied this code.
45N/A *
45N/A * This code is distributed in the hope that it will be useful, but WITHOUT
45N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
45N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
45N/A * version 2 for more details (a copy is included in the LICENSE file that
45N/A * accompanied this code).
45N/A *
45N/A * You should have received a copy of the GNU General Public License version
45N/A * 2 along with this work; if not, write to the Free Software Foundation,
45N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
45N/A *
553N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
553N/A * or visit www.oracle.com if you need additional information or have any
553N/A * questions.
45N/A */
45N/A
45N/Apackage com.sun.tools.javap;
45N/A
87N/Aimport java.net.URI;
282N/Aimport java.text.DateFormat;
45N/Aimport java.util.Collection;
282N/Aimport java.util.Date;
45N/Aimport java.util.List;
45N/A
45N/Aimport com.sun.tools.classfile.AccessFlags;
45N/Aimport com.sun.tools.classfile.Attribute;
45N/Aimport com.sun.tools.classfile.Attributes;
45N/Aimport com.sun.tools.classfile.ClassFile;
45N/Aimport com.sun.tools.classfile.Code_attribute;
45N/Aimport com.sun.tools.classfile.ConstantPool;
45N/Aimport com.sun.tools.classfile.ConstantPoolException;
86N/Aimport com.sun.tools.classfile.ConstantValue_attribute;
45N/Aimport com.sun.tools.classfile.Descriptor;
45N/Aimport com.sun.tools.classfile.DescriptorException;
45N/Aimport com.sun.tools.classfile.Exceptions_attribute;
45N/Aimport com.sun.tools.classfile.Field;
45N/Aimport com.sun.tools.classfile.Method;
45N/Aimport com.sun.tools.classfile.Signature;
45N/Aimport com.sun.tools.classfile.Signature_attribute;
45N/Aimport com.sun.tools.classfile.SourceFile_attribute;
45N/Aimport com.sun.tools.classfile.Type;
952N/Aimport com.sun.tools.classfile.Type.ArrayType;
952N/Aimport com.sun.tools.classfile.Type.ClassSigType;
952N/Aimport com.sun.tools.classfile.Type.ClassType;
952N/Aimport com.sun.tools.classfile.Type.MethodType;
952N/Aimport com.sun.tools.classfile.Type.SimpleType;
952N/Aimport com.sun.tools.classfile.Type.TypeParamType;
952N/Aimport com.sun.tools.classfile.Type.WildcardType;
45N/A
45N/Aimport static com.sun.tools.classfile.AccessFlags.*;
45N/A
45N/A/*
45N/A * The main javap class to write the contents of a class file as text.
45N/A *
580N/A * <p><b>This is NOT part of any supported API.
580N/A * If you write code that depends on this, you do so at your own risk.
45N/A * This code and its internal interfaces are subject to change or
45N/A * deletion without notice.</b>
45N/A */
45N/Apublic class ClassWriter extends BasicWriter {
45N/A static ClassWriter instance(Context context) {
45N/A ClassWriter instance = context.get(ClassWriter.class);
45N/A if (instance == null)
45N/A instance = new ClassWriter(context);
45N/A return instance;
45N/A }
45N/A
45N/A protected ClassWriter(Context context) {
45N/A super(context);
45N/A context.put(ClassWriter.class, this);
45N/A options = Options.instance(context);
45N/A attrWriter = AttributeWriter.instance(context);
45N/A codeWriter = CodeWriter.instance(context);
45N/A constantWriter = ConstantWriter.instance(context);
45N/A }
45N/A
87N/A void setDigest(String name, byte[] digest) {
87N/A this.digestName = name;
87N/A this.digest = digest;
87N/A }
87N/A
87N/A void setFile(URI uri) {
87N/A this.uri = uri;
87N/A }
87N/A
87N/A void setFileSize(int size) {
87N/A this.size = size;
87N/A }
87N/A
87N/A void setLastModified(long lastModified) {
87N/A this.lastModified = lastModified;
87N/A }
87N/A
299N/A protected ClassFile getClassFile() {
45N/A return classFile;
45N/A }
45N/A
299N/A protected void setClassFile(ClassFile cf) {
299N/A classFile = cf;
299N/A constant_pool = classFile.constant_pool;
299N/A }
299N/A
299N/A protected Method getMethod() {
45N/A return method;
45N/A }
45N/A
299N/A protected void setMethod(Method m) {
299N/A method = m;
299N/A }
299N/A
45N/A public void write(ClassFile cf) {
299N/A setClassFile(cf);
45N/A
87N/A if ((options.sysInfo || options.verbose) && !options.compat) {
87N/A if (uri != null) {
87N/A if (uri.getScheme().equals("file"))
87N/A println("Classfile " + uri.getPath());
87N/A else
87N/A println("Classfile " + uri);
87N/A }
347N/A indent(+1);
87N/A if (lastModified != -1) {
87N/A Date lm = new Date(lastModified);
87N/A DateFormat df = DateFormat.getDateInstance();
87N/A if (size > 0) {
87N/A println("Last modified " + df.format(lm) + "; size " + size + " bytes");
87N/A } else {
87N/A println("Last modified " + df.format(lm));
87N/A }
87N/A } else if (size > 0) {
87N/A println("Size " + size + " bytes");
87N/A }
87N/A if (digestName != null && digest != null) {
87N/A StringBuilder sb = new StringBuilder();
87N/A for (byte b: digest)
87N/A sb.append(String.format("%02x", b));
87N/A println(digestName + " checksum " + sb);
87N/A }
87N/A }
87N/A
45N/A Attribute sfa = cf.getAttribute(Attribute.SourceFile);
45N/A if (sfa instanceof SourceFile_attribute) {
45N/A println("Compiled from \"" + getSourceFile((SourceFile_attribute) sfa) + "\"");
45N/A }
45N/A
347N/A if ((options.sysInfo || options.verbose) && !options.compat) {
347N/A indent(-1);
347N/A }
347N/A
45N/A String name = getJavaName(classFile);
45N/A AccessFlags flags = cf.access_flags;
45N/A
45N/A writeModifiers(flags.getClassModifiers());
45N/A
45N/A if (classFile.isClass())
45N/A print("class ");
45N/A else if (classFile.isInterface())
45N/A print("interface ");
45N/A
45N/A print(name);
45N/A
45N/A Signature_attribute sigAttr = getSignature(cf.attributes);
45N/A if (sigAttr == null) {
45N/A // use info from class file header
64N/A if (classFile.isClass() && classFile.super_class != 0 ) {
64N/A String sn = getJavaSuperclassName(cf);
952N/A if (!sn.equals("java.lang.Object")) {
952N/A print(" extends ");
952N/A print(sn);
952N/A }
45N/A }
45N/A for (int i = 0; i < classFile.interfaces.length; i++) {
45N/A print(i == 0 ? (classFile.isClass() ? " implements " : " extends ") : ",");
45N/A print(getJavaInterfaceName(classFile, i));
45N/A }
45N/A } else {
45N/A try {
45N/A Type t = sigAttr.getParsedSignature().getType(constant_pool);
952N/A JavaTypePrinter p = new JavaTypePrinter(classFile.isInterface());
45N/A // The signature parser cannot disambiguate between a
45N/A // FieldType and a ClassSignatureType that only contains a superclass type.
952N/A if (t instanceof Type.ClassSigType) {
952N/A print(p.print(t));
952N/A } else if (options.verbose || !t.isObject()) {
45N/A print(" extends ");
952N/A print(p.print(t));
45N/A }
45N/A } catch (ConstantPoolException e) {
45N/A print(report(e));
45N/A }
45N/A }
45N/A
45N/A if (options.verbose) {
45N/A println();
347N/A indent(+1);
45N/A attrWriter.write(cf, cf.attributes, constant_pool);
347N/A println("minor version: " + cf.minor_version);
347N/A println("major version: " + cf.major_version);
45N/A if (!options.compat)
347N/A writeList("flags: ", flags.getClassFlags(), NEWLINE);
347N/A indent(-1);
45N/A constantWriter.writeConstantPool();
45N/A } else {
347N/A print(" ");
45N/A }
45N/A
45N/A println("{");
347N/A indent(+1);
45N/A writeFields();
45N/A writeMethods();
347N/A indent(-1);
45N/A println("}");
45N/A }
952N/A // where
952N/A class JavaTypePrinter implements Type.Visitor<StringBuilder,StringBuilder> {
952N/A boolean isInterface;
952N/A
952N/A JavaTypePrinter(boolean isInterface) {
952N/A this.isInterface = isInterface;
952N/A }
952N/A
952N/A String print(Type t) {
952N/A return t.accept(this, new StringBuilder()).toString();
952N/A }
952N/A
952N/A public StringBuilder visitSimpleType(SimpleType type, StringBuilder sb) {
952N/A sb.append(getJavaName(type.name));
952N/A return sb;
952N/A }
952N/A
952N/A public StringBuilder visitArrayType(ArrayType type, StringBuilder sb) {
952N/A append(sb, type.elemType);
952N/A sb.append("[]");
952N/A return sb;
952N/A }
952N/A
952N/A public StringBuilder visitMethodType(MethodType type, StringBuilder sb) {
952N/A appendIfNotEmpty(sb, "<", type.typeParamTypes, "> ");
952N/A append(sb, type.returnType);
952N/A append(sb, " (", type.paramTypes, ")");
952N/A appendIfNotEmpty(sb, " throws ", type.throwsTypes, "");
952N/A return sb;
952N/A }
952N/A
952N/A public StringBuilder visitClassSigType(ClassSigType type, StringBuilder sb) {
952N/A appendIfNotEmpty(sb, "<", type.typeParamTypes, ">");
952N/A if (isInterface) {
952N/A appendIfNotEmpty(sb, " extends ", type.superinterfaceTypes, "");
952N/A } else {
952N/A if (type.superclassType != null
952N/A && (options.verbose || !type.superclassType.isObject())) {
952N/A sb.append(" extends ");
952N/A append(sb, type.superclassType);
952N/A }
952N/A appendIfNotEmpty(sb, " implements ", type.superinterfaceTypes, "");
952N/A }
952N/A return sb;
952N/A }
952N/A
952N/A public StringBuilder visitClassType(ClassType type, StringBuilder sb) {
952N/A if (type.outerType != null) {
952N/A append(sb, type.outerType);
952N/A sb.append(".");
952N/A }
952N/A sb.append(getJavaName(type.name));
952N/A appendIfNotEmpty(sb, "<", type.typeArgs, ">");
952N/A return sb;
952N/A }
952N/A
952N/A public StringBuilder visitTypeParamType(TypeParamType type, StringBuilder sb) {
952N/A sb.append(type.name);
952N/A String sep = " extends ";
952N/A if (type.classBound != null
952N/A && (options.verbose || !type.classBound.isObject())) {
952N/A sb.append(sep);
952N/A append(sb, type.classBound);
952N/A sep = " & ";
952N/A }
952N/A if (type.interfaceBounds != null) {
952N/A for (Type bound: type.interfaceBounds) {
952N/A sb.append(sep);
952N/A append(sb, bound);
952N/A sep = " & ";
952N/A }
952N/A }
952N/A return sb;
952N/A }
952N/A
952N/A public StringBuilder visitWildcardType(WildcardType type, StringBuilder sb) {
952N/A switch (type.kind) {
952N/A case UNBOUNDED:
952N/A sb.append("?");
952N/A break;
952N/A case EXTENDS:
952N/A sb.append("? extends ");
952N/A append(sb, type.boundType);
952N/A break;
952N/A case SUPER:
952N/A sb.append("? super ");
952N/A append(sb, type.boundType);
952N/A break;
952N/A default:
952N/A throw new AssertionError();
952N/A }
952N/A return sb;
952N/A }
952N/A
952N/A private void append(StringBuilder sb, Type t) {
952N/A t.accept(this, sb);
952N/A }
952N/A
952N/A private void append(StringBuilder sb, String prefix, List<? extends Type> list, String suffix) {
952N/A sb.append(prefix);
952N/A String sep = "";
952N/A for (Type t: list) {
952N/A sb.append(sep);
952N/A append(sb, t);
952N/A sep = ", ";
952N/A }
952N/A sb.append(suffix);
952N/A }
952N/A
952N/A private void appendIfNotEmpty(StringBuilder sb, String prefix, List<? extends Type> list, String suffix) {
952N/A if (!isEmpty(list))
952N/A append(sb, prefix, list, suffix);
952N/A }
952N/A
952N/A private boolean isEmpty(List<? extends Type> list) {
952N/A return (list == null || list.isEmpty());
952N/A }
952N/A }
45N/A
299N/A protected void writeFields() {
45N/A for (Field f: classFile.fields) {
45N/A writeField(f);
45N/A }
45N/A }
45N/A
299N/A protected void writeField(Field f) {
45N/A if (!options.checkAccess(f.access_flags))
45N/A return;
45N/A
45N/A AccessFlags flags = f.access_flags;
45N/A writeModifiers(flags.getFieldModifiers());
45N/A Signature_attribute sigAttr = getSignature(f.attributes);
45N/A if (sigAttr == null)
527N/A print(getJavaFieldType(f.descriptor));
45N/A else {
45N/A try {
45N/A Type t = sigAttr.getParsedSignature().getType(constant_pool);
527N/A print(getJavaName(t.toString()));
45N/A } catch (ConstantPoolException e) {
45N/A // report error?
45N/A // fall back on non-generic descriptor
527N/A print(getJavaFieldType(f.descriptor));
45N/A }
45N/A }
45N/A print(" ");
45N/A print(getFieldName(f));
86N/A if (options.showConstants && !options.compat) { // BUG 4111861 print static final field contents
86N/A Attribute a = f.attributes.get(Attribute.ConstantValue);
86N/A if (a instanceof ConstantValue_attribute) {
86N/A print(" = ");
86N/A ConstantValue_attribute cv = (ConstantValue_attribute) a;
86N/A print(getConstantValue(f.descriptor, cv.constantvalue_index));
86N/A }
86N/A }
45N/A print(";");
45N/A println();
45N/A
347N/A indent(+1);
347N/A
45N/A if (options.showInternalSignatures)
347N/A println("Signature: " + getValue(f.descriptor));
45N/A
45N/A if (options.verbose && !options.compat)
347N/A writeList("flags: ", flags.getFieldFlags(), NEWLINE);
45N/A
45N/A if (options.showAllAttrs) {
45N/A for (Attribute attr: f.attributes)
45N/A attrWriter.write(f, attr, constant_pool);
45N/A println();
45N/A }
45N/A
347N/A indent(-1);
347N/A
45N/A if (options.showDisassembled || options.showLineAndLocalVariableTables)
45N/A println();
45N/A }
45N/A
299N/A protected void writeMethods() {
45N/A for (Method m: classFile.methods)
45N/A writeMethod(m);
347N/A setPendingNewline(false);
45N/A }
45N/A
299N/A protected void writeMethod(Method m) {
45N/A if (!options.checkAccess(m.access_flags))
45N/A return;
45N/A
45N/A method = m;
45N/A
45N/A AccessFlags flags = m.access_flags;
45N/A
45N/A Descriptor d;
45N/A Type.MethodType methodType;
45N/A List<? extends Type> methodExceptions;
45N/A
45N/A Signature_attribute sigAttr = getSignature(m.attributes);
45N/A if (sigAttr == null) {
45N/A d = m.descriptor;
45N/A methodType = null;
45N/A methodExceptions = null;
45N/A } else {
45N/A Signature methodSig = sigAttr.getParsedSignature();
45N/A d = methodSig;
45N/A try {
45N/A methodType = (Type.MethodType) methodSig.getType(constant_pool);
45N/A methodExceptions = methodType.throwsTypes;
952N/A if (methodExceptions != null && methodExceptions.isEmpty())
45N/A methodExceptions = null;
45N/A } catch (ConstantPoolException e) {
45N/A // report error?
45N/A // fall back on standard descriptor
45N/A methodType = null;
45N/A methodExceptions = null;
45N/A }
45N/A }
45N/A
45N/A writeModifiers(flags.getMethodModifiers());
45N/A if (methodType != null) {
426N/A writeListIfNotEmpty("<", methodType.typeParamTypes, "> ");
45N/A }
45N/A if (getName(m).equals("<init>")) {
45N/A print(getJavaName(classFile));
527N/A print(getJavaParameterTypes(d, flags));
45N/A } else if (getName(m).equals("<clinit>")) {
45N/A print("{}");
45N/A } else {
527N/A print(getJavaReturnType(d));
45N/A print(" ");
45N/A print(getName(m));
527N/A print(getJavaParameterTypes(d, flags));
45N/A }
45N/A
45N/A Attribute e_attr = m.attributes.get(Attribute.Exceptions);
45N/A if (e_attr != null) { // if there are generic exceptions, there must be erased exceptions
45N/A if (e_attr instanceof Exceptions_attribute) {
45N/A Exceptions_attribute exceptions = (Exceptions_attribute) e_attr;
45N/A print(" throws ");
45N/A if (methodExceptions != null) { // use generic list if available
45N/A writeList("", methodExceptions, "");
45N/A } else {
45N/A for (int i = 0; i < exceptions.number_of_exceptions; i++) {
45N/A if (i > 0)
45N/A print(", ");
51N/A print(getJavaException(exceptions, i));
45N/A }
45N/A }
45N/A } else {
45N/A report("Unexpected or invalid value for Exceptions attribute");
45N/A }
45N/A }
45N/A
347N/A println(";");
347N/A
347N/A indent(+1);
45N/A
347N/A if (options.showInternalSignatures) {
347N/A println("Signature: " + getValue(m.descriptor));
347N/A }
45N/A
347N/A if (options.verbose && !options.compat) {
347N/A writeList("flags: ", flags.getMethodFlags(), NEWLINE);
347N/A }
45N/A
45N/A Code_attribute code = null;
45N/A Attribute c_attr = m.attributes.get(Attribute.Code);
45N/A if (c_attr != null) {
45N/A if (c_attr instanceof Code_attribute)
45N/A code = (Code_attribute) c_attr;
45N/A else
45N/A report("Unexpected or invalid value for Code attribute");
45N/A }
45N/A
45N/A if (options.showDisassembled && !options.showAllAttrs) {
45N/A if (code != null) {
347N/A println("Code:");
45N/A codeWriter.writeInstrs(code);
45N/A codeWriter.writeExceptionTable(code);
45N/A }
45N/A }
45N/A
45N/A if (options.showLineAndLocalVariableTables) {
347N/A if (code != null) {
45N/A attrWriter.write(code, code.attributes.get(Attribute.LineNumberTable), constant_pool);
45N/A attrWriter.write(code, code.attributes.get(Attribute.LocalVariableTable), constant_pool);
347N/A }
45N/A }
45N/A
45N/A if (options.showAllAttrs) {
45N/A Attribute[] attrs = m.attributes.attrs;
45N/A for (Attribute attr: attrs)
45N/A attrWriter.write(m, attr, constant_pool);
347N/A }
45N/A
347N/A indent(-1);
347N/A
347N/A // set pendingNewline to write a newline before the next method (if any)
347N/A // if a separator is desired
347N/A setPendingNewline(
347N/A options.showDisassembled ||
347N/A options.showAllAttrs ||
347N/A options.showInternalSignatures ||
347N/A options.showLineAndLocalVariableTables ||
347N/A options.verbose);
45N/A }
45N/A
45N/A void writeModifiers(Collection<String> items) {
45N/A for (Object item: items) {
45N/A print(item);
45N/A print(" ");
45N/A }
45N/A }
45N/A
45N/A void writeList(String prefix, Collection<?> items, String suffix) {
45N/A print(prefix);
45N/A String sep = "";
45N/A for (Object item: items) {
45N/A print(sep);
45N/A print(item);
45N/A sep = ", ";
45N/A }
45N/A print(suffix);
45N/A }
45N/A
45N/A void writeListIfNotEmpty(String prefix, List<?> items, String suffix) {
45N/A if (items != null && items.size() > 0)
45N/A writeList(prefix, items, suffix);
45N/A }
45N/A
45N/A Signature_attribute getSignature(Attributes attributes) {
45N/A if (options.compat) // javap does not recognize recent attributes
45N/A return null;
45N/A return (Signature_attribute) attributes.get(Attribute.Signature);
45N/A }
45N/A
45N/A String adjustVarargs(AccessFlags flags, String params) {
45N/A if (flags.is(ACC_VARARGS) && !options.compat) {
45N/A int i = params.lastIndexOf("[]");
45N/A if (i > 0)
45N/A return params.substring(0, i) + "..." + params.substring(i+2);
45N/A }
45N/A
45N/A return params;
45N/A }
45N/A
45N/A String getJavaName(ClassFile cf) {
45N/A try {
45N/A return getJavaName(cf.getName());
45N/A } catch (ConstantPoolException e) {
45N/A return report(e);
45N/A }
45N/A }
45N/A
45N/A String getJavaSuperclassName(ClassFile cf) {
45N/A try {
45N/A return getJavaName(cf.getSuperclassName());
45N/A } catch (ConstantPoolException e) {
45N/A return report(e);
45N/A }
45N/A }
45N/A
45N/A String getJavaInterfaceName(ClassFile cf, int index) {
45N/A try {
45N/A return getJavaName(cf.getInterfaceName(index));
45N/A } catch (ConstantPoolException e) {
45N/A return report(e);
45N/A }
45N/A }
45N/A
527N/A String getJavaFieldType(Descriptor d) {
45N/A try {
527N/A return getJavaName(d.getFieldType(constant_pool));
45N/A } catch (ConstantPoolException e) {
45N/A return report(e);
45N/A } catch (DescriptorException e) {
45N/A return report(e);
45N/A }
45N/A }
45N/A
527N/A String getJavaReturnType(Descriptor d) {
45N/A try {
527N/A return getJavaName(d.getReturnType(constant_pool));
45N/A } catch (ConstantPoolException e) {
45N/A return report(e);
45N/A } catch (DescriptorException e) {
45N/A return report(e);
45N/A }
45N/A }
45N/A
527N/A String getJavaParameterTypes(Descriptor d, AccessFlags flags) {
45N/A try {
527N/A return getJavaName(adjustVarargs(flags, d.getParameterTypes(constant_pool)));
45N/A } catch (ConstantPoolException e) {
45N/A return report(e);
45N/A } catch (DescriptorException e) {
45N/A return report(e);
45N/A }
45N/A }
45N/A
51N/A String getJavaException(Exceptions_attribute attr, int index) {
51N/A try {
51N/A return getJavaName(attr.getException(index, constant_pool));
51N/A } catch (ConstantPoolException e) {
51N/A return report(e);
51N/A }
51N/A }
51N/A
45N/A String getValue(Descriptor d) {
45N/A try {
45N/A return d.getValue(constant_pool);
45N/A } catch (ConstantPoolException e) {
45N/A return report(e);
45N/A }
45N/A }
45N/A
45N/A String getFieldName(Field f) {
45N/A try {
45N/A return f.getName(constant_pool);
45N/A } catch (ConstantPoolException e) {
45N/A return report(e);
45N/A }
45N/A }
45N/A
45N/A String getName(Method m) {
45N/A try {
45N/A return m.getName(constant_pool);
45N/A } catch (ConstantPoolException e) {
45N/A return report(e);
45N/A }
45N/A }
45N/A
45N/A static String getJavaName(String name) {
45N/A return name.replace('/', '.');
45N/A }
45N/A
45N/A String getSourceFile(SourceFile_attribute attr) {
45N/A try {
45N/A return attr.getSourceFile(constant_pool);
45N/A } catch (ConstantPoolException e) {
45N/A return report(e);
45N/A }
45N/A }
45N/A
86N/A /**
86N/A * Get the value of an entry in the constant pool as a Java constant.
86N/A * Characters and booleans are represented by CONSTANT_Intgere entries.
86N/A * Character and string values are processed to escape characters outside
86N/A * the basic printable ASCII set.
86N/A * @param d the descriptor, giving the expected type of the constant
86N/A * @param index the index of the value in the constant pool
86N/A * @return a printable string containing the value of the constant.
86N/A */
86N/A String getConstantValue(Descriptor d, int index) {
86N/A try {
86N/A ConstantPool.CPInfo cpInfo = constant_pool.get(index);
86N/A
86N/A switch (cpInfo.getTag()) {
86N/A case ConstantPool.CONSTANT_Integer: {
86N/A ConstantPool.CONSTANT_Integer_info info =
86N/A (ConstantPool.CONSTANT_Integer_info) cpInfo;
86N/A String t = d.getValue(constant_pool);
86N/A if (t.equals("C")) { // character
86N/A return getConstantCharValue((char) info.value);
86N/A } else if (t.equals("Z")) { // boolean
86N/A return String.valueOf(info.value == 1);
86N/A } else { // other: assume integer
86N/A return String.valueOf(info.value);
86N/A }
86N/A }
86N/A
86N/A case ConstantPool.CONSTANT_String: {
86N/A ConstantPool.CONSTANT_String_info info =
86N/A (ConstantPool.CONSTANT_String_info) cpInfo;
86N/A return getConstantStringValue(info.getString());
86N/A }
86N/A
86N/A default:
86N/A return constantWriter.stringValue(cpInfo);
86N/A }
86N/A } catch (ConstantPoolException e) {
86N/A return "#" + index;
86N/A }
86N/A }
86N/A
86N/A private String getConstantCharValue(char c) {
86N/A StringBuilder sb = new StringBuilder();
86N/A sb.append('\'');
86N/A sb.append(esc(c, '\''));
86N/A sb.append('\'');
86N/A return sb.toString();
86N/A }
86N/A
86N/A private String getConstantStringValue(String s) {
86N/A StringBuilder sb = new StringBuilder();
86N/A sb.append("\"");
86N/A for (int i = 0; i < s.length(); i++) {
86N/A sb.append(esc(s.charAt(i), '"'));
86N/A }
86N/A sb.append("\"");
86N/A return sb.toString();
86N/A }
86N/A
86N/A private String esc(char c, char quote) {
86N/A if (32 <= c && c <= 126 && c != quote)
86N/A return String.valueOf(c);
86N/A else switch (c) {
86N/A case '\b': return "\\b";
86N/A case '\n': return "\\n";
86N/A case '\t': return "\\t";
86N/A case '\f': return "\\f";
86N/A case '\r': return "\\r";
86N/A case '\\': return "\\\\";
86N/A case '\'': return "\\'";
86N/A case '\"': return "\\\"";
86N/A default: return String.format("\\u%04x", (int) c);
86N/A }
86N/A }
86N/A
45N/A private Options options;
45N/A private AttributeWriter attrWriter;
45N/A private CodeWriter codeWriter;
45N/A private ConstantWriter constantWriter;
45N/A private ClassFile classFile;
87N/A private URI uri;
87N/A private long lastModified;
87N/A private String digestName;
87N/A private byte[] digest;
87N/A private int size;
45N/A private ConstantPool constant_pool;
45N/A private Method method;
45N/A private static final String NEWLINE = System.getProperty("line.separator", "\n");
45N/A}