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

Thu, 30 Jul 2009 09:18:55 -0700

author
jjg
date
Thu, 30 Jul 2009 09:18:55 -0700
changeset 346
e33efb09ed75
parent 300
ed989c347b3c
child 348
743f17b55b44
permissions
-rw-r--r--

4880672: javap does not output inner interfaces of an interface
Reviewed-by: mcimadamore

     1 /*
     2  * Copyright 2007-2008 Sun Microsystems, Inc.  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.  Sun designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
    23  * have any questions.
    24  */
    26 package com.sun.tools.javap;
    28 import com.sun.tools.classfile.ClassFile;
    29 import com.sun.tools.classfile.ConstantPool;
    30 import com.sun.tools.classfile.ConstantPoolException;
    32 import static com.sun.tools.classfile.ConstantPool.*;
    34 /*
    35  *  Write a constant pool entry.
    36  *
    37  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    38  *  you write code that depends on this, you do so at your own risk.
    39  *  This code and its internal interfaces are subject to change or
    40  *  deletion without notice.</b>
    41  */
    42 public class ConstantWriter extends BasicWriter {
    43     public static ConstantWriter instance(Context context) {
    44         ConstantWriter instance = context.get(ConstantWriter.class);
    45         if (instance == null)
    46             instance = new ConstantWriter(context);
    47         return instance;
    48     }
    50     protected ConstantWriter(Context context) {
    51         super(context);
    52         context.put(ConstantWriter.class, this);
    53         classWriter = ClassWriter.instance(context);
    54         options = Options.instance(context);
    55     }
    57     protected void writeConstantPool() {
    58         ConstantPool constant_pool = classWriter.getClassFile().constant_pool;
    59         writeConstantPool(constant_pool);
    60     }
    62     protected void writeConstantPool(ConstantPool constant_pool) {
    63         ConstantPool.Visitor<Integer, Void> v = new ConstantPool.Visitor<Integer,Void>() {
    64             public Integer visitClass(CONSTANT_Class_info info, Void p) {
    65                 println("#" + info.name_index + ";\t//  " + stringValue(info));
    66                 return 1;
    67             }
    69             public Integer visitDouble(CONSTANT_Double_info info, Void p) {
    70                 println(stringValue(info) + ";");
    71                 return 2;
    72             }
    74             public Integer visitFieldref(CONSTANT_Fieldref_info info, Void p) {
    75                 println("#" + info.class_index + ".#" + info.name_and_type_index + ";\t//  " + stringValue(info));
    76                 return 1;
    77             }
    79             public Integer visitFloat(CONSTANT_Float_info info, Void p) {
    80                 println(stringValue(info) + ";");
    81                 return 1;
    82             }
    84             public Integer visitInteger(CONSTANT_Integer_info info, Void p) {
    85                 println(stringValue(info) + ";");
    86                 return 1;
    87             }
    89             public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
    90                 println("#" + info.class_index + ".#" + info.name_and_type_index + ";\t//  " + stringValue(info));
    91                 return 1;
    92             }
    94             public Integer visitLong(CONSTANT_Long_info info, Void p) {
    95                 println(stringValue(info) + ";");
    96                 return 2;
    97             }
    99             public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
   100                 String tab = (options.compat ? "" : "\t"); // BUG 6622232 javap gets whitespace confused
   101                 println("#" + info.name_index + ":#" + info.type_index + ";" + tab + "//  " + stringValue(info));
   102                 return 1;
   103             }
   105             public Integer visitMethodref(CONSTANT_Methodref_info info, Void p) {
   106                 println("#" + info.class_index + ".#" + info.name_and_type_index + ";\t//  " + stringValue(info));
   107                 return 1;
   108             }
   110             public Integer visitString(CONSTANT_String_info info, Void p) {
   111                 println("#" + info.string_index + ";\t//  " + stringValue(info));
   112                 return 1;
   113             }
   115             public Integer visitUtf8(CONSTANT_Utf8_info info, Void p) {
   116                 println(stringValue(info) + ";");
   117                 return 1;
   118             }
   120         };
   121         println("  Constant pool:");
   122         int cpx = 1;
   123         while (cpx < constant_pool.size()) {
   124             try {
   125                 CPInfo cpInfo = constant_pool.get(cpx);
   126                 print("const #" + cpx + " = " + tagName(cpInfo.getTag()) + "\t");
   127                 cpx += cpInfo.accept(v, null);
   128             } catch (ConstantPool.InvalidIndex ex) {
   129                 print("const #" + cpx); // should not happen
   130             }
   131         }
   132     }
   134     protected void write(int cpx) {
   135         ClassFile classFile = classWriter.getClassFile();
   136         if (cpx == 0) {
   137             print("#0");
   138             return;
   139         }
   141         CPInfo cpInfo;
   142         try {
   143             cpInfo = classFile.constant_pool.get(cpx);
   144         } catch (ConstantPoolException e) {
   145             print("#" + cpx);
   146             return;
   147         }
   149         int tag = cpInfo.getTag();
   150         switch (tag) {
   151             case CONSTANT_Methodref:
   152             case CONSTANT_InterfaceMethodref:
   153             case CONSTANT_Fieldref:
   154                 // simplify references within this class
   155                 CPRefInfo ref = (CPRefInfo) cpInfo;
   156                 try {
   157                     if (ref.class_index == classFile.this_class)
   158                          cpInfo = classFile.constant_pool.get(ref.name_and_type_index);
   159                 } catch (ConstantPool.InvalidIndex e) {
   160                     // ignore, for now
   161                 }
   162         }
   163         print(tagName(tag) + " " + stringValue(cpInfo));
   164     }
   166     String tagName(int tag) {
   167         switch (tag) {
   168             case CONSTANT_Utf8:
   169                 return "Asciz";
   170             case CONSTANT_Integer:
   171                 return "int";
   172             case CONSTANT_Float:
   173                 return "float";
   174             case CONSTANT_Long:
   175                 return "long";
   176             case CONSTANT_Double:
   177                 return "double";
   178             case CONSTANT_Class:
   179                 return "class";
   180             case CONSTANT_String:
   181                 return "String";
   182             case CONSTANT_Fieldref:
   183                 return "Field";
   184             case CONSTANT_Methodref:
   185                 return "Method";
   186             case CONSTANT_InterfaceMethodref:
   187                 return "InterfaceMethod";
   188             case CONSTANT_NameAndType:
   189                 return "NameAndType";
   190             default:
   191                 return "unknown tag";
   192         }
   193     }
   195     String stringValue(int constant_pool_index) {
   196         ClassFile classFile = classWriter.getClassFile();
   197         try {
   198             return stringValue(classFile.constant_pool.get(constant_pool_index));
   199         } catch (ConstantPool.InvalidIndex e) {
   200             return report(e);
   201         }
   202     }
   204     String stringValue(CPInfo cpInfo) {
   205         return stringValueVisitor.visit(cpInfo);
   206     }
   208     StringValueVisitor stringValueVisitor = new StringValueVisitor();
   210     private class StringValueVisitor implements ConstantPool.Visitor<String, Void> {
   211         public String visit(CPInfo info) {
   212             return info.accept(this, null);
   213         }
   215         public String visitClass(CONSTANT_Class_info info, Void p) {
   216             return getCheckedName(info);
   217         }
   219         String getCheckedName(CONSTANT_Class_info info) {
   220             try {
   221                 return checkName(info.getName());
   222             } catch (ConstantPoolException e) {
   223                 return report(e);
   224             }
   225         }
   227         public String visitDouble(CONSTANT_Double_info info, Void p) {
   228             return info.value + "d";
   229         }
   231         public String visitFieldref(CONSTANT_Fieldref_info info, Void p) {
   232             return visitRef(info, p);
   233         }
   235         public String visitFloat(CONSTANT_Float_info info, Void p) {
   236             return info.value + "f";
   237         }
   239         public String visitInteger(CONSTANT_Integer_info info, Void p) {
   240             return String.valueOf(info.value);
   241         }
   243         public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
   244             return visitRef(info, p);
   245         }
   247         public String visitLong(CONSTANT_Long_info info, Void p) {
   248             return info.value + "l";
   249         }
   251         public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
   252             return getCheckedName(info) + ":" + getType(info);
   253         }
   255         String getCheckedName(CONSTANT_NameAndType_info info) {
   256             try {
   257                 return checkName(info.getName());
   258             } catch (ConstantPoolException e) {
   259                 return report(e);
   260             }
   261         }
   263         String getType(CONSTANT_NameAndType_info info) {
   264             try {
   265                 return info.getType();
   266             } catch (ConstantPoolException e) {
   267                 return report(e);
   268             }
   269         }
   271         public String visitMethodref(CONSTANT_Methodref_info info, Void p) {
   272             return visitRef(info, p);
   273         }
   275         public String visitString(CONSTANT_String_info info, Void p) {
   276             try {
   277                 ClassFile classFile = classWriter.getClassFile();
   278                 int string_index = info.string_index;
   279                 return stringValue(classFile.constant_pool.getUTF8Info(string_index));
   280             } catch (ConstantPoolException e) {
   281                 return report(e);
   282             }
   283         }
   285         public String visitUtf8(CONSTANT_Utf8_info info, Void p) {
   286             String s = info.value;
   287             StringBuilder sb = new StringBuilder();
   288             for (int i = 0; i < s.length(); i++) {
   289                 char c = s.charAt(i);
   290                 switch (c) {
   291                     case '\t':
   292                         sb.append('\\').append('t');
   293                         break;
   294                     case '\n':
   295                         sb.append('\\').append('n');
   296                         break;
   297                     case '\r':
   298                         sb.append('\\').append('r');
   299                         break;
   300                     case '\"':
   301                         sb.append('\\').append('\"');
   302                         break;
   303                     default:
   304                         sb.append(c);
   305                 }
   306             }
   307             return sb.toString();
   308         }
   310         String visitRef(CPRefInfo info, Void p) {
   311             String cn = getCheckedClassName(info);
   312             String nat;
   313             try {
   314                 nat = stringValue(info.getNameAndTypeInfo());
   315             } catch (ConstantPoolException e) {
   316                 nat = report(e);
   317             }
   318             return cn + "." + nat;
   319         }
   321         String getCheckedClassName(CPRefInfo info) {
   322             try {
   323                 return checkName(info.getClassName());
   324             } catch (ConstantPoolException e) {
   325                 return report(e);
   326             }
   327         }
   328     }
   331     /* If name is a valid binary name, return it; otherwise quote it. */
   332     private static String checkName(String name) {
   333         if (name == null)
   334             return "null";
   336         int len = name.length();
   337         if (len == 0)
   338             return "\"\"";
   340         int cc = '/';
   341         int cp;
   342         for (int k = 0; k < len; k += Character.charCount(cp)) {
   343             cp = name.codePointAt(k);
   344             if ((cc == '/' && !Character.isJavaIdentifierStart(cp))
   345                     || (cp != '/' && !Character.isJavaIdentifierPart(cp))) {
   346                 return "\"" + addEscapes(name) + "\"";
   347             }
   348             cc = cp;
   349         }
   351         return name;
   352     }
   354     /* If name requires escapes, put them in, so it can be a string body. */
   355     private static String addEscapes(String name) {
   356         String esc = "\\\"\n\t";
   357         String rep = "\\\"nt";
   358         StringBuilder buf = null;
   359         int nextk = 0;
   360         int len = name.length();
   361         for (int k = 0; k < len; k++) {
   362             char cp = name.charAt(k);
   363             int n = esc.indexOf(cp);
   364             if (n >= 0) {
   365                 if (buf == null)
   366                     buf = new StringBuilder(len * 2);
   367                 if (nextk < k)
   368                     buf.append(name, nextk, k);
   369                 buf.append('\\');
   370                 buf.append(rep.charAt(n));
   371                 nextk = k+1;
   372             }
   373         }
   374         if (buf == null)
   375             return name;
   376         if (nextk < len)
   377             buf.append(name, nextk, len);
   378         return buf.toString();
   379     }
   381     private ClassWriter classWriter;
   382     private Options options;
   383 }

mercurial