/*
 * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.tools.javap;

import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URI;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import javax.lang.model.element.Modifier;
import javax.lang.model.element.NestingKind;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;

import com.sun.tools.classfile.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;

/**
 *  "Main" class for javap, normally accessed from the command line
 *  via Main, or from JSR199 via DisassemblerTool.
 *
 *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
 *  you write code that depends on this, you do so at your own risk.
 *  This code and its internal interfaces are subject to change or
 *  deletion without notice.</b>
 */
public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
    public class BadArgs extends Exception {
        static final long serialVersionUID = 8765093759964640721L;
        BadArgs(String key, Object... args) {
            super(JavapTask.this.getMessage(key, args));
            this.key = key;
            this.args = args;
        }

        BadArgs showUsage(boolean b) {
            showUsage = b;
            return this;
        }

        final String key;
        final Object[] args;
        boolean showUsage;
    }

    static abstract class Option {
        Option(boolean hasArg, String... aliases) {
            this.hasArg = hasArg;
            this.aliases = aliases;
        }

        boolean matches(String opt) {
            for (String a: aliases) {
                if (a.equals(opt))
                    return true;
            }
            return false;
        }

        boolean ignoreRest() {
            return false;
        }

        abstract void process(JavapTask task, String opt, String arg) throws BadArgs;

        final boolean hasArg;
        final String[] aliases;
    }

    static Option[] recognizedOptions = {

        new Option(false, "-help", "--help", "-?") {
            void process(JavapTask task, String opt, String arg) {
                task.options.help = true;
            }
        },

        new Option(false, "-version") {
            void process(JavapTask task, String opt, String arg) {
                task.options.version = true;
            }
        },

        new Option(false, "-fullversion") {
            void process(JavapTask task, String opt, String arg) {
                task.options.fullVersion = true;
            }
        },

        new Option(false, "-v", "-verbose", "-all") {
            void process(JavapTask task, String opt, String arg) {
                task.options.verbose = true;
                task.options.showFlags = true;
                task.options.showAllAttrs = true;
            }
        },

        new Option(false, "-l") {
            void process(JavapTask task, String opt, String arg) {
                task.options.showLineAndLocalVariableTables = true;
            }
        },

        new Option(false, "-public") {
            void process(JavapTask task, String opt, String arg) {
                task.options.accessOptions.add(opt);
                task.options.showAccess = AccessFlags.ACC_PUBLIC;
            }
        },

        new Option(false, "-protected") {
            void process(JavapTask task, String opt, String arg) {
                task.options.accessOptions.add(opt);
                task.options.showAccess = AccessFlags.ACC_PROTECTED;
            }
        },

        new Option(false, "-package") {
            void process(JavapTask task, String opt, String arg) {
                task.options.accessOptions.add(opt);
                task.options.showAccess = 0;
            }
        },

        new Option(false, "-p", "-private") {
            void process(JavapTask task, String opt, String arg) {
                if (!task.options.accessOptions.contains("-p") &&
                        !task.options.accessOptions.contains("-private")) {
                    task.options.accessOptions.add(opt);
                }
                task.options.showAccess = AccessFlags.ACC_PRIVATE;
            }
        },

        new Option(false, "-c") {
            void process(JavapTask task, String opt, String arg) {
                task.options.showDisassembled = true;
            }
        },

        new Option(false, "-s") {
            void process(JavapTask task, String opt, String arg) {
                task.options.showInternalSignatures = true;
            }
        },

//        new Option(false, "-all") {
//            void process(JavapTask task, String opt, String arg) {
//                task.options.showAllAttrs = true;
//            }
//        },

        new Option(false, "-h") {
            void process(JavapTask task, String opt, String arg) throws BadArgs {
                throw task.new BadArgs("err.h.not.supported");
            }
        },

        new Option(false, "-verify", "-verify-verbose") {
            void process(JavapTask task, String opt, String arg) throws BadArgs {
                throw task.new BadArgs("err.verify.not.supported");
            }
        },

        new Option(false, "-sysinfo") {
            void process(JavapTask task, String opt, String arg) {
                task.options.sysInfo = true;
            }
        },

        new Option(false, "-Xold") {
            void process(JavapTask task, String opt, String arg) throws BadArgs {
                task.log.println(task.getMessage("warn.Xold.not.supported"));
            }
        },

        new Option(false, "-Xnew") {
            void process(JavapTask task, String opt, String arg) throws BadArgs {
                // ignore: this _is_ the new version
            }
        },

        new Option(false, "-XDcompat") {
            void process(JavapTask task, String opt, String arg) {
                task.options.compat = true;
            }
        },

        new Option(false, "-XDjsr277") {
            void process(JavapTask task, String opt, String arg) {
                task.options.jsr277 = true;
            }
        },

        new Option(false, "-XDdetails") {
            void process(JavapTask task, String opt, String arg) {
                task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);
            }

        },

        new Option(false, "-XDdetails:") {
            @Override
            boolean matches(String opt) {
                int sep = opt.indexOf(":");
                return sep != -1 && super.matches(opt.substring(0, sep + 1));
            }

            void process(JavapTask task, String opt, String arg) throws BadArgs {
                int sep = opt.indexOf(":");
                for (String v: opt.substring(sep + 1).split("[,: ]+")) {
                    if (!handleArg(task, v))
                        throw task.new BadArgs("err.invalid.arg.for.option", v);
                }
            }

            boolean handleArg(JavapTask task, String arg) {
                if (arg.length() == 0)
                    return true;

                if (arg.equals("all")) {
                    task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);
                    return true;
                }

                boolean on = true;
                if (arg.startsWith("-")) {
                    on = false;
                    arg = arg.substring(1);
                }

                for (InstructionDetailWriter.Kind k: InstructionDetailWriter.Kind.values()) {
                    if (arg.equalsIgnoreCase(k.option)) {
                        if (on)
                            task.options.details.add(k);
                        else
                            task.options.details.remove(k);
                        return true;
                    }
                }
                return false;
            }
        },

        new Option(false, "-constants") {
            void process(JavapTask task, String opt, String arg) {
                task.options.showConstants = true;
            }
        },

        new Option(false, "-XDinner") {
            void process(JavapTask task, String opt, String arg) {
                task.options.showInnerClasses = true;
            }
        },

        new Option(false, "-XDindent:") {
            @Override
            boolean matches(String opt) {
                int sep = opt.indexOf(":");
                return sep != -1 && super.matches(opt.substring(0, sep + 1));
            }

            void process(JavapTask task, String opt, String arg) throws BadArgs {
                int sep = opt.indexOf(":");
                try {
                    task.options.indentWidth = Integer.valueOf(opt.substring(sep + 1));
                } catch (NumberFormatException e) {
                }
            }
        },

        new Option(false, "-XDtab:") {
            @Override
            boolean matches(String opt) {
                int sep = opt.indexOf(":");
                return sep != -1 && super.matches(opt.substring(0, sep + 1));
            }

            void process(JavapTask task, String opt, String arg) throws BadArgs {
                int sep = opt.indexOf(":");
                try {
                    task.options.tabColumn = Integer.valueOf(opt.substring(sep + 1));
                } catch (NumberFormatException e) {
                }
            }
        }

    };

    public JavapTask() {
        context = new Context();
        context.put(Messages.class, this);
        options = Options.instance(context);
        attributeFactory = new Attribute.Factory();
    }

    public JavapTask(Writer out,
            JavaFileManager fileManager,
            DiagnosticListener<? super JavaFileObject> diagnosticListener) {
        this();
        this.log = getPrintWriterForWriter(out);
        this.fileManager = fileManager;
        this.diagnosticListener = diagnosticListener;
    }

    public JavapTask(Writer out,
            JavaFileManager fileManager,
            DiagnosticListener<? super JavaFileObject> diagnosticListener,
            Iterable<String> options,
            Iterable<String> classes) {
        this(out, fileManager, diagnosticListener);

        this.classes = new ArrayList<String>();
        for (String classname: classes) {
            classname.getClass(); // null-check
            this.classes.add(classname);
        }

        try {
            handleOptions(options, false);
        } catch (BadArgs e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }

    public void setLocale(Locale locale) {
        if (locale == null)
            locale = Locale.getDefault();
        task_locale = locale;
    }

    public void setLog(PrintWriter log) {
        this.log = log;
    }

    public void setLog(OutputStream s) {
        setLog(getPrintWriterForStream(s));
    }

    private static PrintWriter getPrintWriterForStream(OutputStream s) {
        return new PrintWriter(s, true);
    }

    private static PrintWriter getPrintWriterForWriter(Writer w) {
        if (w == null)
            return getPrintWriterForStream(null);
        else if (w instanceof PrintWriter)
            return (PrintWriter) w;
        else
            return new PrintWriter(w, true);
    }

    public void setDiagnosticListener(DiagnosticListener<? super JavaFileObject> dl) {
        diagnosticListener = dl;
    }

    public void setDiagnosticListener(OutputStream s) {
        setDiagnosticListener(getDiagnosticListenerForStream(s));
    }

    private DiagnosticListener<JavaFileObject> getDiagnosticListenerForStream(OutputStream s) {
        return getDiagnosticListenerForWriter(getPrintWriterForStream(s));
    }

    private DiagnosticListener<JavaFileObject> getDiagnosticListenerForWriter(Writer w) {
        final PrintWriter pw = getPrintWriterForWriter(w);
        return new DiagnosticListener<JavaFileObject> () {
            public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
                switch (diagnostic.getKind()) {
                    case ERROR:
                        pw.print(getMessage("err.prefix"));
                        break;
                    case WARNING:
                        pw.print(getMessage("warn.prefix"));
                        break;
                    case NOTE:
                        pw.print(getMessage("note.prefix"));
                        break;
                }
                pw.print(" ");
                pw.println(diagnostic.getMessage(null));
            }
        };
    }

    /** Result codes.
     */
    static final int
        EXIT_OK = 0,        // Compilation completed with no errors.
        EXIT_ERROR = 1,     // Completed but reported errors.
        EXIT_CMDERR = 2,    // Bad command-line arguments
        EXIT_SYSERR = 3,    // System error or resource exhaustion.
        EXIT_ABNORMAL = 4;  // Compiler terminated abnormally

    int run(String[] args) {
        try {
            handleOptions(args);

            // the following gives consistent behavior with javac
            if (classes == null || classes.size() == 0) {
                if (options.help || options.version || options.fullVersion)
                    return EXIT_OK;
                else
                    return EXIT_CMDERR;
            }

            try {
                boolean ok = run();
                return ok ? EXIT_OK : EXIT_ERROR;
            } finally {
                if (defaultFileManager != null) {
                    try {
                        defaultFileManager.close();
                        defaultFileManager = null;
                    } catch (IOException e) {
                        throw new InternalError(e);
                    }
                }
            }
        } catch (BadArgs e) {
            reportError(e.key, e.args);
            if (e.showUsage) {
                log.println(getMessage("main.usage.summary", progname));
            }
            return EXIT_CMDERR;
        } catch (InternalError e) {
            Object[] e_args;
            if (e.getCause() == null)
                e_args = e.args;
            else {
                e_args = new Object[e.args.length + 1];
                e_args[0] = e.getCause();
                System.arraycopy(e.args, 0, e_args, 1, e.args.length);
            }
            reportError("err.internal.error", e_args);
            return EXIT_ABNORMAL;
        } finally {
            log.flush();
        }
    }

    public void handleOptions(String[] args) throws BadArgs {
        handleOptions(Arrays.asList(args), true);
    }

    private void handleOptions(Iterable<String> args, boolean allowClasses) throws BadArgs {
        if (log == null) {
            log = getPrintWriterForStream(System.out);
            if (diagnosticListener == null)
              diagnosticListener = getDiagnosticListenerForStream(System.err);
        } else {
            if (diagnosticListener == null)
              diagnosticListener = getDiagnosticListenerForWriter(log);
        }


        if (fileManager == null)
            fileManager = getDefaultFileManager(diagnosticListener, log);

        Iterator<String> iter = args.iterator();
        boolean noArgs = !iter.hasNext();

        while (iter.hasNext()) {
            String arg = iter.next();
            if (arg.startsWith("-"))
                handleOption(arg, iter);
            else if (allowClasses) {
                if (classes == null)
                    classes = new ArrayList<String>();
                classes.add(arg);
                while (iter.hasNext())
                    classes.add(iter.next());
            } else
                throw new BadArgs("err.unknown.option", arg).showUsage(true);
        }

        if (!options.compat && options.accessOptions.size() > 1) {
            StringBuilder sb = new StringBuilder();
            for (String opt: options.accessOptions) {
                if (sb.length() > 0)
                    sb.append(" ");
                sb.append(opt);
            }
            throw new BadArgs("err.incompatible.options", sb);
        }

        if ((classes == null || classes.size() == 0) &&
                !(noArgs || options.help || options.version || options.fullVersion)) {
            throw new BadArgs("err.no.classes.specified");
        }

        if (noArgs || options.help)
            showHelp();

        if (options.version || options.fullVersion)
            showVersion(options.fullVersion);
    }

    private void handleOption(String name, Iterator<String> rest) throws BadArgs {
        for (Option o: recognizedOptions) {
            if (o.matches(name)) {
                if (o.hasArg) {
                    if (rest.hasNext())
                        o.process(this, name, rest.next());
                    else
                        throw new BadArgs("err.missing.arg", name).showUsage(true);
                } else
                    o.process(this, name, null);

                if (o.ignoreRest()) {
                    while (rest.hasNext())
                        rest.next();
                }
                return;
            }
        }

        if (fileManager.handleOption(name, rest))
            return;

        throw new BadArgs("err.unknown.option", name).showUsage(true);
    }

    public Boolean call() {
        return run();
    }

    public boolean run() {
        if (classes == null || classes.size() == 0)
            return false;

        context.put(PrintWriter.class, log);
        ClassWriter classWriter = ClassWriter.instance(context);
        SourceWriter sourceWriter = SourceWriter.instance(context);
        sourceWriter.setFileManager(fileManager);

        attributeFactory.setCompat(options.compat);
        attributeFactory.setJSR277(options.jsr277);

        boolean ok = true;

        for (String className: classes) {
            JavaFileObject fo;
            try {
                writeClass(classWriter, className);
            } catch (ConstantPoolException e) {
                reportError("err.bad.constant.pool", className, e.getLocalizedMessage());
                ok = false;
            } catch (EOFException e) {
                reportError("err.end.of.file", className);
                ok = false;
            } catch (FileNotFoundException e) {
                reportError("err.file.not.found", e.getLocalizedMessage());
                ok = false;
            } catch (IOException e) {
                //e.printStackTrace();
                Object msg = e.getLocalizedMessage();
                if (msg == null)
                    msg = e;
                reportError("err.ioerror", className, msg);
                ok = false;
            } catch (Throwable t) {
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                t.printStackTrace(pw);
                pw.close();
                reportError("err.crash", t.toString(), sw.toString());
                ok = false;
            }
        }

        return ok;
    }

    protected boolean writeClass(ClassWriter classWriter, String className)
            throws IOException, ConstantPoolException {
        JavaFileObject fo = open(className);
        if (fo == null) {
            reportError("err.class.not.found", className);
            return false;
        }

        ClassFileInfo cfInfo = read(fo);
        if (!className.endsWith(".class")) {
            String cfName = cfInfo.cf.getName();
            if (!cfName.replaceAll("[/$]", ".").equals(className.replaceAll("[/$]", ".")))
                reportWarning("warn.unexpected.class", className, cfName.replace('/', '.'));
        }
        write(cfInfo);

        if (options.showInnerClasses) {
            ClassFile cf = cfInfo.cf;
            Attribute a = cf.getAttribute(Attribute.InnerClasses);
            if (a instanceof InnerClasses_attribute) {
                InnerClasses_attribute inners = (InnerClasses_attribute) a;
                try {
                    boolean ok = true;
                    for (int i = 0; i < inners.classes.length; i++) {
                        int outerIndex = inners.classes[i].outer_class_info_index;
                        ConstantPool.CONSTANT_Class_info outerClassInfo = cf.constant_pool.getClassInfo(outerIndex);
                        String outerClassName = outerClassInfo.getName();
                        if (outerClassName.equals(cf.getName())) {
                            int innerIndex = inners.classes[i].inner_class_info_index;
                            ConstantPool.CONSTANT_Class_info innerClassInfo = cf.constant_pool.getClassInfo(innerIndex);
                            String innerClassName = innerClassInfo.getName();
                            classWriter.println("// inner class " + innerClassName.replaceAll("[/$]", "."));
                            classWriter.println();
                            ok = ok & writeClass(classWriter, innerClassName);
                        }
                    }
                    return ok;
                } catch (ConstantPoolException e) {
                    reportError("err.bad.innerclasses.attribute", className);
                    return false;
                }
            } else if (a != null) {
                reportError("err.bad.innerclasses.attribute", className);
                return false;
            }
        }

        return true;
    }

    protected JavaFileObject open(String className) throws IOException {
        // for compatibility, first see if it is a class name
        JavaFileObject fo = getClassFileObject(className);
        if (fo != null)
            return fo;

        // see if it is an inner class, by replacing dots to $, starting from the right
        String cn = className;
        int lastDot;
        while ((lastDot = cn.lastIndexOf(".")) != -1) {
            cn = cn.substring(0, lastDot) + "$" + cn.substring(lastDot + 1);
            fo = getClassFileObject(cn);
            if (fo != null)
                return fo;
        }

        if (!className.endsWith(".class"))
            return null;

        if (fileManager instanceof StandardJavaFileManager) {
            StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
            fo = sfm.getJavaFileObjects(className).iterator().next();
            if (fo != null && fo.getLastModified() != 0) {
                return fo;
            }
        }

        // see if it is a URL, and if so, wrap it in just enough of a JavaFileObject
        // to suit javap's needs
        if (className.matches("^[A-Za-z]+:.*")) {
            try {
                final URI uri = new URI(className);
                final URL url = uri.toURL();
                final URLConnection conn = url.openConnection();
                return new JavaFileObject() {
                    public Kind getKind() {
                        return JavaFileObject.Kind.CLASS;
                    }

                    public boolean isNameCompatible(String simpleName, Kind kind) {
                        throw new UnsupportedOperationException();
                    }

                    public NestingKind getNestingKind() {
                        throw new UnsupportedOperationException();
                    }

                    public Modifier getAccessLevel() {
                        throw new UnsupportedOperationException();
                    }

                    public URI toUri() {
                        return uri;
                    }

                    public String getName() {
                        return url.toString();
                    }

                    public InputStream openInputStream() throws IOException {
                        return conn.getInputStream();
                    }

                    public OutputStream openOutputStream() throws IOException {
                        throw new UnsupportedOperationException();
                    }

                    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
                        throw new UnsupportedOperationException();
                    }

                    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
                        throw new UnsupportedOperationException();
                    }

                    public Writer openWriter() throws IOException {
                        throw new UnsupportedOperationException();
                    }

                    public long getLastModified() {
                        return conn.getLastModified();
                    }

                    public boolean delete() {
                        throw new UnsupportedOperationException();
                    }

                };
            } catch (URISyntaxException ignore) {
            } catch (IOException ignore) {
            }
        }

        return null;
    }

    public static class ClassFileInfo {
        ClassFileInfo(JavaFileObject fo, ClassFile cf, byte[] digest, int size) {
            this.fo = fo;
            this.cf = cf;
            this.digest = digest;
            this.size = size;
        }
        public final JavaFileObject fo;
        public final ClassFile cf;
        public final byte[] digest;
        public final int size;
    }

    public ClassFileInfo read(JavaFileObject fo) throws IOException, ConstantPoolException {
        InputStream in = fo.openInputStream();
        try {
            SizeInputStream sizeIn = null;
            MessageDigest md  = null;
            if (options.sysInfo || options.verbose) {
                try {
                    md = MessageDigest.getInstance("MD5");
                } catch (NoSuchAlgorithmException ignore) {
                }
                in = new DigestInputStream(in, md);
                in = sizeIn = new SizeInputStream(in);
            }

            ClassFile cf = ClassFile.read(in, attributeFactory);
            byte[] digest = (md == null) ? null : md.digest();
            int size = (sizeIn == null) ? -1 : sizeIn.size();
            return new ClassFileInfo(fo, cf, digest, size);
        } finally {
            in.close();
        }
    }

    public void write(ClassFileInfo info) {
        ClassWriter classWriter = ClassWriter.instance(context);
        if (options.sysInfo || options.verbose) {
            classWriter.setFile(info.fo.toUri());
            classWriter.setLastModified(info.fo.getLastModified());
            classWriter.setDigest("MD5", info.digest);
            classWriter.setFileSize(info.size);
        }

        classWriter.write(info.cf);
    }

    protected void setClassFile(ClassFile classFile) {
        ClassWriter classWriter = ClassWriter.instance(context);
        classWriter.setClassFile(classFile);
    }

    protected void setMethod(Method enclosingMethod) {
        ClassWriter classWriter = ClassWriter.instance(context);
        classWriter.setMethod(enclosingMethod);
    }

    protected void write(Attribute value) {
        AttributeWriter attrWriter = AttributeWriter.instance(context);
        ClassWriter classWriter = ClassWriter.instance(context);
        ClassFile cf = classWriter.getClassFile();
        attrWriter.write(cf, value, cf.constant_pool);
    }

    protected void write(Attributes attrs) {
        AttributeWriter attrWriter = AttributeWriter.instance(context);
        ClassWriter classWriter = ClassWriter.instance(context);
        ClassFile cf = classWriter.getClassFile();
        attrWriter.write(cf, attrs, cf.constant_pool);
    }

    protected void write(ConstantPool constant_pool) {
        ConstantWriter constantWriter = ConstantWriter.instance(context);
        constantWriter.writeConstantPool(constant_pool);
    }

    protected void write(ConstantPool constant_pool, int value) {
        ConstantWriter constantWriter = ConstantWriter.instance(context);
        constantWriter.write(value);
    }

    protected void write(ConstantPool.CPInfo value) {
        ConstantWriter constantWriter = ConstantWriter.instance(context);
        constantWriter.println(value);
    }

    protected void write(Field value) {
        ClassWriter classWriter = ClassWriter.instance(context);
        classWriter.writeField(value);
    }

    protected void write(Method value) {
        ClassWriter classWriter = ClassWriter.instance(context);
        classWriter.writeMethod(value);
    }

    private JavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
        if (defaultFileManager == null)
            defaultFileManager = JavapFileManager.create(dl, log);
        return defaultFileManager;
    }

    private JavaFileObject getClassFileObject(String className) throws IOException {
        JavaFileObject fo;
        fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
        if (fo == null)
            fo = fileManager.getJavaFileForInput(StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
        return fo;
    }

    private void showHelp() {
        log.println(getMessage("main.usage", progname));
        for (Option o: recognizedOptions) {
            String name = o.aliases[0].substring(1); // there must always be at least one name
            if (name.startsWith("X") || name.equals("fullversion") || name.equals("h") || name.equals("verify"))
                continue;
            log.println(getMessage("main.opt." + name));
        }
        String[] fmOptions = { "-classpath", "-bootclasspath" };
        for (String o: fmOptions) {
            if (fileManager.isSupportedOption(o) == -1)
                continue;
            String name = o.substring(1);
            log.println(getMessage("main.opt." + name));
        }

    }

    private void showVersion(boolean full) {
        log.println(version(full ? "full" : "release"));
    }

    private static final String versionRBName = "com.sun.tools.javap.resources.version";
    private static ResourceBundle versionRB;

    private String version(String key) {
        // key=version:  mm.nn.oo[-milestone]
        // key=full:     mm.mm.oo[-milestone]-build
        if (versionRB == null) {
            try {
                versionRB = ResourceBundle.getBundle(versionRBName);
            } catch (MissingResourceException e) {
                return getMessage("version.resource.missing", System.getProperty("java.version"));
            }
        }
        try {
            return versionRB.getString(key);
        }
        catch (MissingResourceException e) {
            return getMessage("version.unknown", System.getProperty("java.version"));
        }
    }

    private void reportError(String key, Object... args) {
        diagnosticListener.report(createDiagnostic(Diagnostic.Kind.ERROR, key, args));
    }

    private void reportNote(String key, Object... args) {
        diagnosticListener.report(createDiagnostic(Diagnostic.Kind.NOTE, key, args));
    }

    private void reportWarning(String key, Object... args) {
        diagnosticListener.report(createDiagnostic(Diagnostic.Kind.WARNING, key, args));
    }

    private Diagnostic<JavaFileObject> createDiagnostic(
            final Diagnostic.Kind kind, final String key, final Object... args) {
        return new Diagnostic<JavaFileObject>() {
            public Kind getKind() {
                return kind;
            }

            public JavaFileObject getSource() {
                return null;
            }

            public long getPosition() {
                return Diagnostic.NOPOS;
            }

            public long getStartPosition() {
                return Diagnostic.NOPOS;
            }

            public long getEndPosition() {
                return Diagnostic.NOPOS;
            }

            public long getLineNumber() {
                return Diagnostic.NOPOS;
            }

            public long getColumnNumber() {
                return Diagnostic.NOPOS;
            }

            public String getCode() {
                return key;
            }

            public String getMessage(Locale locale) {
                return JavapTask.this.getMessage(locale, key, args);
            }

            @Override
            public String toString() {
                return getClass().getName() + "[key=" + key + ",args=" + Arrays.asList(args) + "]";
            }

        };

    }

    public String getMessage(String key, Object... args) {
        return getMessage(task_locale, key, args);
    }

    public String getMessage(Locale locale, String key, Object... args) {
        if (bundles == null) {
            // could make this a HashMap<Locale,SoftReference<ResourceBundle>>
            // and for efficiency, keep a hard reference to the bundle for the task
            // locale
            bundles = new HashMap<Locale, ResourceBundle>();
        }

        if (locale == null)
            locale = Locale.getDefault();

        ResourceBundle b = bundles.get(locale);
        if (b == null) {
            try {
                b = ResourceBundle.getBundle("com.sun.tools.javap.resources.javap", locale);
                bundles.put(locale, b);
            } catch (MissingResourceException e) {
                throw new InternalError("Cannot find javap resource bundle for locale " + locale);
            }
        }

        try {
            return MessageFormat.format(b.getString(key), args);
        } catch (MissingResourceException e) {
            throw new InternalError(e, key);
        }
    }

    protected Context context;
    JavaFileManager fileManager;
    JavaFileManager defaultFileManager;
    PrintWriter log;
    DiagnosticListener<? super JavaFileObject> diagnosticListener;
    List<String> classes;
    Options options;
    //ResourceBundle bundle;
    Locale task_locale;
    Map<Locale, ResourceBundle> bundles;
    protected Attribute.Factory attributeFactory;

    private static final String progname = "javap";

    private static class SizeInputStream extends FilterInputStream {
        SizeInputStream(InputStream in) {
            super(in);
        }

        int size() {
            return size;
        }

        @Override
        public int read(byte[] buf, int offset, int length) throws IOException {
            int n = super.read(buf, offset, length);
            if (n > 0)
                size += n;
            return n;
        }

        @Override
        public int read() throws IOException {
            int b = super.read();
            size += 1;
            return b;
        }

        private int size;
    }
}
