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

changeset 0
959103a6100f
child 2525
2eb010b6cb22
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/classes/com/sun/tools/javap/ClassWriter.java	Wed Apr 27 01:34:52 2016 +0800
     1.3 @@ -0,0 +1,756 @@
     1.4 +/*
     1.5 + * Copyright (c) 2007, 2014, Oracle and/or its affiliates. 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.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +package com.sun.tools.javap;
    1.30 +
    1.31 +import java.net.URI;
    1.32 +import java.text.DateFormat;
    1.33 +import java.util.Collection;
    1.34 +import java.util.Date;
    1.35 +import java.util.List;
    1.36 +
    1.37 +import com.sun.tools.classfile.AccessFlags;
    1.38 +import com.sun.tools.classfile.Attribute;
    1.39 +import com.sun.tools.classfile.Attributes;
    1.40 +import com.sun.tools.classfile.ClassFile;
    1.41 +import com.sun.tools.classfile.Code_attribute;
    1.42 +import com.sun.tools.classfile.ConstantPool;
    1.43 +import com.sun.tools.classfile.ConstantPoolException;
    1.44 +import com.sun.tools.classfile.ConstantValue_attribute;
    1.45 +import com.sun.tools.classfile.Descriptor;
    1.46 +import com.sun.tools.classfile.DescriptorException;
    1.47 +import com.sun.tools.classfile.Exceptions_attribute;
    1.48 +import com.sun.tools.classfile.Field;
    1.49 +import com.sun.tools.classfile.Method;
    1.50 +import com.sun.tools.classfile.Signature;
    1.51 +import com.sun.tools.classfile.Signature_attribute;
    1.52 +import com.sun.tools.classfile.SourceFile_attribute;
    1.53 +import com.sun.tools.classfile.Type;
    1.54 +import com.sun.tools.classfile.Type.ArrayType;
    1.55 +import com.sun.tools.classfile.Type.ClassSigType;
    1.56 +import com.sun.tools.classfile.Type.ClassType;
    1.57 +import com.sun.tools.classfile.Type.MethodType;
    1.58 +import com.sun.tools.classfile.Type.SimpleType;
    1.59 +import com.sun.tools.classfile.Type.TypeParamType;
    1.60 +import com.sun.tools.classfile.Type.WildcardType;
    1.61 +
    1.62 +import static com.sun.tools.classfile.AccessFlags.*;
    1.63 +
    1.64 +/*
    1.65 + *  The main javap class to write the contents of a class file as text.
    1.66 + *
    1.67 + *  <p><b>This is NOT part of any supported API.
    1.68 + *  If you write code that depends on this, you do so at your own risk.
    1.69 + *  This code and its internal interfaces are subject to change or
    1.70 + *  deletion without notice.</b>
    1.71 + */
    1.72 +public class ClassWriter extends BasicWriter {
    1.73 +    static ClassWriter instance(Context context) {
    1.74 +        ClassWriter instance = context.get(ClassWriter.class);
    1.75 +        if (instance == null)
    1.76 +            instance = new ClassWriter(context);
    1.77 +        return instance;
    1.78 +    }
    1.79 +
    1.80 +    protected ClassWriter(Context context) {
    1.81 +        super(context);
    1.82 +        context.put(ClassWriter.class, this);
    1.83 +        options = Options.instance(context);
    1.84 +        attrWriter = AttributeWriter.instance(context);
    1.85 +        codeWriter = CodeWriter.instance(context);
    1.86 +        constantWriter = ConstantWriter.instance(context);
    1.87 +    }
    1.88 +
    1.89 +    void setDigest(String name, byte[] digest) {
    1.90 +        this.digestName = name;
    1.91 +        this.digest = digest;
    1.92 +    }
    1.93 +
    1.94 +    void setFile(URI uri) {
    1.95 +        this.uri = uri;
    1.96 +    }
    1.97 +
    1.98 +    void setFileSize(int size) {
    1.99 +        this.size = size;
   1.100 +    }
   1.101 +
   1.102 +    void setLastModified(long lastModified) {
   1.103 +        this.lastModified = lastModified;
   1.104 +    }
   1.105 +
   1.106 +    protected ClassFile getClassFile() {
   1.107 +        return classFile;
   1.108 +    }
   1.109 +
   1.110 +    protected void setClassFile(ClassFile cf) {
   1.111 +        classFile = cf;
   1.112 +        constant_pool = classFile.constant_pool;
   1.113 +    }
   1.114 +
   1.115 +    protected Method getMethod() {
   1.116 +        return method;
   1.117 +    }
   1.118 +
   1.119 +    protected void setMethod(Method m) {
   1.120 +        method = m;
   1.121 +    }
   1.122 +
   1.123 +    public void write(ClassFile cf) {
   1.124 +        setClassFile(cf);
   1.125 +
   1.126 +        if (options.sysInfo || options.verbose) {
   1.127 +            if (uri != null) {
   1.128 +                if (uri.getScheme().equals("file"))
   1.129 +                    println("Classfile " + uri.getPath());
   1.130 +                else
   1.131 +                    println("Classfile " + uri);
   1.132 +            }
   1.133 +            indent(+1);
   1.134 +            if (lastModified != -1) {
   1.135 +                Date lm = new Date(lastModified);
   1.136 +                DateFormat df = DateFormat.getDateInstance();
   1.137 +                if (size > 0) {
   1.138 +                    println("Last modified " + df.format(lm) + "; size " + size + " bytes");
   1.139 +                } else {
   1.140 +                    println("Last modified " + df.format(lm));
   1.141 +                }
   1.142 +            } else if (size > 0) {
   1.143 +                println("Size " + size + " bytes");
   1.144 +            }
   1.145 +            if (digestName != null && digest != null) {
   1.146 +                StringBuilder sb = new StringBuilder();
   1.147 +                for (byte b: digest)
   1.148 +                    sb.append(String.format("%02x", b));
   1.149 +                println(digestName + " checksum " + sb);
   1.150 +            }
   1.151 +        }
   1.152 +
   1.153 +        Attribute sfa = cf.getAttribute(Attribute.SourceFile);
   1.154 +        if (sfa instanceof SourceFile_attribute) {
   1.155 +            println("Compiled from \"" + getSourceFile((SourceFile_attribute) sfa) + "\"");
   1.156 +        }
   1.157 +
   1.158 +        if (options.sysInfo || options.verbose) {
   1.159 +            indent(-1);
   1.160 +        }
   1.161 +
   1.162 +        String name = getJavaName(classFile);
   1.163 +        AccessFlags flags = cf.access_flags;
   1.164 +
   1.165 +        writeModifiers(flags.getClassModifiers());
   1.166 +
   1.167 +        if (classFile.isClass())
   1.168 +            print("class ");
   1.169 +        else if (classFile.isInterface())
   1.170 +            print("interface ");
   1.171 +
   1.172 +        print(name);
   1.173 +
   1.174 +        Signature_attribute sigAttr = getSignature(cf.attributes);
   1.175 +        if (sigAttr == null) {
   1.176 +            // use info from class file header
   1.177 +            if (classFile.isClass() && classFile.super_class != 0 ) {
   1.178 +                String sn = getJavaSuperclassName(cf);
   1.179 +                if (!sn.equals("java.lang.Object")) {
   1.180 +                    print(" extends ");
   1.181 +                    print(sn);
   1.182 +                }
   1.183 +            }
   1.184 +            for (int i = 0; i < classFile.interfaces.length; i++) {
   1.185 +                print(i == 0 ? (classFile.isClass() ? " implements " : " extends ") : ",");
   1.186 +                print(getJavaInterfaceName(classFile, i));
   1.187 +            }
   1.188 +        } else {
   1.189 +            try {
   1.190 +                Type t = sigAttr.getParsedSignature().getType(constant_pool);
   1.191 +                JavaTypePrinter p = new JavaTypePrinter(classFile.isInterface());
   1.192 +                // The signature parser cannot disambiguate between a
   1.193 +                // FieldType and a ClassSignatureType that only contains a superclass type.
   1.194 +                if (t instanceof Type.ClassSigType) {
   1.195 +                    print(p.print(t));
   1.196 +                } else if (options.verbose || !t.isObject()) {
   1.197 +                    print(" extends ");
   1.198 +                    print(p.print(t));
   1.199 +                }
   1.200 +            } catch (ConstantPoolException e) {
   1.201 +                print(report(e));
   1.202 +            }
   1.203 +        }
   1.204 +
   1.205 +        if (options.verbose) {
   1.206 +            println();
   1.207 +            indent(+1);
   1.208 +            println("minor version: " + cf.minor_version);
   1.209 +            println("major version: " + cf.major_version);
   1.210 +            writeList("flags: ", flags.getClassFlags(), "\n");
   1.211 +            indent(-1);
   1.212 +            constantWriter.writeConstantPool();
   1.213 +        } else {
   1.214 +            print(" ");
   1.215 +        }
   1.216 +
   1.217 +        println("{");
   1.218 +        indent(+1);
   1.219 +        writeFields();
   1.220 +        writeMethods();
   1.221 +        indent(-1);
   1.222 +        println("}");
   1.223 +
   1.224 +        if (options.verbose) {
   1.225 +            attrWriter.write(cf, cf.attributes, constant_pool);
   1.226 +        }
   1.227 +    }
   1.228 +    // where
   1.229 +        class JavaTypePrinter implements Type.Visitor<StringBuilder,StringBuilder> {
   1.230 +            boolean isInterface;
   1.231 +
   1.232 +            JavaTypePrinter(boolean isInterface) {
   1.233 +                this.isInterface = isInterface;
   1.234 +            }
   1.235 +
   1.236 +            String print(Type t) {
   1.237 +                return t.accept(this, new StringBuilder()).toString();
   1.238 +            }
   1.239 +
   1.240 +            String printTypeArgs(List<? extends TypeParamType> typeParamTypes) {
   1.241 +                StringBuilder builder = new StringBuilder();
   1.242 +                appendIfNotEmpty(builder, "<", typeParamTypes, "> ");
   1.243 +                return builder.toString();
   1.244 +            }
   1.245 +
   1.246 +            public StringBuilder visitSimpleType(SimpleType type, StringBuilder sb) {
   1.247 +                sb.append(getJavaName(type.name));
   1.248 +                return sb;
   1.249 +            }
   1.250 +
   1.251 +            public StringBuilder visitArrayType(ArrayType type, StringBuilder sb) {
   1.252 +                append(sb, type.elemType);
   1.253 +                sb.append("[]");
   1.254 +                return sb;
   1.255 +            }
   1.256 +
   1.257 +            public StringBuilder visitMethodType(MethodType type, StringBuilder sb) {
   1.258 +                appendIfNotEmpty(sb, "<", type.typeParamTypes, "> ");
   1.259 +                append(sb, type.returnType);
   1.260 +                append(sb, " (", type.paramTypes, ")");
   1.261 +                appendIfNotEmpty(sb, " throws ", type.throwsTypes, "");
   1.262 +                return sb;
   1.263 +            }
   1.264 +
   1.265 +            public StringBuilder visitClassSigType(ClassSigType type, StringBuilder sb) {
   1.266 +                appendIfNotEmpty(sb, "<", type.typeParamTypes, ">");
   1.267 +                if (isInterface) {
   1.268 +                    appendIfNotEmpty(sb, " extends ", type.superinterfaceTypes, "");
   1.269 +                } else {
   1.270 +                    if (type.superclassType != null
   1.271 +                            && (options.verbose || !type.superclassType.isObject())) {
   1.272 +                        sb.append(" extends ");
   1.273 +                        append(sb, type.superclassType);
   1.274 +                    }
   1.275 +                    appendIfNotEmpty(sb, " implements ", type.superinterfaceTypes, "");
   1.276 +                }
   1.277 +                return sb;
   1.278 +            }
   1.279 +
   1.280 +            public StringBuilder visitClassType(ClassType type, StringBuilder sb) {
   1.281 +                if (type.outerType != null) {
   1.282 +                    append(sb, type.outerType);
   1.283 +                    sb.append(".");
   1.284 +                }
   1.285 +                sb.append(getJavaName(type.name));
   1.286 +                appendIfNotEmpty(sb, "<", type.typeArgs, ">");
   1.287 +                return sb;
   1.288 +            }
   1.289 +
   1.290 +            public StringBuilder visitTypeParamType(TypeParamType type, StringBuilder sb) {
   1.291 +                sb.append(type.name);
   1.292 +                String sep = " extends ";
   1.293 +                if (type.classBound != null
   1.294 +                        && (options.verbose || !type.classBound.isObject())) {
   1.295 +                    sb.append(sep);
   1.296 +                    append(sb, type.classBound);
   1.297 +                    sep = " & ";
   1.298 +                }
   1.299 +                if (type.interfaceBounds != null) {
   1.300 +                    for (Type bound: type.interfaceBounds) {
   1.301 +                        sb.append(sep);
   1.302 +                        append(sb, bound);
   1.303 +                        sep = " & ";
   1.304 +                    }
   1.305 +                }
   1.306 +                return sb;
   1.307 +            }
   1.308 +
   1.309 +            public StringBuilder visitWildcardType(WildcardType type, StringBuilder sb) {
   1.310 +                switch (type.kind) {
   1.311 +                    case UNBOUNDED:
   1.312 +                        sb.append("?");
   1.313 +                        break;
   1.314 +                    case EXTENDS:
   1.315 +                        sb.append("? extends ");
   1.316 +                        append(sb, type.boundType);
   1.317 +                        break;
   1.318 +                    case SUPER:
   1.319 +                        sb.append("? super ");
   1.320 +                        append(sb, type.boundType);
   1.321 +                        break;
   1.322 +                    default:
   1.323 +                        throw new AssertionError();
   1.324 +                }
   1.325 +                return sb;
   1.326 +            }
   1.327 +
   1.328 +            private void append(StringBuilder sb, Type t) {
   1.329 +                t.accept(this, sb);
   1.330 +            }
   1.331 +
   1.332 +            private void append(StringBuilder sb, String prefix, List<? extends Type> list, String suffix) {
   1.333 +                sb.append(prefix);
   1.334 +                String sep = "";
   1.335 +                for (Type t: list) {
   1.336 +                    sb.append(sep);
   1.337 +                    append(sb, t);
   1.338 +                    sep = ", ";
   1.339 +                }
   1.340 +                sb.append(suffix);
   1.341 +            }
   1.342 +
   1.343 +            private void appendIfNotEmpty(StringBuilder sb, String prefix, List<? extends Type> list, String suffix) {
   1.344 +                if (!isEmpty(list))
   1.345 +                    append(sb, prefix, list, suffix);
   1.346 +            }
   1.347 +
   1.348 +            private boolean isEmpty(List<? extends Type> list) {
   1.349 +                return (list == null || list.isEmpty());
   1.350 +            }
   1.351 +        }
   1.352 +
   1.353 +    protected void writeFields() {
   1.354 +        for (Field f: classFile.fields) {
   1.355 +            writeField(f);
   1.356 +        }
   1.357 +    }
   1.358 +
   1.359 +    protected void writeField(Field f) {
   1.360 +        if (!options.checkAccess(f.access_flags))
   1.361 +            return;
   1.362 +
   1.363 +        AccessFlags flags = f.access_flags;
   1.364 +        writeModifiers(flags.getFieldModifiers());
   1.365 +        Signature_attribute sigAttr = getSignature(f.attributes);
   1.366 +        if (sigAttr == null)
   1.367 +            print(getJavaFieldType(f.descriptor));
   1.368 +        else {
   1.369 +            try {
   1.370 +                Type t = sigAttr.getParsedSignature().getType(constant_pool);
   1.371 +                print(getJavaName(t.toString()));
   1.372 +            } catch (ConstantPoolException e) {
   1.373 +                // report error?
   1.374 +                // fall back on non-generic descriptor
   1.375 +                print(getJavaFieldType(f.descriptor));
   1.376 +            }
   1.377 +        }
   1.378 +        print(" ");
   1.379 +        print(getFieldName(f));
   1.380 +        if (options.showConstants) {
   1.381 +            Attribute a = f.attributes.get(Attribute.ConstantValue);
   1.382 +            if (a instanceof ConstantValue_attribute) {
   1.383 +                print(" = ");
   1.384 +                ConstantValue_attribute cv = (ConstantValue_attribute) a;
   1.385 +                print(getConstantValue(f.descriptor, cv.constantvalue_index));
   1.386 +            }
   1.387 +        }
   1.388 +        print(";");
   1.389 +        println();
   1.390 +
   1.391 +        indent(+1);
   1.392 +
   1.393 +        boolean showBlank = false;
   1.394 +
   1.395 +        if (options.showDescriptors)
   1.396 +            println("descriptor: " + getValue(f.descriptor));
   1.397 +
   1.398 +        if (options.verbose)
   1.399 +            writeList("flags: ", flags.getFieldFlags(), "\n");
   1.400 +
   1.401 +        if (options.showAllAttrs) {
   1.402 +            for (Attribute attr: f.attributes)
   1.403 +                attrWriter.write(f, attr, constant_pool);
   1.404 +            showBlank = true;
   1.405 +        }
   1.406 +
   1.407 +        indent(-1);
   1.408 +
   1.409 +        if (showBlank || options.showDisassembled || options.showLineAndLocalVariableTables)
   1.410 +            println();
   1.411 +    }
   1.412 +
   1.413 +    protected void writeMethods() {
   1.414 +        for (Method m: classFile.methods)
   1.415 +            writeMethod(m);
   1.416 +        setPendingNewline(false);
   1.417 +    }
   1.418 +
   1.419 +    protected void writeMethod(Method m) {
   1.420 +        if (!options.checkAccess(m.access_flags))
   1.421 +            return;
   1.422 +
   1.423 +        method = m;
   1.424 +
   1.425 +        AccessFlags flags = m.access_flags;
   1.426 +
   1.427 +        Descriptor d;
   1.428 +        Type.MethodType methodType;
   1.429 +        List<? extends Type> methodExceptions;
   1.430 +
   1.431 +        Signature_attribute sigAttr = getSignature(m.attributes);
   1.432 +        if (sigAttr == null) {
   1.433 +            d = m.descriptor;
   1.434 +            methodType = null;
   1.435 +            methodExceptions = null;
   1.436 +        } else {
   1.437 +            Signature methodSig = sigAttr.getParsedSignature();
   1.438 +            d = methodSig;
   1.439 +            try {
   1.440 +                methodType = (Type.MethodType) methodSig.getType(constant_pool);
   1.441 +                methodExceptions = methodType.throwsTypes;
   1.442 +                if (methodExceptions != null && methodExceptions.isEmpty())
   1.443 +                    methodExceptions = null;
   1.444 +            } catch (ConstantPoolException e) {
   1.445 +                // report error?
   1.446 +                // fall back on standard descriptor
   1.447 +                methodType = null;
   1.448 +                methodExceptions = null;
   1.449 +            }
   1.450 +        }
   1.451 +
   1.452 +        writeModifiers(flags.getMethodModifiers());
   1.453 +        if (methodType != null) {
   1.454 +            print(new JavaTypePrinter(false).printTypeArgs(methodType.typeParamTypes));
   1.455 +        }
   1.456 +        if (getName(m).equals("<init>")) {
   1.457 +            print(getJavaName(classFile));
   1.458 +            print(getJavaParameterTypes(d, flags));
   1.459 +        } else if (getName(m).equals("<clinit>")) {
   1.460 +            print("{}");
   1.461 +        } else {
   1.462 +            print(getJavaReturnType(d));
   1.463 +            print(" ");
   1.464 +            print(getName(m));
   1.465 +            print(getJavaParameterTypes(d, flags));
   1.466 +        }
   1.467 +
   1.468 +        Attribute e_attr = m.attributes.get(Attribute.Exceptions);
   1.469 +        if (e_attr != null) { // if there are generic exceptions, there must be erased exceptions
   1.470 +            if (e_attr instanceof Exceptions_attribute) {
   1.471 +                Exceptions_attribute exceptions = (Exceptions_attribute) e_attr;
   1.472 +                print(" throws ");
   1.473 +                if (methodExceptions != null) { // use generic list if available
   1.474 +                    writeList("", methodExceptions, "");
   1.475 +                } else {
   1.476 +                    for (int i = 0; i < exceptions.number_of_exceptions; i++) {
   1.477 +                        if (i > 0)
   1.478 +                            print(", ");
   1.479 +                        print(getJavaException(exceptions, i));
   1.480 +                    }
   1.481 +                }
   1.482 +            } else {
   1.483 +                report("Unexpected or invalid value for Exceptions attribute");
   1.484 +            }
   1.485 +        }
   1.486 +
   1.487 +        println(";");
   1.488 +
   1.489 +        indent(+1);
   1.490 +
   1.491 +        if (options.showDescriptors) {
   1.492 +            println("descriptor: " + getValue(m.descriptor));
   1.493 +        }
   1.494 +
   1.495 +        if (options.verbose) {
   1.496 +            writeList("flags: ", flags.getMethodFlags(), "\n");
   1.497 +        }
   1.498 +
   1.499 +        Code_attribute code = null;
   1.500 +        Attribute c_attr = m.attributes.get(Attribute.Code);
   1.501 +        if (c_attr != null) {
   1.502 +            if (c_attr instanceof Code_attribute)
   1.503 +                code = (Code_attribute) c_attr;
   1.504 +            else
   1.505 +                report("Unexpected or invalid value for Code attribute");
   1.506 +        }
   1.507 +
   1.508 +        if (options.showAllAttrs) {
   1.509 +            Attribute[] attrs = m.attributes.attrs;
   1.510 +            for (Attribute attr: attrs)
   1.511 +                attrWriter.write(m, attr, constant_pool);
   1.512 +        } else if (code != null) {
   1.513 +            if (options.showDisassembled) {
   1.514 +                println("Code:");
   1.515 +                codeWriter.writeInstrs(code);
   1.516 +                codeWriter.writeExceptionTable(code);
   1.517 +            }
   1.518 +
   1.519 +            if (options.showLineAndLocalVariableTables) {
   1.520 +                attrWriter.write(code, code.attributes.get(Attribute.LineNumberTable), constant_pool);
   1.521 +                attrWriter.write(code, code.attributes.get(Attribute.LocalVariableTable), constant_pool);
   1.522 +            }
   1.523 +        }
   1.524 +
   1.525 +        indent(-1);
   1.526 +
   1.527 +        // set pendingNewline to write a newline before the next method (if any)
   1.528 +        // if a separator is desired
   1.529 +        setPendingNewline(
   1.530 +                options.showDisassembled ||
   1.531 +                options.showAllAttrs ||
   1.532 +                options.showDescriptors ||
   1.533 +                options.showLineAndLocalVariableTables ||
   1.534 +                options.verbose);
   1.535 +    }
   1.536 +
   1.537 +    void writeModifiers(Collection<String> items) {
   1.538 +        for (Object item: items) {
   1.539 +            print(item);
   1.540 +            print(" ");
   1.541 +        }
   1.542 +    }
   1.543 +
   1.544 +    void writeList(String prefix, Collection<?> items, String suffix) {
   1.545 +        print(prefix);
   1.546 +        String sep = "";
   1.547 +        for (Object item: items) {
   1.548 +            print(sep);
   1.549 +            print(item);
   1.550 +            sep = ", ";
   1.551 +        }
   1.552 +        print(suffix);
   1.553 +    }
   1.554 +
   1.555 +    void writeListIfNotEmpty(String prefix, List<?> items, String suffix) {
   1.556 +        if (items != null && items.size() > 0)
   1.557 +            writeList(prefix, items, suffix);
   1.558 +    }
   1.559 +
   1.560 +    Signature_attribute getSignature(Attributes attributes) {
   1.561 +        return (Signature_attribute) attributes.get(Attribute.Signature);
   1.562 +    }
   1.563 +
   1.564 +    String adjustVarargs(AccessFlags flags, String params) {
   1.565 +        if (flags.is(ACC_VARARGS)) {
   1.566 +            int i = params.lastIndexOf("[]");
   1.567 +            if (i > 0)
   1.568 +                return params.substring(0, i) + "..." + params.substring(i+2);
   1.569 +        }
   1.570 +
   1.571 +        return params;
   1.572 +    }
   1.573 +
   1.574 +    String getJavaName(ClassFile cf) {
   1.575 +        try {
   1.576 +            return getJavaName(cf.getName());
   1.577 +        } catch (ConstantPoolException e) {
   1.578 +            return report(e);
   1.579 +        }
   1.580 +    }
   1.581 +
   1.582 +    String getJavaSuperclassName(ClassFile cf) {
   1.583 +        try {
   1.584 +            return getJavaName(cf.getSuperclassName());
   1.585 +        } catch (ConstantPoolException e) {
   1.586 +            return report(e);
   1.587 +        }
   1.588 +    }
   1.589 +
   1.590 +    String getJavaInterfaceName(ClassFile cf, int index) {
   1.591 +        try {
   1.592 +            return getJavaName(cf.getInterfaceName(index));
   1.593 +        } catch (ConstantPoolException e) {
   1.594 +            return report(e);
   1.595 +        }
   1.596 +    }
   1.597 +
   1.598 +    String getJavaFieldType(Descriptor d) {
   1.599 +        try {
   1.600 +            return getJavaName(d.getFieldType(constant_pool));
   1.601 +        } catch (ConstantPoolException e) {
   1.602 +            return report(e);
   1.603 +        } catch (DescriptorException e) {
   1.604 +            return report(e);
   1.605 +        }
   1.606 +    }
   1.607 +
   1.608 +    String getJavaReturnType(Descriptor d) {
   1.609 +        try {
   1.610 +            return getJavaName(d.getReturnType(constant_pool));
   1.611 +        } catch (ConstantPoolException e) {
   1.612 +            return report(e);
   1.613 +        } catch (DescriptorException e) {
   1.614 +            return report(e);
   1.615 +        }
   1.616 +    }
   1.617 +
   1.618 +    String getJavaParameterTypes(Descriptor d, AccessFlags flags) {
   1.619 +        try {
   1.620 +            return getJavaName(adjustVarargs(flags, d.getParameterTypes(constant_pool)));
   1.621 +        } catch (ConstantPoolException e) {
   1.622 +            return report(e);
   1.623 +        } catch (DescriptorException e) {
   1.624 +            return report(e);
   1.625 +        }
   1.626 +    }
   1.627 +
   1.628 +    String getJavaException(Exceptions_attribute attr, int index) {
   1.629 +        try {
   1.630 +            return getJavaName(attr.getException(index, constant_pool));
   1.631 +        } catch (ConstantPoolException e) {
   1.632 +            return report(e);
   1.633 +        }
   1.634 +    }
   1.635 +
   1.636 +    String getValue(Descriptor d) {
   1.637 +        try {
   1.638 +            return d.getValue(constant_pool);
   1.639 +        } catch (ConstantPoolException e) {
   1.640 +            return report(e);
   1.641 +        }
   1.642 +    }
   1.643 +
   1.644 +    String getFieldName(Field f) {
   1.645 +        try {
   1.646 +            return f.getName(constant_pool);
   1.647 +        } catch (ConstantPoolException e) {
   1.648 +            return report(e);
   1.649 +        }
   1.650 +    }
   1.651 +
   1.652 +    String getName(Method m) {
   1.653 +        try {
   1.654 +            return m.getName(constant_pool);
   1.655 +        } catch (ConstantPoolException e) {
   1.656 +            return report(e);
   1.657 +        }
   1.658 +    }
   1.659 +
   1.660 +    static String getJavaName(String name) {
   1.661 +        return name.replace('/', '.');
   1.662 +    }
   1.663 +
   1.664 +    String getSourceFile(SourceFile_attribute attr) {
   1.665 +        try {
   1.666 +            return attr.getSourceFile(constant_pool);
   1.667 +        } catch (ConstantPoolException e) {
   1.668 +            return report(e);
   1.669 +        }
   1.670 +    }
   1.671 +
   1.672 +    /**
   1.673 +     * Get the value of an entry in the constant pool as a Java constant.
   1.674 +     * Characters and booleans are represented by CONSTANT_Intgere entries.
   1.675 +     * Character and string values are processed to escape characters outside
   1.676 +     * the basic printable ASCII set.
   1.677 +     * @param d the descriptor, giving the expected type of the constant
   1.678 +     * @param index the index of the value in the constant pool
   1.679 +     * @return a printable string containing the value of the constant.
   1.680 +     */
   1.681 +    String getConstantValue(Descriptor d, int index) {
   1.682 +        try {
   1.683 +            ConstantPool.CPInfo cpInfo = constant_pool.get(index);
   1.684 +
   1.685 +            switch (cpInfo.getTag()) {
   1.686 +                case ConstantPool.CONSTANT_Integer: {
   1.687 +                    ConstantPool.CONSTANT_Integer_info info =
   1.688 +                            (ConstantPool.CONSTANT_Integer_info) cpInfo;
   1.689 +                    String t = d.getValue(constant_pool);
   1.690 +                    if (t.equals("C")) { // character
   1.691 +                        return getConstantCharValue((char) info.value);
   1.692 +                    } else if (t.equals("Z")) { // boolean
   1.693 +                        return String.valueOf(info.value == 1);
   1.694 +                    } else { // other: assume integer
   1.695 +                        return String.valueOf(info.value);
   1.696 +                    }
   1.697 +                }
   1.698 +
   1.699 +                case ConstantPool.CONSTANT_String: {
   1.700 +                    ConstantPool.CONSTANT_String_info info =
   1.701 +                            (ConstantPool.CONSTANT_String_info) cpInfo;
   1.702 +                    return getConstantStringValue(info.getString());
   1.703 +                }
   1.704 +
   1.705 +                default:
   1.706 +                    return constantWriter.stringValue(cpInfo);
   1.707 +            }
   1.708 +        } catch (ConstantPoolException e) {
   1.709 +            return "#" + index;
   1.710 +        }
   1.711 +    }
   1.712 +
   1.713 +    private String getConstantCharValue(char c) {
   1.714 +        StringBuilder sb = new StringBuilder();
   1.715 +        sb.append('\'');
   1.716 +        sb.append(esc(c, '\''));
   1.717 +        sb.append('\'');
   1.718 +        return sb.toString();
   1.719 +    }
   1.720 +
   1.721 +    private String getConstantStringValue(String s) {
   1.722 +        StringBuilder sb = new StringBuilder();
   1.723 +        sb.append("\"");
   1.724 +        for (int i = 0; i < s.length(); i++) {
   1.725 +            sb.append(esc(s.charAt(i), '"'));
   1.726 +        }
   1.727 +        sb.append("\"");
   1.728 +        return sb.toString();
   1.729 +    }
   1.730 +
   1.731 +    private String esc(char c, char quote) {
   1.732 +        if (32 <= c && c <= 126 && c != quote)
   1.733 +            return String.valueOf(c);
   1.734 +        else switch (c) {
   1.735 +            case '\b': return "\\b";
   1.736 +            case '\n': return "\\n";
   1.737 +            case '\t': return "\\t";
   1.738 +            case '\f': return "\\f";
   1.739 +            case '\r': return "\\r";
   1.740 +            case '\\': return "\\\\";
   1.741 +            case '\'': return "\\'";
   1.742 +            case '\"': return "\\\"";
   1.743 +            default:   return String.format("\\u%04x", (int) c);
   1.744 +        }
   1.745 +    }
   1.746 +
   1.747 +    private Options options;
   1.748 +    private AttributeWriter attrWriter;
   1.749 +    private CodeWriter codeWriter;
   1.750 +    private ConstantWriter constantWriter;
   1.751 +    private ClassFile classFile;
   1.752 +    private URI uri;
   1.753 +    private long lastModified;
   1.754 +    private String digestName;
   1.755 +    private byte[] digest;
   1.756 +    private int size;
   1.757 +    private ConstantPool constant_pool;
   1.758 +    private Method method;
   1.759 +}

mercurial