1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javap/ConstantWriter.java Tue Jun 03 13:26:47 2008 -0700 1.3 @@ -0,0 +1,352 @@ 1.4 +/* 1.5 + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Sun designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Sun in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.26 + * have any questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.javap; 1.30 + 1.31 +import com.sun.tools.classfile.ClassFile; 1.32 +import com.sun.tools.classfile.ConstantPool; 1.33 +import com.sun.tools.classfile.ConstantPoolException; 1.34 + 1.35 +import static com.sun.tools.classfile.ConstantPool.*; 1.36 + 1.37 +/* 1.38 + * Write a constant pool entry. 1.39 + * 1.40 + * <p><b>This is NOT part of any API supported by Sun Microsystems. If 1.41 + * you write code that depends on this, you do so at your own risk. 1.42 + * This code and its internal interfaces are subject to change or 1.43 + * deletion without notice.</b> 1.44 + */ 1.45 +public class ConstantWriter extends BasicWriter { 1.46 + static ConstantWriter instance(Context context) { 1.47 + ConstantWriter instance = context.get(ConstantWriter.class); 1.48 + if (instance == null) 1.49 + instance = new ConstantWriter(context); 1.50 + return instance; 1.51 + } 1.52 + 1.53 + protected ConstantWriter(Context context) { 1.54 + super(context); 1.55 + context.put(ConstantWriter.class, this); 1.56 + classWriter = ClassWriter.instance(context); 1.57 + options = Options.instance(context); 1.58 + } 1.59 + 1.60 + void writeConstantPool() { 1.61 + ConstantPool.Visitor<Integer, Void> v = new ConstantPool.Visitor<Integer,Void>() { 1.62 + public Integer visitClass(CONSTANT_Class_info info, Void p) { 1.63 + println("#" + info.name_index + ";\t// " + stringValue(info)); 1.64 + return 1; 1.65 + } 1.66 + 1.67 + public Integer visitDouble(CONSTANT_Double_info info, Void p) { 1.68 + println(stringValue(info) + ";"); 1.69 + return 2; 1.70 + } 1.71 + 1.72 + public Integer visitFieldref(CONSTANT_Fieldref_info info, Void p) { 1.73 + println("#" + info.class_index + ".#" + info.name_and_type_index + ";\t// " + stringValue(info)); 1.74 + return 1; 1.75 + } 1.76 + 1.77 + public Integer visitFloat(CONSTANT_Float_info info, Void p) { 1.78 + println(stringValue(info) + ";"); 1.79 + return 1; 1.80 + } 1.81 + 1.82 + public Integer visitInteger(CONSTANT_Integer_info info, Void p) { 1.83 + println(stringValue(info) + ";"); 1.84 + return 1; 1.85 + } 1.86 + 1.87 + public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) { 1.88 + println("#" + info.class_index + ".#" + info.name_and_type_index + ";\t// " + stringValue(info)); 1.89 + return 1; 1.90 + } 1.91 + 1.92 + public Integer visitLong(CONSTANT_Long_info info, Void p) { 1.93 + println(stringValue(info) + ";"); 1.94 + return 2; 1.95 + } 1.96 + 1.97 + public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) { 1.98 + String tab = (options.compat ? "" : "\t"); // BUG 6622232 javap gets whitespace confused 1.99 + println("#" + info.name_index + ":#" + info.type_index + ";" + tab + "// " + stringValue(info)); 1.100 + return 1; 1.101 + } 1.102 + 1.103 + public Integer visitMethodref(CONSTANT_Methodref_info info, Void p) { 1.104 + println("#" + info.class_index + ".#" + info.name_and_type_index + ";\t// " + stringValue(info)); 1.105 + return 1; 1.106 + } 1.107 + 1.108 + public Integer visitString(CONSTANT_String_info info, Void p) { 1.109 + println("#" + info.string_index + ";\t// " + stringValue(info)); 1.110 + return 1; 1.111 + } 1.112 + 1.113 + public Integer visitUtf8(CONSTANT_Utf8_info info, Void p) { 1.114 + println(stringValue(info) + ";"); 1.115 + return 1; 1.116 + } 1.117 + 1.118 + }; 1.119 + println(" Constant pool:"); 1.120 + ConstantPool constant_pool = classWriter.getClassFile().constant_pool; 1.121 + int cpx = 1; 1.122 + while (cpx < constant_pool.size()) { 1.123 + try { 1.124 + CPInfo cpInfo = constant_pool.get(cpx); 1.125 + print("const #" + cpx + " = " + tagName(cpInfo.getTag()) + "\t"); 1.126 + cpx += cpInfo.accept(v, null); 1.127 + } catch (ConstantPool.InvalidIndex ex) { 1.128 + print("const #" + cpx); // should not happen 1.129 + } 1.130 + } 1.131 + } 1.132 + 1.133 + void write(int cpx) { 1.134 + ClassFile classFile = classWriter.getClassFile(); 1.135 + if (cpx == 0) { 1.136 + print("#0"); 1.137 + return; 1.138 + } 1.139 + 1.140 + CPInfo cpInfo; 1.141 + try { 1.142 + cpInfo = classFile.constant_pool.get(cpx); 1.143 + } catch (ConstantPoolException e) { 1.144 + print("#" + cpx); 1.145 + return; 1.146 + } 1.147 + 1.148 + int tag = cpInfo.getTag(); 1.149 + switch (tag) { 1.150 + case CONSTANT_Methodref: 1.151 + case CONSTANT_InterfaceMethodref: 1.152 + case CONSTANT_Fieldref: 1.153 + // simplify references within this class 1.154 + CPRefInfo ref = (CPRefInfo) cpInfo; 1.155 + try { 1.156 + if (ref.class_index == classFile.this_class) 1.157 + cpInfo = classFile.constant_pool.get(ref.name_and_type_index); 1.158 + } catch (ConstantPool.InvalidIndex e) { 1.159 + // ignore, for now 1.160 + } 1.161 + } 1.162 + print(tagName(tag) + " " + stringValue(cpInfo)); 1.163 + } 1.164 + 1.165 + String tagName(int tag) { 1.166 + switch (tag) { 1.167 + case CONSTANT_Utf8: 1.168 + return "Asciz"; 1.169 + case CONSTANT_Integer: 1.170 + return "int"; 1.171 + case CONSTANT_Float: 1.172 + return "float"; 1.173 + case CONSTANT_Long: 1.174 + return "long"; 1.175 + case CONSTANT_Double: 1.176 + return "double"; 1.177 + case CONSTANT_Class: 1.178 + return "class"; 1.179 + case CONSTANT_String: 1.180 + return "String"; 1.181 + case CONSTANT_Fieldref: 1.182 + return "Field"; 1.183 + case CONSTANT_Methodref: 1.184 + return "Method"; 1.185 + case CONSTANT_InterfaceMethodref: 1.186 + return "InterfaceMethod"; 1.187 + case CONSTANT_NameAndType: 1.188 + return "NameAndType"; 1.189 + default: 1.190 + return "unknown tag"; 1.191 + } 1.192 + } 1.193 + 1.194 + String stringValue(int constant_pool_index) { 1.195 + ClassFile classFile = classWriter.getClassFile(); 1.196 + try { 1.197 + return stringValue(classFile.constant_pool.get(constant_pool_index)); 1.198 + } catch (ConstantPool.InvalidIndex e) { 1.199 + return report(e); 1.200 + } 1.201 + } 1.202 + 1.203 + String stringValue(CPInfo cpInfo) { 1.204 + return stringValueVisitor.visit(cpInfo); 1.205 + } 1.206 + 1.207 + StringValueVisitor stringValueVisitor = new StringValueVisitor(); 1.208 + 1.209 + private class StringValueVisitor implements ConstantPool.Visitor<String, Void> { 1.210 + public String visit(CPInfo info) { 1.211 + return info.accept(this, null); 1.212 + } 1.213 + 1.214 + public String visitClass(CONSTANT_Class_info info, Void p) { 1.215 + return getCheckedName(info); 1.216 + } 1.217 + 1.218 + String getCheckedName(CONSTANT_Class_info info) { 1.219 + try { 1.220 + return checkName(info.getName()); 1.221 + } catch (ConstantPoolException e) { 1.222 + return report(e); 1.223 + } 1.224 + } 1.225 + 1.226 + public String visitDouble(CONSTANT_Double_info info, Void p) { 1.227 + return info.value + "d"; 1.228 + } 1.229 + 1.230 + public String visitFieldref(CONSTANT_Fieldref_info info, Void p) { 1.231 + return visitRef(info, p); 1.232 + } 1.233 + 1.234 + public String visitFloat(CONSTANT_Float_info info, Void p) { 1.235 + return info.value + "f"; 1.236 + } 1.237 + 1.238 + public String visitInteger(CONSTANT_Integer_info info, Void p) { 1.239 + return String.valueOf(info.value); 1.240 + } 1.241 + 1.242 + public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) { 1.243 + return visitRef(info, p); 1.244 + } 1.245 + 1.246 + public String visitLong(CONSTANT_Long_info info, Void p) { 1.247 + return info.value + "l"; 1.248 + } 1.249 + 1.250 + public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) { 1.251 + return getCheckedName(info) + ":" + getType(info); 1.252 + } 1.253 + 1.254 + String getCheckedName(CONSTANT_NameAndType_info info) { 1.255 + try { 1.256 + return checkName(info.getName()); 1.257 + } catch (ConstantPoolException e) { 1.258 + return report(e); 1.259 + } 1.260 + } 1.261 + 1.262 + String getType(CONSTANT_NameAndType_info info) { 1.263 + try { 1.264 + return info.getType(); 1.265 + } catch (ConstantPoolException e) { 1.266 + return report(e); 1.267 + } 1.268 + } 1.269 + 1.270 + public String visitMethodref(CONSTANT_Methodref_info info, Void p) { 1.271 + return visitRef(info, p); 1.272 + } 1.273 + 1.274 + public String visitString(CONSTANT_String_info info, Void p) { 1.275 + try { 1.276 + ClassFile classFile = classWriter.getClassFile(); 1.277 + int string_index = info.string_index; 1.278 + return stringValue(classFile.constant_pool.getUTF8Info(string_index)); 1.279 + } catch (ConstantPoolException e) { 1.280 + return report(e); 1.281 + } 1.282 + } 1.283 + 1.284 + public String visitUtf8(CONSTANT_Utf8_info info, Void p) { 1.285 + String s = info.value; 1.286 + StringBuilder sb = new StringBuilder(); 1.287 + for (int i = 0; i < s.length(); i++) { 1.288 + char c = s.charAt(i); 1.289 + switch (c) { 1.290 + case '\t': 1.291 + sb.append('\\').append('t'); 1.292 + break; 1.293 + case '\n': 1.294 + sb.append('\\').append('n'); 1.295 + break; 1.296 + case '\r': 1.297 + sb.append('\\').append('r'); 1.298 + break; 1.299 + case '\"': 1.300 + sb.append('\\').append('\"'); 1.301 + break; 1.302 + default: 1.303 + sb.append(c); 1.304 + } 1.305 + } 1.306 + return sb.toString(); 1.307 + } 1.308 + 1.309 + String visitRef(CPRefInfo info, Void p) { 1.310 + String cn = getCheckedClassName(info); 1.311 + String nat; 1.312 + try { 1.313 + nat = stringValue(info.getNameAndTypeInfo()); 1.314 + } catch (ConstantPoolException e) { 1.315 + nat = report(e); 1.316 + } 1.317 + return cn + "." + nat; 1.318 + } 1.319 + 1.320 + String getCheckedClassName(CPRefInfo info) { 1.321 + try { 1.322 + return checkName(info.getClassName()); 1.323 + } catch (ConstantPoolException e) { 1.324 + return report(e); 1.325 + } 1.326 + } 1.327 + } 1.328 + 1.329 + 1.330 + /* If name is a valid binary name, return it; otherwise quote it. */ 1.331 + private static String checkName(String name) { 1.332 + if (name == null) 1.333 + return "null"; 1.334 + 1.335 + int len = name.length(); 1.336 + if (len == 0) 1.337 + return "\"\""; 1.338 + 1.339 + int cc = '/'; 1.340 + int cp; 1.341 + for (int k = 0; k < len; k += Character.charCount(cp)) { 1.342 + cp = name.codePointAt(k); 1.343 + if ((cc == '/' && !Character.isJavaIdentifierStart(cp)) 1.344 + || (cp != '/' && !Character.isJavaIdentifierPart(cp))) { 1.345 + return "\"" + name + "\""; 1.346 + } 1.347 + cc = cp; 1.348 + } 1.349 + 1.350 + return name; 1.351 + } 1.352 + 1.353 + private ClassWriter classWriter; 1.354 + private Options options; 1.355 +}