Thu, 30 Jul 2009 09:18:55 -0700
4880672: javap does not output inner interfaces of an interface
Reviewed-by: mcimadamore
jjg@46 | 1 | /* |
xdono@54 | 2 | * Copyright 2007-2008 Sun Microsystems, Inc. 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 |
jjg@46 | 7 | * published by the Free Software Foundation. Sun designates this |
jjg@46 | 8 | * particular file as subject to the "Classpath" exception as provided |
jjg@46 | 9 | * by Sun 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 | * |
jjg@46 | 21 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
jjg@46 | 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
jjg@46 | 23 | * have any 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@46 | 57 | * <p><b>This is NOT part of any API supported by Sun Microsystems. If |
jjg@46 | 58 | * 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@88 | 123 | if (lastModified != -1) { |
jjg@88 | 124 | Date lm = new Date(lastModified); |
jjg@88 | 125 | DateFormat df = DateFormat.getDateInstance(); |
jjg@88 | 126 | if (size > 0) { |
jjg@88 | 127 | println("Last modified " + df.format(lm) + "; size " + size + " bytes"); |
jjg@88 | 128 | } else { |
jjg@88 | 129 | println("Last modified " + df.format(lm)); |
jjg@88 | 130 | } |
jjg@88 | 131 | } else if (size > 0) { |
jjg@88 | 132 | println("Size " + size + " bytes"); |
jjg@88 | 133 | } |
jjg@88 | 134 | if (digestName != null && digest != null) { |
jjg@88 | 135 | StringBuilder sb = new StringBuilder(); |
jjg@88 | 136 | for (byte b: digest) |
jjg@88 | 137 | sb.append(String.format("%02x", b)); |
jjg@88 | 138 | println(digestName + " checksum " + sb); |
jjg@88 | 139 | } |
jjg@88 | 140 | } |
jjg@88 | 141 | |
jjg@46 | 142 | Attribute sfa = cf.getAttribute(Attribute.SourceFile); |
jjg@46 | 143 | if (sfa instanceof SourceFile_attribute) { |
jjg@46 | 144 | println("Compiled from \"" + getSourceFile((SourceFile_attribute) sfa) + "\""); |
jjg@46 | 145 | } |
jjg@46 | 146 | |
jjg@46 | 147 | String name = getJavaName(classFile); |
jjg@46 | 148 | AccessFlags flags = cf.access_flags; |
jjg@46 | 149 | |
jjg@46 | 150 | writeModifiers(flags.getClassModifiers()); |
jjg@46 | 151 | |
jjg@46 | 152 | if (classFile.isClass()) |
jjg@46 | 153 | print("class "); |
jjg@46 | 154 | else if (classFile.isInterface()) |
jjg@46 | 155 | print("interface "); |
jjg@46 | 156 | |
jjg@46 | 157 | print(name); |
jjg@46 | 158 | |
jjg@46 | 159 | Signature_attribute sigAttr = getSignature(cf.attributes); |
jjg@46 | 160 | if (sigAttr == null) { |
jjg@46 | 161 | // use info from class file header |
jjg@65 | 162 | if (classFile.isClass() && classFile.super_class != 0 ) { |
jjg@65 | 163 | String sn = getJavaSuperclassName(cf); |
jjg@65 | 164 | print(" extends "); |
jjg@65 | 165 | print(sn); |
jjg@46 | 166 | } |
jjg@46 | 167 | for (int i = 0; i < classFile.interfaces.length; i++) { |
jjg@46 | 168 | print(i == 0 ? (classFile.isClass() ? " implements " : " extends ") : ","); |
jjg@46 | 169 | print(getJavaInterfaceName(classFile, i)); |
jjg@46 | 170 | } |
jjg@46 | 171 | } else { |
jjg@46 | 172 | try { |
jjg@46 | 173 | Type t = sigAttr.getParsedSignature().getType(constant_pool); |
jjg@46 | 174 | // The signature parser cannot disambiguate between a |
jjg@46 | 175 | // FieldType and a ClassSignatureType that only contains a superclass type. |
jjg@46 | 176 | if (t instanceof Type.ClassSigType) |
jjg@46 | 177 | print(t); |
jjg@65 | 178 | else { |
jjg@46 | 179 | print(" extends "); |
jjg@46 | 180 | print(t); |
jjg@46 | 181 | } |
jjg@46 | 182 | } catch (ConstantPoolException e) { |
jjg@46 | 183 | print(report(e)); |
jjg@46 | 184 | } |
jjg@46 | 185 | } |
jjg@46 | 186 | |
jjg@46 | 187 | if (options.verbose) { |
jjg@46 | 188 | println(); |
jjg@46 | 189 | attrWriter.write(cf, cf.attributes, constant_pool); |
jjg@46 | 190 | println(" minor version: " + cf.minor_version); |
jjg@46 | 191 | println(" major version: " + cf.major_version); |
jjg@46 | 192 | if (!options.compat) |
jjg@46 | 193 | writeList(" flags: ", flags.getClassFlags(), NEWLINE); |
jjg@46 | 194 | constantWriter.writeConstantPool(); |
jjg@46 | 195 | println(); |
jjg@46 | 196 | } else { |
jjg@46 | 197 | if (!options.compat) |
jjg@46 | 198 | print(" "); |
jjg@46 | 199 | } |
jjg@46 | 200 | |
jjg@46 | 201 | println("{"); |
jjg@46 | 202 | writeFields(); |
jjg@46 | 203 | writeMethods(); |
jjg@46 | 204 | println("}"); |
jjg@46 | 205 | println(); |
jjg@46 | 206 | } |
jjg@46 | 207 | |
jjg@300 | 208 | protected void writeFields() { |
jjg@46 | 209 | for (Field f: classFile.fields) { |
jjg@46 | 210 | writeField(f); |
jjg@46 | 211 | } |
jjg@46 | 212 | } |
jjg@46 | 213 | |
jjg@300 | 214 | protected void writeField(Field f) { |
jjg@46 | 215 | if (!options.checkAccess(f.access_flags)) |
jjg@46 | 216 | return; |
jjg@46 | 217 | |
jjg@46 | 218 | if (!(options.showLineAndLocalVariableTables |
jjg@46 | 219 | || options.showDisassembled |
jjg@46 | 220 | || options.verbose |
jjg@46 | 221 | || options.showInternalSignatures |
jjg@46 | 222 | || options.showAllAttrs)) { |
jjg@46 | 223 | print(" "); |
jjg@46 | 224 | } |
jjg@46 | 225 | |
jjg@46 | 226 | AccessFlags flags = f.access_flags; |
jjg@46 | 227 | writeModifiers(flags.getFieldModifiers()); |
jjg@46 | 228 | Signature_attribute sigAttr = getSignature(f.attributes); |
jjg@46 | 229 | if (sigAttr == null) |
jjg@46 | 230 | print(getFieldType(f.descriptor)); |
jjg@46 | 231 | else { |
jjg@46 | 232 | try { |
jjg@46 | 233 | Type t = sigAttr.getParsedSignature().getType(constant_pool); |
jjg@46 | 234 | print(t); |
jjg@46 | 235 | } catch (ConstantPoolException e) { |
jjg@46 | 236 | // report error? |
jjg@46 | 237 | // fall back on non-generic descriptor |
jjg@46 | 238 | print(getFieldType(f.descriptor)); |
jjg@46 | 239 | } |
jjg@46 | 240 | } |
jjg@46 | 241 | print(" "); |
jjg@46 | 242 | print(getFieldName(f)); |
jjg@87 | 243 | if (options.showConstants && !options.compat) { // BUG 4111861 print static final field contents |
jjg@87 | 244 | Attribute a = f.attributes.get(Attribute.ConstantValue); |
jjg@87 | 245 | if (a instanceof ConstantValue_attribute) { |
jjg@87 | 246 | print(" = "); |
jjg@87 | 247 | ConstantValue_attribute cv = (ConstantValue_attribute) a; |
jjg@87 | 248 | print(getConstantValue(f.descriptor, cv.constantvalue_index)); |
jjg@87 | 249 | } |
jjg@87 | 250 | } |
jjg@46 | 251 | print(";"); |
jjg@46 | 252 | println(); |
jjg@46 | 253 | |
jjg@46 | 254 | if (options.showInternalSignatures) |
jjg@46 | 255 | println(" Signature: " + getValue(f.descriptor)); |
jjg@46 | 256 | |
jjg@46 | 257 | if (options.verbose && !options.compat) |
jjg@46 | 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@46 | 266 | if (options.showDisassembled || options.showLineAndLocalVariableTables) |
jjg@46 | 267 | println(); |
jjg@46 | 268 | } |
jjg@46 | 269 | |
jjg@300 | 270 | protected void writeMethods() { |
jjg@46 | 271 | for (Method m: classFile.methods) |
jjg@46 | 272 | writeMethod(m); |
jjg@46 | 273 | } |
jjg@46 | 274 | |
jjg@300 | 275 | protected void writeMethod(Method m) { |
jjg@46 | 276 | if (!options.checkAccess(m.access_flags)) |
jjg@46 | 277 | return; |
jjg@46 | 278 | |
jjg@46 | 279 | method = m; |
jjg@46 | 280 | |
jjg@46 | 281 | if (!(options.showLineAndLocalVariableTables |
jjg@46 | 282 | || options.showDisassembled |
jjg@46 | 283 | || options.verbose |
jjg@46 | 284 | || options.showInternalSignatures |
jjg@46 | 285 | || options.showAllAttrs)) { |
jjg@46 | 286 | print(" "); |
jjg@46 | 287 | } |
jjg@46 | 288 | |
jjg@46 | 289 | AccessFlags flags = m.access_flags; |
jjg@46 | 290 | |
jjg@46 | 291 | Descriptor d; |
jjg@46 | 292 | Type.MethodType methodType; |
jjg@46 | 293 | List<? extends Type> methodExceptions; |
jjg@46 | 294 | |
jjg@46 | 295 | Signature_attribute sigAttr = getSignature(m.attributes); |
jjg@46 | 296 | if (sigAttr == null) { |
jjg@46 | 297 | d = m.descriptor; |
jjg@46 | 298 | methodType = null; |
jjg@46 | 299 | methodExceptions = null; |
jjg@46 | 300 | } else { |
jjg@46 | 301 | Signature methodSig = sigAttr.getParsedSignature(); |
jjg@46 | 302 | d = methodSig; |
jjg@46 | 303 | try { |
jjg@46 | 304 | methodType = (Type.MethodType) methodSig.getType(constant_pool); |
jjg@46 | 305 | methodExceptions = methodType.throwsTypes; |
jjg@46 | 306 | if (methodExceptions != null && methodExceptions.size() == 0) |
jjg@46 | 307 | methodExceptions = null; |
jjg@46 | 308 | } catch (ConstantPoolException e) { |
jjg@46 | 309 | // report error? |
jjg@46 | 310 | // fall back on standard descriptor |
jjg@46 | 311 | methodType = null; |
jjg@46 | 312 | methodExceptions = null; |
jjg@46 | 313 | } |
jjg@46 | 314 | } |
jjg@46 | 315 | |
jjg@46 | 316 | writeModifiers(flags.getMethodModifiers()); |
jjg@46 | 317 | if (methodType != null) { |
jjg@46 | 318 | writeListIfNotEmpty("<", methodType.typeArgTypes, "> "); |
jjg@46 | 319 | } |
jjg@46 | 320 | if (getName(m).equals("<init>")) { |
jjg@46 | 321 | print(getJavaName(classFile)); |
jjg@46 | 322 | print(getParameterTypes(d, flags)); |
jjg@46 | 323 | } else if (getName(m).equals("<clinit>")) { |
jjg@46 | 324 | print("{}"); |
jjg@46 | 325 | } else { |
jjg@46 | 326 | print(getReturnType(d)); |
jjg@46 | 327 | print(" "); |
jjg@46 | 328 | print(getName(m)); |
jjg@46 | 329 | print(getParameterTypes(d, flags)); |
jjg@46 | 330 | } |
jjg@46 | 331 | |
jjg@46 | 332 | Attribute e_attr = m.attributes.get(Attribute.Exceptions); |
jjg@46 | 333 | if (e_attr != null) { // if there are generic exceptions, there must be erased exceptions |
jjg@46 | 334 | if (e_attr instanceof Exceptions_attribute) { |
jjg@46 | 335 | Exceptions_attribute exceptions = (Exceptions_attribute) e_attr; |
jjg@46 | 336 | if (options.compat) { // Bug XXXXXXX whitespace |
jjg@46 | 337 | if (!(options.showLineAndLocalVariableTables |
jjg@46 | 338 | || options.showDisassembled |
jjg@46 | 339 | || options.verbose |
jjg@46 | 340 | || options.showInternalSignatures |
jjg@46 | 341 | || options.showAllAttrs)) { |
jjg@46 | 342 | print(" "); |
jjg@46 | 343 | } |
jjg@46 | 344 | print(" "); |
jjg@46 | 345 | } |
jjg@46 | 346 | print(" throws "); |
jjg@46 | 347 | if (methodExceptions != null) { // use generic list if available |
jjg@46 | 348 | writeList("", methodExceptions, ""); |
jjg@46 | 349 | } else { |
jjg@46 | 350 | for (int i = 0; i < exceptions.number_of_exceptions; i++) { |
jjg@46 | 351 | if (i > 0) |
jjg@46 | 352 | print(", "); |
jjg@52 | 353 | print(getJavaException(exceptions, i)); |
jjg@46 | 354 | } |
jjg@46 | 355 | } |
jjg@46 | 356 | } else { |
jjg@46 | 357 | report("Unexpected or invalid value for Exceptions attribute"); |
jjg@46 | 358 | } |
jjg@46 | 359 | } |
jjg@46 | 360 | |
jjg@46 | 361 | print(";"); |
jjg@46 | 362 | println(); |
jjg@46 | 363 | |
jjg@46 | 364 | if (options.showInternalSignatures) |
jjg@46 | 365 | println(" Signature: " + getValue(m.descriptor)); |
jjg@46 | 366 | |
jjg@46 | 367 | if (options.verbose && !options.compat) |
jjg@46 | 368 | writeList(" flags: ", flags.getMethodFlags(), NEWLINE); |
jjg@46 | 369 | |
jjg@46 | 370 | Code_attribute code = null; |
jjg@46 | 371 | Attribute c_attr = m.attributes.get(Attribute.Code); |
jjg@46 | 372 | if (c_attr != null) { |
jjg@46 | 373 | if (c_attr instanceof Code_attribute) |
jjg@46 | 374 | code = (Code_attribute) c_attr; |
jjg@46 | 375 | else |
jjg@46 | 376 | report("Unexpected or invalid value for Code attribute"); |
jjg@46 | 377 | } |
jjg@46 | 378 | |
jjg@46 | 379 | if (options.showDisassembled && !options.showAllAttrs) { |
jjg@46 | 380 | if (code != null) { |
jjg@46 | 381 | println(" Code:"); |
jjg@46 | 382 | codeWriter.writeInstrs(code); |
jjg@46 | 383 | codeWriter.writeExceptionTable(code); |
jjg@46 | 384 | } |
jjg@46 | 385 | println(); |
jjg@46 | 386 | } |
jjg@46 | 387 | |
jjg@46 | 388 | if (options.showLineAndLocalVariableTables) { |
jjg@46 | 389 | if (code != null) |
jjg@46 | 390 | attrWriter.write(code, code.attributes.get(Attribute.LineNumberTable), constant_pool); |
jjg@46 | 391 | println(); |
jjg@46 | 392 | if (code != null) |
jjg@46 | 393 | attrWriter.write(code, code.attributes.get(Attribute.LocalVariableTable), constant_pool); |
jjg@46 | 394 | println(); |
jjg@46 | 395 | println(); |
jjg@46 | 396 | } |
jjg@46 | 397 | |
jjg@46 | 398 | if (options.showAllAttrs) { |
jjg@46 | 399 | Attribute[] attrs = m.attributes.attrs; |
jjg@46 | 400 | for (Attribute attr: attrs) |
jjg@46 | 401 | attrWriter.write(m, attr, constant_pool); |
jjg@46 | 402 | |
jjg@46 | 403 | // // the following condition is to mimic old javap |
jjg@46 | 404 | // if (!(attrs.length > 0 && |
jjg@46 | 405 | // attrs[attrs.length - 1] instanceof Exceptions_attribute)) |
jjg@46 | 406 | println(); |
jjg@46 | 407 | } |
jjg@46 | 408 | } |
jjg@46 | 409 | |
jjg@46 | 410 | void writeModifiers(Collection<String> items) { |
jjg@46 | 411 | for (Object item: items) { |
jjg@46 | 412 | print(item); |
jjg@46 | 413 | print(" "); |
jjg@46 | 414 | } |
jjg@46 | 415 | } |
jjg@46 | 416 | |
jjg@46 | 417 | void writeList(String prefix, Collection<?> items, String suffix) { |
jjg@46 | 418 | print(prefix); |
jjg@46 | 419 | String sep = ""; |
jjg@46 | 420 | for (Object item: items) { |
jjg@46 | 421 | print(sep); |
jjg@46 | 422 | print(item); |
jjg@46 | 423 | sep = ", "; |
jjg@46 | 424 | } |
jjg@46 | 425 | print(suffix); |
jjg@46 | 426 | } |
jjg@46 | 427 | |
jjg@46 | 428 | void writeListIfNotEmpty(String prefix, List<?> items, String suffix) { |
jjg@46 | 429 | if (items != null && items.size() > 0) |
jjg@46 | 430 | writeList(prefix, items, suffix); |
jjg@46 | 431 | } |
jjg@46 | 432 | |
jjg@46 | 433 | Signature_attribute getSignature(Attributes attributes) { |
jjg@46 | 434 | if (options.compat) // javap does not recognize recent attributes |
jjg@46 | 435 | return null; |
jjg@46 | 436 | return (Signature_attribute) attributes.get(Attribute.Signature); |
jjg@46 | 437 | } |
jjg@46 | 438 | |
jjg@46 | 439 | String adjustVarargs(AccessFlags flags, String params) { |
jjg@46 | 440 | if (flags.is(ACC_VARARGS) && !options.compat) { |
jjg@46 | 441 | int i = params.lastIndexOf("[]"); |
jjg@46 | 442 | if (i > 0) |
jjg@46 | 443 | return params.substring(0, i) + "..." + params.substring(i+2); |
jjg@46 | 444 | } |
jjg@46 | 445 | |
jjg@46 | 446 | return params; |
jjg@46 | 447 | } |
jjg@46 | 448 | |
jjg@46 | 449 | String getJavaName(ClassFile cf) { |
jjg@46 | 450 | try { |
jjg@46 | 451 | return getJavaName(cf.getName()); |
jjg@46 | 452 | } catch (ConstantPoolException e) { |
jjg@46 | 453 | return report(e); |
jjg@46 | 454 | } |
jjg@46 | 455 | } |
jjg@46 | 456 | |
jjg@46 | 457 | String getJavaSuperclassName(ClassFile cf) { |
jjg@46 | 458 | try { |
jjg@46 | 459 | return getJavaName(cf.getSuperclassName()); |
jjg@46 | 460 | } catch (ConstantPoolException e) { |
jjg@46 | 461 | return report(e); |
jjg@46 | 462 | } |
jjg@46 | 463 | } |
jjg@46 | 464 | |
jjg@46 | 465 | String getJavaInterfaceName(ClassFile cf, int index) { |
jjg@46 | 466 | try { |
jjg@46 | 467 | return getJavaName(cf.getInterfaceName(index)); |
jjg@46 | 468 | } catch (ConstantPoolException e) { |
jjg@46 | 469 | return report(e); |
jjg@46 | 470 | } |
jjg@46 | 471 | } |
jjg@46 | 472 | |
jjg@46 | 473 | String getFieldType(Descriptor d) { |
jjg@46 | 474 | try { |
jjg@46 | 475 | return d.getFieldType(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@46 | 483 | String getReturnType(Descriptor d) { |
jjg@46 | 484 | try { |
jjg@46 | 485 | return d.getReturnType(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@46 | 493 | String getParameterTypes(Descriptor d, AccessFlags flags) { |
jjg@46 | 494 | try { |
jjg@46 | 495 | return adjustVarargs(flags, d.getParameterTypes(constant_pool)); |
jjg@46 | 496 | } catch (ConstantPoolException e) { |
jjg@46 | 497 | return report(e); |
jjg@46 | 498 | } catch (DescriptorException e) { |
jjg@46 | 499 | return report(e); |
jjg@46 | 500 | } |
jjg@46 | 501 | } |
jjg@46 | 502 | |
jjg@52 | 503 | String getJavaException(Exceptions_attribute attr, int index) { |
jjg@52 | 504 | try { |
jjg@52 | 505 | return getJavaName(attr.getException(index, constant_pool)); |
jjg@52 | 506 | } catch (ConstantPoolException e) { |
jjg@52 | 507 | return report(e); |
jjg@52 | 508 | } |
jjg@52 | 509 | } |
jjg@52 | 510 | |
jjg@46 | 511 | String getValue(Descriptor d) { |
jjg@46 | 512 | try { |
jjg@46 | 513 | return d.getValue(constant_pool); |
jjg@46 | 514 | } catch (ConstantPoolException e) { |
jjg@46 | 515 | return report(e); |
jjg@46 | 516 | } |
jjg@46 | 517 | } |
jjg@46 | 518 | |
jjg@46 | 519 | String getFieldName(Field f) { |
jjg@46 | 520 | try { |
jjg@46 | 521 | return f.getName(constant_pool); |
jjg@46 | 522 | } catch (ConstantPoolException e) { |
jjg@46 | 523 | return report(e); |
jjg@46 | 524 | } |
jjg@46 | 525 | } |
jjg@46 | 526 | |
jjg@46 | 527 | String getName(Method m) { |
jjg@46 | 528 | try { |
jjg@46 | 529 | return m.getName(constant_pool); |
jjg@46 | 530 | } catch (ConstantPoolException e) { |
jjg@46 | 531 | return report(e); |
jjg@46 | 532 | } |
jjg@46 | 533 | } |
jjg@46 | 534 | |
jjg@46 | 535 | static String getJavaName(String name) { |
jjg@46 | 536 | return name.replace('/', '.'); |
jjg@46 | 537 | } |
jjg@46 | 538 | |
jjg@46 | 539 | String getSourceFile(SourceFile_attribute attr) { |
jjg@46 | 540 | try { |
jjg@46 | 541 | return attr.getSourceFile(constant_pool); |
jjg@46 | 542 | } catch (ConstantPoolException e) { |
jjg@46 | 543 | return report(e); |
jjg@46 | 544 | } |
jjg@46 | 545 | } |
jjg@46 | 546 | |
jjg@87 | 547 | /** |
jjg@87 | 548 | * Get the value of an entry in the constant pool as a Java constant. |
jjg@87 | 549 | * Characters and booleans are represented by CONSTANT_Intgere entries. |
jjg@87 | 550 | * Character and string values are processed to escape characters outside |
jjg@87 | 551 | * the basic printable ASCII set. |
jjg@87 | 552 | * @param d the descriptor, giving the expected type of the constant |
jjg@87 | 553 | * @param index the index of the value in the constant pool |
jjg@87 | 554 | * @return a printable string containing the value of the constant. |
jjg@87 | 555 | */ |
jjg@87 | 556 | String getConstantValue(Descriptor d, int index) { |
jjg@87 | 557 | try { |
jjg@87 | 558 | ConstantPool.CPInfo cpInfo = constant_pool.get(index); |
jjg@87 | 559 | |
jjg@87 | 560 | switch (cpInfo.getTag()) { |
jjg@87 | 561 | case ConstantPool.CONSTANT_Integer: { |
jjg@87 | 562 | ConstantPool.CONSTANT_Integer_info info = |
jjg@87 | 563 | (ConstantPool.CONSTANT_Integer_info) cpInfo; |
jjg@87 | 564 | String t = d.getValue(constant_pool); |
jjg@87 | 565 | if (t.equals("C")) { // character |
jjg@87 | 566 | return getConstantCharValue((char) info.value); |
jjg@87 | 567 | } else if (t.equals("Z")) { // boolean |
jjg@87 | 568 | return String.valueOf(info.value == 1); |
jjg@87 | 569 | } else { // other: assume integer |
jjg@87 | 570 | return String.valueOf(info.value); |
jjg@87 | 571 | } |
jjg@87 | 572 | } |
jjg@87 | 573 | |
jjg@87 | 574 | case ConstantPool.CONSTANT_String: { |
jjg@87 | 575 | ConstantPool.CONSTANT_String_info info = |
jjg@87 | 576 | (ConstantPool.CONSTANT_String_info) cpInfo; |
jjg@87 | 577 | return getConstantStringValue(info.getString()); |
jjg@87 | 578 | } |
jjg@87 | 579 | |
jjg@87 | 580 | default: |
jjg@87 | 581 | return constantWriter.stringValue(cpInfo); |
jjg@87 | 582 | } |
jjg@87 | 583 | } catch (ConstantPoolException e) { |
jjg@87 | 584 | return "#" + index; |
jjg@87 | 585 | } |
jjg@87 | 586 | } |
jjg@87 | 587 | |
jjg@87 | 588 | private String getConstantCharValue(char c) { |
jjg@87 | 589 | StringBuilder sb = new StringBuilder(); |
jjg@87 | 590 | sb.append('\''); |
jjg@87 | 591 | sb.append(esc(c, '\'')); |
jjg@87 | 592 | sb.append('\''); |
jjg@87 | 593 | return sb.toString(); |
jjg@87 | 594 | } |
jjg@87 | 595 | |
jjg@87 | 596 | private String getConstantStringValue(String s) { |
jjg@87 | 597 | StringBuilder sb = new StringBuilder(); |
jjg@87 | 598 | sb.append("\""); |
jjg@87 | 599 | for (int i = 0; i < s.length(); i++) { |
jjg@87 | 600 | sb.append(esc(s.charAt(i), '"')); |
jjg@87 | 601 | } |
jjg@87 | 602 | sb.append("\""); |
jjg@87 | 603 | return sb.toString(); |
jjg@87 | 604 | } |
jjg@87 | 605 | |
jjg@87 | 606 | private String esc(char c, char quote) { |
jjg@87 | 607 | if (32 <= c && c <= 126 && c != quote) |
jjg@87 | 608 | return String.valueOf(c); |
jjg@87 | 609 | else switch (c) { |
jjg@87 | 610 | case '\b': return "\\b"; |
jjg@87 | 611 | case '\n': return "\\n"; |
jjg@87 | 612 | case '\t': return "\\t"; |
jjg@87 | 613 | case '\f': return "\\f"; |
jjg@87 | 614 | case '\r': return "\\r"; |
jjg@87 | 615 | case '\\': return "\\\\"; |
jjg@87 | 616 | case '\'': return "\\'"; |
jjg@87 | 617 | case '\"': return "\\\""; |
jjg@87 | 618 | default: return String.format("\\u%04x", (int) c); |
jjg@87 | 619 | } |
jjg@87 | 620 | } |
jjg@87 | 621 | |
jjg@46 | 622 | private Options options; |
jjg@46 | 623 | private AttributeWriter attrWriter; |
jjg@46 | 624 | private CodeWriter codeWriter; |
jjg@46 | 625 | private ConstantWriter constantWriter; |
jjg@46 | 626 | private ClassFile classFile; |
jjg@88 | 627 | private URI uri; |
jjg@88 | 628 | private long lastModified; |
jjg@88 | 629 | private String digestName; |
jjg@88 | 630 | private byte[] digest; |
jjg@88 | 631 | private int size; |
jjg@46 | 632 | private ConstantPool constant_pool; |
jjg@46 | 633 | private Method method; |
jjg@46 | 634 | private static final String NEWLINE = System.getProperty("line.separator", "\n"); |
jjg@46 | 635 | } |