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

Sat, 08 Aug 2009 17:56:37 -0700

author
jjg
date
Sat, 08 Aug 2009 17:56:37 -0700
changeset 355
961dc3acdb06
parent 354
cba827f72977
child 554
9d9f26857129
permissions
-rw-r--r--

6868539: javap should use current names for constant pool tags
Reviewed-by: ksrini

     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                 print("#" + info.name_index);
    66                 tab();
    67                 println("//  " + stringValue(info));
    68                 return 1;
    69             }
    71             public Integer visitDouble(CONSTANT_Double_info info, Void p) {
    72                 println(stringValue(info));
    73                 return 2;
    74             }
    76             public Integer visitFieldref(CONSTANT_Fieldref_info info, Void p) {
    77                 print("#" + info.class_index + ".#" + info.name_and_type_index);
    78                 tab();
    79                 println("//  " + stringValue(info));
    80                 return 1;
    81             }
    83             public Integer visitFloat(CONSTANT_Float_info info, Void p) {
    84                 println(stringValue(info));
    85                 return 1;
    86             }
    88             public Integer visitInteger(CONSTANT_Integer_info info, Void p) {
    89                 println(stringValue(info));
    90                 return 1;
    91             }
    93             public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
    94                 print("#" + info.class_index + ".#" + info.name_and_type_index);
    95                 tab();
    96                 println("//  " + stringValue(info));
    97                 return 1;
    98             }
   100             public Integer visitLong(CONSTANT_Long_info info, Void p) {
   101                 println(stringValue(info));
   102                 return 2;
   103             }
   105             public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
   106                 print("#" + info.name_index + ":#" + info.type_index);
   107                 tab();
   108                 println("//  " + stringValue(info));
   109                 return 1;
   110             }
   112             public Integer visitMethodref(CONSTANT_Methodref_info info, Void p) {
   113                 print("#" + info.class_index + ".#" + info.name_and_type_index);
   114                 tab();
   115                 println("//  " + stringValue(info));
   116                 return 1;
   117             }
   119             public Integer visitString(CONSTANT_String_info info, Void p) {
   120                 print("#" + info.string_index);
   121                 tab();
   122                 println("//  " + stringValue(info));
   123                 return 1;
   124             }
   126             public Integer visitUtf8(CONSTANT_Utf8_info info, Void p) {
   127                 println(stringValue(info));
   128                 return 1;
   129             }
   131         };
   132         println("Constant pool:");
   133         indent(+1);
   134         int width = String.valueOf(constant_pool.size()).length() + 1;
   135         int cpx = 1;
   136         while (cpx < constant_pool.size()) {
   137             print(String.format("%" + width + "s", ("#" + cpx)));
   138             try {
   139                 CPInfo cpInfo = constant_pool.get(cpx);
   140                 print(String.format(" = %-18s ", cpTagName(cpInfo)));
   141                 cpx += cpInfo.accept(v, null);
   142             } catch (ConstantPool.InvalidIndex ex) {
   143                 // should not happen
   144             }
   145         }
   146         indent(-1);
   147     }
   149     protected void write(int cpx) {
   150         ClassFile classFile = classWriter.getClassFile();
   151         if (cpx == 0) {
   152             print("#0");
   153             return;
   154         }
   156         CPInfo cpInfo;
   157         try {
   158             cpInfo = classFile.constant_pool.get(cpx);
   159         } catch (ConstantPoolException e) {
   160             print("#" + cpx);
   161             return;
   162         }
   164         int tag = cpInfo.getTag();
   165         switch (tag) {
   166             case CONSTANT_Methodref:
   167             case CONSTANT_InterfaceMethodref:
   168             case CONSTANT_Fieldref:
   169                 // simplify references within this class
   170                 CPRefInfo ref = (CPRefInfo) cpInfo;
   171                 try {
   172                     if (ref.class_index == classFile.this_class)
   173                          cpInfo = classFile.constant_pool.get(ref.name_and_type_index);
   174                 } catch (ConstantPool.InvalidIndex e) {
   175                     // ignore, for now
   176                 }
   177         }
   178         print(tagName(tag) + " " + stringValue(cpInfo));
   179     }
   181     String cpTagName(CPInfo cpInfo) {
   182         String n = cpInfo.getClass().getSimpleName();
   183         return n.replace("CONSTANT_", "").replace("_info", "");
   184     }
   186     String tagName(int tag) {
   187         switch (tag) {
   188             case CONSTANT_Utf8:
   189                 return "Utf8";
   190             case CONSTANT_Integer:
   191                 return "int";
   192             case CONSTANT_Float:
   193                 return "float";
   194             case CONSTANT_Long:
   195                 return "long";
   196             case CONSTANT_Double:
   197                 return "double";
   198             case CONSTANT_Class:
   199                 return "class";
   200             case CONSTANT_String:
   201                 return "String";
   202             case CONSTANT_Fieldref:
   203                 return "Field";
   204             case CONSTANT_Methodref:
   205                 return "Method";
   206             case CONSTANT_InterfaceMethodref:
   207                 return "InterfaceMethod";
   208             case CONSTANT_NameAndType:
   209                 return "NameAndType";
   210             default:
   211                 return "(unknown tag)";
   212         }
   213     }
   215     String stringValue(int constant_pool_index) {
   216         ClassFile classFile = classWriter.getClassFile();
   217         try {
   218             return stringValue(classFile.constant_pool.get(constant_pool_index));
   219         } catch (ConstantPool.InvalidIndex e) {
   220             return report(e);
   221         }
   222     }
   224     String stringValue(CPInfo cpInfo) {
   225         return stringValueVisitor.visit(cpInfo);
   226     }
   228     StringValueVisitor stringValueVisitor = new StringValueVisitor();
   230     private class StringValueVisitor implements ConstantPool.Visitor<String, Void> {
   231         public String visit(CPInfo info) {
   232             return info.accept(this, null);
   233         }
   235         public String visitClass(CONSTANT_Class_info info, Void p) {
   236             return getCheckedName(info);
   237         }
   239         String getCheckedName(CONSTANT_Class_info info) {
   240             try {
   241                 return checkName(info.getName());
   242             } catch (ConstantPoolException e) {
   243                 return report(e);
   244             }
   245         }
   247         public String visitDouble(CONSTANT_Double_info info, Void p) {
   248             return info.value + "d";
   249         }
   251         public String visitFieldref(CONSTANT_Fieldref_info info, Void p) {
   252             return visitRef(info, p);
   253         }
   255         public String visitFloat(CONSTANT_Float_info info, Void p) {
   256             return info.value + "f";
   257         }
   259         public String visitInteger(CONSTANT_Integer_info info, Void p) {
   260             return String.valueOf(info.value);
   261         }
   263         public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
   264             return visitRef(info, p);
   265         }
   267         public String visitLong(CONSTANT_Long_info info, Void p) {
   268             return info.value + "l";
   269         }
   271         public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
   272             return getCheckedName(info) + ":" + getType(info);
   273         }
   275         String getCheckedName(CONSTANT_NameAndType_info info) {
   276             try {
   277                 return checkName(info.getName());
   278             } catch (ConstantPoolException e) {
   279                 return report(e);
   280             }
   281         }
   283         String getType(CONSTANT_NameAndType_info info) {
   284             try {
   285                 return info.getType();
   286             } catch (ConstantPoolException e) {
   287                 return report(e);
   288             }
   289         }
   291         public String visitMethodref(CONSTANT_Methodref_info info, Void p) {
   292             return visitRef(info, p);
   293         }
   295         public String visitString(CONSTANT_String_info info, Void p) {
   296             try {
   297                 ClassFile classFile = classWriter.getClassFile();
   298                 int string_index = info.string_index;
   299                 return stringValue(classFile.constant_pool.getUTF8Info(string_index));
   300             } catch (ConstantPoolException e) {
   301                 return report(e);
   302             }
   303         }
   305         public String visitUtf8(CONSTANT_Utf8_info info, Void p) {
   306             String s = info.value;
   307             StringBuilder sb = new StringBuilder();
   308             for (int i = 0; i < s.length(); i++) {
   309                 char c = s.charAt(i);
   310                 switch (c) {
   311                     case '\t':
   312                         sb.append('\\').append('t');
   313                         break;
   314                     case '\n':
   315                         sb.append('\\').append('n');
   316                         break;
   317                     case '\r':
   318                         sb.append('\\').append('r');
   319                         break;
   320                     case '\"':
   321                         sb.append('\\').append('\"');
   322                         break;
   323                     default:
   324                         sb.append(c);
   325                 }
   326             }
   327             return sb.toString();
   328         }
   330         String visitRef(CPRefInfo info, Void p) {
   331             String cn = getCheckedClassName(info);
   332             String nat;
   333             try {
   334                 nat = stringValue(info.getNameAndTypeInfo());
   335             } catch (ConstantPoolException e) {
   336                 nat = report(e);
   337             }
   338             return cn + "." + nat;
   339         }
   341         String getCheckedClassName(CPRefInfo info) {
   342             try {
   343                 return checkName(info.getClassName());
   344             } catch (ConstantPoolException e) {
   345                 return report(e);
   346             }
   347         }
   348     }
   351     /* If name is a valid binary name, return it; otherwise quote it. */
   352     private static String checkName(String name) {
   353         if (name == null)
   354             return "null";
   356         int len = name.length();
   357         if (len == 0)
   358             return "\"\"";
   360         int cc = '/';
   361         int cp;
   362         for (int k = 0; k < len; k += Character.charCount(cp)) {
   363             cp = name.codePointAt(k);
   364             if ((cc == '/' && !Character.isJavaIdentifierStart(cp))
   365                     || (cp != '/' && !Character.isJavaIdentifierPart(cp))) {
   366                 return "\"" + addEscapes(name) + "\"";
   367             }
   368             cc = cp;
   369         }
   371         return name;
   372     }
   374     /* If name requires escapes, put them in, so it can be a string body. */
   375     private static String addEscapes(String name) {
   376         String esc = "\\\"\n\t";
   377         String rep = "\\\"nt";
   378         StringBuilder buf = null;
   379         int nextk = 0;
   380         int len = name.length();
   381         for (int k = 0; k < len; k++) {
   382             char cp = name.charAt(k);
   383             int n = esc.indexOf(cp);
   384             if (n >= 0) {
   385                 if (buf == null)
   386                     buf = new StringBuilder(len * 2);
   387                 if (nextk < k)
   388                     buf.append(name, nextk, k);
   389                 buf.append('\\');
   390                 buf.append(rep.charAt(n));
   391                 nextk = k+1;
   392             }
   393         }
   394         if (buf == null)
   395             return name;
   396         if (nextk < len)
   397             buf.append(name, nextk, len);
   398         return buf.toString();
   399     }
   401     private ClassWriter classWriter;
   402     private Options options;
   403 }

mercurial