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