jdk/make/modules/tools/src/com/sun/classanalyzer/ConstantPoolParser.java
changeset 8852 c228cf346138
parent 8851 e630c590eb10
parent 8717 f75a1efb1412
child 8853 6aa795396cc8
child 9067 c0b85430843d
equal deleted inserted replaced
8851:e630c590eb10 8852:c228cf346138
     1 /*
       
     2  * Copyright (c) 2009, 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.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 package com.sun.classanalyzer;
       
    24 
       
    25 import com.sun.tools.classfile.*;
       
    26 import com.sun.tools.classfile.ConstantPool.*;
       
    27 import static com.sun.tools.classfile.ConstantPool.*;
       
    28 
       
    29 /**
       
    30  *
       
    31  * @author Mandy Chung
       
    32  */
       
    33 public class ConstantPoolParser {
       
    34 
       
    35     private final ClassFileParser cfparser;
       
    36     private final StringValueVisitor visitor;
       
    37     private final ConstantPool cpool;
       
    38 
       
    39     ConstantPoolParser(ClassFileParser parser) {
       
    40         this.cfparser = parser;
       
    41         this.cpool = cfparser.classfile.constant_pool;
       
    42         this.visitor = new StringValueVisitor();
       
    43     }
       
    44 
       
    45     public String stringValue(CPInfo cpInfo) {
       
    46         return visitor.visit(cpInfo);
       
    47     }
       
    48 
       
    49     public String stringValue(int constant_pool_index) {
       
    50         try {
       
    51             return stringValue(cpool.get(constant_pool_index));
       
    52         } catch (ConstantPool.InvalidIndex e) {
       
    53             throw new RuntimeException(e);
       
    54         }
       
    55     }
       
    56 
       
    57     public void parseDependency() {
       
    58         ConstantPool.Visitor<Integer, Void> v = new ConstantPool.Visitor<Integer, Void>() {
       
    59 
       
    60             public Integer visitClass(CONSTANT_Class_info info, Void p) {
       
    61                 try {
       
    62                     String classname = cfparser.checkClassName(info.getName());
       
    63                     if (classname.isEmpty()) {
       
    64                         return 1;
       
    65                     }
       
    66 
       
    67                     Klass from = cfparser.this_klass;
       
    68                     Klass to = Klass.getKlass(classname);
       
    69                     ResolutionInfo resInfo = ResolutionInfo.resolvedConstantPool(from, to, info.name_index);
       
    70 
       
    71                     from.addDep(to, resInfo);
       
    72                     to.addReferrer(from, resInfo);
       
    73                 } catch (ConstantPoolException ex) {
       
    74                     throw new RuntimeException(ex);
       
    75                 }
       
    76                 return 1;
       
    77             }
       
    78 
       
    79             public Integer visitDouble(CONSTANT_Double_info info, Void p) {
       
    80                 // skip
       
    81                 return 2;
       
    82             }
       
    83 
       
    84             public Integer visitFieldref(CONSTANT_Fieldref_info info, Void p) {
       
    85                 // skip
       
    86                 return 1;
       
    87             }
       
    88 
       
    89             public Integer visitFloat(CONSTANT_Float_info info, Void p) {
       
    90                 // skip
       
    91                 return 1;
       
    92             }
       
    93 
       
    94             public Integer visitInteger(CONSTANT_Integer_info info, Void p) {
       
    95                 // skip
       
    96                 return 1;
       
    97             }
       
    98 
       
    99             public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
       
   100                 // skip
       
   101                 return 1;
       
   102             }
       
   103 
       
   104             public Integer visitLong(CONSTANT_Long_info info, Void p) {
       
   105                 // skip
       
   106                 return 2;
       
   107             }
       
   108 
       
   109             public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
       
   110                 // skip
       
   111                 return 1;
       
   112             }
       
   113 
       
   114             public Integer visitMethodref(CONSTANT_Methodref_info info, Void p) {
       
   115                 // skip
       
   116                 return 1;
       
   117             }
       
   118 
       
   119             public Integer visitString(CONSTANT_String_info info, Void p) {
       
   120                 // skip
       
   121                 return 1;
       
   122             }
       
   123 
       
   124             public Integer visitUtf8(CONSTANT_Utf8_info info, Void p) {
       
   125                 // skip
       
   126                 return 1;
       
   127             }
       
   128         };
       
   129         int cpx = 1;
       
   130         while (cpx < cpool.size()) {
       
   131             try {
       
   132                 CPInfo cpInfo = cpool.get(cpx);
       
   133                 cpx += cpInfo.accept(v, null);
       
   134             } catch (ConstantPool.InvalidIndex ex) {
       
   135                 throw new RuntimeException(ex);
       
   136             }
       
   137         }
       
   138     }
       
   139 
       
   140     int getTag(int index) {
       
   141         try {
       
   142             return cpool.get(index).getTag();
       
   143         } catch (ConstantPoolException ex) {
       
   144             throw new RuntimeException(ex);
       
   145         }
       
   146     }
       
   147 
       
   148     String getDescriptor(int index) {
       
   149         CPInfo cpInfo;
       
   150         try {
       
   151             cpInfo = cpool.get(index);
       
   152         } catch (ConstantPoolException ex) {
       
   153             throw new RuntimeException(ex);
       
   154         }
       
   155 
       
   156         int tag = cpInfo.getTag();
       
   157         switch (tag) {
       
   158             case CONSTANT_Methodref:
       
   159             case CONSTANT_InterfaceMethodref:
       
   160             case CONSTANT_Fieldref:
       
   161                 // simplify references within this class
       
   162                 CPRefInfo ref = (CPRefInfo) cpInfo;
       
   163                 try {
       
   164                     return ref.getNameAndTypeInfo().getType();
       
   165                 } catch (ConstantPoolException ex) {
       
   166                 }
       
   167         }
       
   168         return stringValue(cpInfo);
       
   169     }
       
   170 
       
   171     String getMethodName(int index) {
       
   172         try {
       
   173             CPInfo cpInfo = cpool.get(index);
       
   174             if (cpInfo.getTag() == CONSTANT_Methodref ||
       
   175                     cpInfo.getTag() == CONSTANT_InterfaceMethodref) {
       
   176 
       
   177                 // simplify references within this class
       
   178                 CPRefInfo ref = (CPRefInfo) cpInfo;
       
   179                 String classname;
       
   180                 if (ref.class_index == cfparser.classfile.this_class) {
       
   181                     classname = cfparser.this_klass.getClassName();
       
   182                 } else {
       
   183                     classname = cfparser.checkClassName(ref.getClassName()).replace('/', '.');
       
   184                 }
       
   185                 String methodname = ref.getNameAndTypeInfo().getName();
       
   186                 return classname + "." + methodname;
       
   187             } else {
       
   188                 return null;
       
   189             }
       
   190         } catch (InvalidIndex ex) {
       
   191             throw new RuntimeException(ex);
       
   192         } catch (ConstantPoolException ex) {
       
   193             throw new RuntimeException(ex);
       
   194         }
       
   195 
       
   196     }
       
   197 
       
   198     class StringValueVisitor implements ConstantPool.Visitor<String, Void> {
       
   199 
       
   200         public StringValueVisitor() {
       
   201         }
       
   202 
       
   203         public String visit(CPInfo info) {
       
   204             return info.accept(this, null);
       
   205         }
       
   206 
       
   207         public String visitClass(CONSTANT_Class_info info, Void p) {
       
   208             return getCheckedName(info);
       
   209         }
       
   210 
       
   211         String getCheckedName(CONSTANT_Class_info info) {
       
   212             try {
       
   213                 return checkName(info.getName());
       
   214             } catch (ConstantPoolException e) {
       
   215                 throw new RuntimeException(e);
       
   216             }
       
   217         }
       
   218 
       
   219         public String visitDouble(CONSTANT_Double_info info, Void p) {
       
   220             return info.value + "d";
       
   221         }
       
   222 
       
   223         public String visitFieldref(CONSTANT_Fieldref_info info, Void p) {
       
   224             return visitRef(info, p);
       
   225         }
       
   226 
       
   227         public String visitFloat(CONSTANT_Float_info info, Void p) {
       
   228             return info.value + "f";
       
   229         }
       
   230 
       
   231         public String visitInteger(CONSTANT_Integer_info info, Void p) {
       
   232             return String.valueOf(info.value);
       
   233         }
       
   234 
       
   235         public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
       
   236             return visitRef(info, p);
       
   237         }
       
   238 
       
   239         public String visitLong(CONSTANT_Long_info info, Void p) {
       
   240             return info.value + "l";
       
   241         }
       
   242 
       
   243         public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
       
   244             return getCheckedName(info) + ":" + getType(info);
       
   245         }
       
   246 
       
   247         String getCheckedName(CONSTANT_NameAndType_info info) {
       
   248             try {
       
   249                 return checkName(info.getName());
       
   250             } catch (ConstantPoolException e) {
       
   251                 throw new RuntimeException(e);
       
   252             }
       
   253         }
       
   254 
       
   255         String getType(CONSTANT_NameAndType_info info) {
       
   256             try {
       
   257                 return info.getType();
       
   258             } catch (ConstantPoolException e) {
       
   259                 throw new RuntimeException(e);
       
   260             }
       
   261         }
       
   262 
       
   263         public String visitMethodref(CONSTANT_Methodref_info info, Void p) {
       
   264             return visitRef(info, p);
       
   265         }
       
   266 
       
   267         public String visitString(CONSTANT_String_info info, Void p) {
       
   268             try {
       
   269                 int string_index = info.string_index;
       
   270                 return cpool.getUTF8Info(string_index).accept(this, p);
       
   271             } catch (ConstantPoolException e) {
       
   272                 throw new RuntimeException(e);
       
   273             }
       
   274         }
       
   275 
       
   276         public String visitUtf8(CONSTANT_Utf8_info info, Void p) {
       
   277             String s = info.value;
       
   278             StringBuilder sb = new StringBuilder();
       
   279             for (int i = 0; i < s.length(); i++) {
       
   280                 char c = s.charAt(i);
       
   281                 switch (c) {
       
   282                     case '\t':
       
   283                         sb.append('\\').append('t');
       
   284                         break;
       
   285                     case '\n':
       
   286                         sb.append('\\').append('n');
       
   287                         break;
       
   288                     case '\r':
       
   289                         sb.append('\\').append('r');
       
   290                         break;
       
   291                     case '\"':
       
   292                         sb.append('\\').append('\"');
       
   293                         break;
       
   294                     default:
       
   295                         sb.append(c);
       
   296                 }
       
   297             }
       
   298             return sb.toString();
       
   299         }
       
   300 
       
   301         String visitRef(CPRefInfo info, Void p) {
       
   302             String cn = getCheckedClassName(info);
       
   303             String nat;
       
   304             try {
       
   305                 nat = info.getNameAndTypeInfo().accept(this, p);
       
   306             } catch (ConstantPoolException e) {
       
   307                 nat = e.getMessage();
       
   308             }
       
   309             return cn + "." + nat;
       
   310         }
       
   311 
       
   312         String getCheckedClassName(CPRefInfo info) {
       
   313             try {
       
   314                 return checkName(info.getClassName());
       
   315             } catch (ConstantPoolException e) {
       
   316                 throw new RuntimeException(e);
       
   317             }
       
   318         }
       
   319     }
       
   320     /* If name is a valid binary name, return it; otherwise quote it. */
       
   321 
       
   322     private static String checkName(String name) {
       
   323         if (name == null) {
       
   324             return "null";
       
   325         }
       
   326 
       
   327         int len = name.length();
       
   328         if (len == 0) {
       
   329             return "\"\"";
       
   330         }
       
   331 
       
   332         int cc = '/';
       
   333         int cp;
       
   334         for (int k = 0; k < len; k += Character.charCount(cp)) {
       
   335             cp = name.codePointAt(k);
       
   336             if ((cc == '/' && !Character.isJavaIdentifierStart(cp)) || (cp != '/' && !Character.isJavaIdentifierPart(cp))) {
       
   337                 return "\"" + name + "\"";
       
   338             }
       
   339             cc = cp;
       
   340         }
       
   341         return name;
       
   342     }
       
   343 
       
   344     String tagName(int index) {
       
   345         try {
       
   346             int tag = cpool.get(index).getTag();
       
   347             switch (tag) {
       
   348                 case CONSTANT_Utf8:
       
   349                     return "Utf8";
       
   350                 case CONSTANT_Integer:
       
   351                     return "int";
       
   352                 case CONSTANT_Float:
       
   353                     return "float";
       
   354                 case CONSTANT_Long:
       
   355                     return "long";
       
   356                 case CONSTANT_Double:
       
   357                     return "double";
       
   358                 case CONSTANT_Class:
       
   359                     return "class";
       
   360                 case CONSTANT_String:
       
   361                     return "String";
       
   362                 case CONSTANT_Fieldref:
       
   363                     return "Field";
       
   364                 case CONSTANT_Methodref:
       
   365                     return "Method";
       
   366                 case CONSTANT_InterfaceMethodref:
       
   367                     return "InterfaceMethod";
       
   368                 case CONSTANT_NameAndType:
       
   369                     return "NameAndType";
       
   370                 default:
       
   371                     return "(unknown tag)";
       
   372             }
       
   373         } catch (InvalidIndex e) {
       
   374             throw new RuntimeException(e);
       
   375         }
       
   376     }
       
   377 }