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