Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java
38899 views
/*1* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.javap;2627import java.io.EOFException;28import java.io.FileNotFoundException;29import java.io.FilterInputStream;30import java.io.InputStream;31import java.io.IOException;32import java.io.OutputStream;33import java.io.PrintWriter;34import java.io.Reader;35import java.io.StringWriter;36import java.io.Writer;37import java.net.URI;38import java.security.DigestInputStream;39import java.security.MessageDigest;40import java.security.NoSuchAlgorithmException;41import java.text.MessageFormat;42import java.util.ArrayList;43import java.util.Arrays;44import java.util.EnumSet;45import java.util.HashMap;46import java.util.Iterator;47import java.util.List;48import java.util.Locale;49import java.util.Map;50import java.util.MissingResourceException;51import java.util.ResourceBundle;5253import javax.lang.model.element.Modifier;54import javax.lang.model.element.NestingKind;55import javax.tools.Diagnostic;56import javax.tools.DiagnosticListener;57import javax.tools.JavaFileManager;58import javax.tools.JavaFileObject;59import javax.tools.StandardJavaFileManager;60import javax.tools.StandardLocation;6162import com.sun.tools.classfile.*;63import java.net.URISyntaxException;64import java.net.URL;65import java.net.URLConnection;6667/**68* "Main" class for javap, normally accessed from the command line69* via Main, or from JSR199 via DisassemblerTool.70*71* <p><b>This is NOT part of any supported API.72* If you write code that depends on this, you do so at your own risk.73* This code and its internal interfaces are subject to change or74* deletion without notice.</b>75*/76public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {77public class BadArgs extends Exception {78static final long serialVersionUID = 8765093759964640721L;79BadArgs(String key, Object... args) {80super(JavapTask.this.getMessage(key, args));81this.key = key;82this.args = args;83}8485BadArgs showUsage(boolean b) {86showUsage = b;87return this;88}8990final String key;91final Object[] args;92boolean showUsage;93}9495static abstract class Option {96Option(boolean hasArg, String... aliases) {97this.hasArg = hasArg;98this.aliases = aliases;99}100101boolean matches(String opt) {102for (String a: aliases) {103if (a.equals(opt))104return true;105}106return false;107}108109boolean ignoreRest() {110return false;111}112113abstract void process(JavapTask task, String opt, String arg) throws BadArgs;114115final boolean hasArg;116final String[] aliases;117}118119static final Option[] recognizedOptions = {120121new Option(false, "-help", "--help", "-?") {122void process(JavapTask task, String opt, String arg) {123task.options.help = true;124}125},126127new Option(false, "-version") {128void process(JavapTask task, String opt, String arg) {129task.options.version = true;130}131},132133new Option(false, "-fullversion") {134void process(JavapTask task, String opt, String arg) {135task.options.fullVersion = true;136}137},138139new Option(false, "-v", "-verbose", "-all") {140void process(JavapTask task, String opt, String arg) {141task.options.verbose = true;142task.options.showDescriptors = true;143task.options.showFlags = true;144task.options.showAllAttrs = true;145}146},147148new Option(false, "-l") {149void process(JavapTask task, String opt, String arg) {150task.options.showLineAndLocalVariableTables = true;151}152},153154new Option(false, "-public") {155void process(JavapTask task, String opt, String arg) {156task.options.accessOptions.add(opt);157task.options.showAccess = AccessFlags.ACC_PUBLIC;158}159},160161new Option(false, "-protected") {162void process(JavapTask task, String opt, String arg) {163task.options.accessOptions.add(opt);164task.options.showAccess = AccessFlags.ACC_PROTECTED;165}166},167168new Option(false, "-package") {169void process(JavapTask task, String opt, String arg) {170task.options.accessOptions.add(opt);171task.options.showAccess = 0;172}173},174175new Option(false, "-p", "-private") {176void process(JavapTask task, String opt, String arg) {177if (!task.options.accessOptions.contains("-p") &&178!task.options.accessOptions.contains("-private")) {179task.options.accessOptions.add(opt);180}181task.options.showAccess = AccessFlags.ACC_PRIVATE;182}183},184185new Option(false, "-c") {186void process(JavapTask task, String opt, String arg) {187task.options.showDisassembled = true;188}189},190191new Option(false, "-s") {192void process(JavapTask task, String opt, String arg) {193task.options.showDescriptors = true;194}195},196197new Option(false, "-sysinfo") {198void process(JavapTask task, String opt, String arg) {199task.options.sysInfo = true;200}201},202203new Option(false, "-XDdetails") {204void process(JavapTask task, String opt, String arg) {205task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);206}207208},209210new Option(false, "-XDdetails:") {211@Override212boolean matches(String opt) {213int sep = opt.indexOf(":");214return sep != -1 && super.matches(opt.substring(0, sep + 1));215}216217void process(JavapTask task, String opt, String arg) throws BadArgs {218int sep = opt.indexOf(":");219for (String v: opt.substring(sep + 1).split("[,: ]+")) {220if (!handleArg(task, v))221throw task.new BadArgs("err.invalid.arg.for.option", v);222}223}224225boolean handleArg(JavapTask task, String arg) {226if (arg.length() == 0)227return true;228229if (arg.equals("all")) {230task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);231return true;232}233234boolean on = true;235if (arg.startsWith("-")) {236on = false;237arg = arg.substring(1);238}239240for (InstructionDetailWriter.Kind k: InstructionDetailWriter.Kind.values()) {241if (arg.equalsIgnoreCase(k.option)) {242if (on)243task.options.details.add(k);244else245task.options.details.remove(k);246return true;247}248}249return false;250}251},252253new Option(false, "-constants") {254void process(JavapTask task, String opt, String arg) {255task.options.showConstants = true;256}257},258259new Option(false, "-XDinner") {260void process(JavapTask task, String opt, String arg) {261task.options.showInnerClasses = true;262}263},264265new Option(false, "-XDindent:") {266@Override267boolean matches(String opt) {268int sep = opt.indexOf(":");269return sep != -1 && super.matches(opt.substring(0, sep + 1));270}271272void process(JavapTask task, String opt, String arg) throws BadArgs {273int sep = opt.indexOf(":");274try {275int i = Integer.valueOf(opt.substring(sep + 1));276if (i > 0) // silently ignore invalid values277task.options.indentWidth = i;278} catch (NumberFormatException e) {279}280}281},282283new Option(false, "-XDtab:") {284@Override285boolean matches(String opt) {286int sep = opt.indexOf(":");287return sep != -1 && super.matches(opt.substring(0, sep + 1));288}289290void process(JavapTask task, String opt, String arg) throws BadArgs {291int sep = opt.indexOf(":");292try {293int i = Integer.valueOf(opt.substring(sep + 1));294if (i > 0) // silently ignore invalid values295task.options.tabColumn = i;296} catch (NumberFormatException e) {297}298}299}300301};302303public JavapTask() {304context = new Context();305context.put(Messages.class, this);306options = Options.instance(context);307attributeFactory = new Attribute.Factory();308}309310public JavapTask(Writer out,311JavaFileManager fileManager,312DiagnosticListener<? super JavaFileObject> diagnosticListener) {313this();314this.log = getPrintWriterForWriter(out);315this.fileManager = fileManager;316this.diagnosticListener = diagnosticListener;317}318319public JavapTask(Writer out,320JavaFileManager fileManager,321DiagnosticListener<? super JavaFileObject> diagnosticListener,322Iterable<String> options,323Iterable<String> classes) {324this(out, fileManager, diagnosticListener);325326this.classes = new ArrayList<String>();327for (String classname: classes) {328classname.getClass(); // null-check329this.classes.add(classname);330}331332try {333if (options != null)334handleOptions(options, false);335} catch (BadArgs e) {336throw new IllegalArgumentException(e.getMessage());337}338}339340public void setLocale(Locale locale) {341if (locale == null)342locale = Locale.getDefault();343task_locale = locale;344}345346public void setLog(Writer log) {347this.log = getPrintWriterForWriter(log);348}349350public void setLog(OutputStream s) {351setLog(getPrintWriterForStream(s));352}353354private static PrintWriter getPrintWriterForStream(OutputStream s) {355return new PrintWriter(s == null ? System.err : s, true);356}357358private static PrintWriter getPrintWriterForWriter(Writer w) {359if (w == null)360return getPrintWriterForStream(null);361else if (w instanceof PrintWriter)362return (PrintWriter) w;363else364return new PrintWriter(w, true);365}366367public void setDiagnosticListener(DiagnosticListener<? super JavaFileObject> dl) {368diagnosticListener = dl;369}370371public void setDiagnosticListener(OutputStream s) {372setDiagnosticListener(getDiagnosticListenerForStream(s));373}374375private DiagnosticListener<JavaFileObject> getDiagnosticListenerForStream(OutputStream s) {376return getDiagnosticListenerForWriter(getPrintWriterForStream(s));377}378379private DiagnosticListener<JavaFileObject> getDiagnosticListenerForWriter(Writer w) {380final PrintWriter pw = getPrintWriterForWriter(w);381return new DiagnosticListener<JavaFileObject> () {382public void report(Diagnostic<? extends JavaFileObject> diagnostic) {383switch (diagnostic.getKind()) {384case ERROR:385pw.print(getMessage("err.prefix"));386break;387case WARNING:388pw.print(getMessage("warn.prefix"));389break;390case NOTE:391pw.print(getMessage("note.prefix"));392break;393}394pw.print(" ");395pw.println(diagnostic.getMessage(null));396}397};398}399400/** Result codes.401*/402static final int403EXIT_OK = 0, // Compilation completed with no errors.404EXIT_ERROR = 1, // Completed but reported errors.405EXIT_CMDERR = 2, // Bad command-line arguments406EXIT_SYSERR = 3, // System error or resource exhaustion.407EXIT_ABNORMAL = 4; // Compiler terminated abnormally408409int run(String[] args) {410try {411handleOptions(args);412413// the following gives consistent behavior with javac414if (classes == null || classes.size() == 0) {415if (options.help || options.version || options.fullVersion)416return EXIT_OK;417else418return EXIT_CMDERR;419}420421try {422return run();423} finally {424if (defaultFileManager != null) {425try {426defaultFileManager.close();427defaultFileManager = null;428} catch (IOException e) {429throw new InternalError(e);430}431}432}433} catch (BadArgs e) {434reportError(e.key, e.args);435if (e.showUsage) {436printLines(getMessage("main.usage.summary", progname));437}438return EXIT_CMDERR;439} catch (InternalError e) {440Object[] e_args;441if (e.getCause() == null)442e_args = e.args;443else {444e_args = new Object[e.args.length + 1];445e_args[0] = e.getCause();446System.arraycopy(e.args, 0, e_args, 1, e.args.length);447}448reportError("err.internal.error", e_args);449return EXIT_ABNORMAL;450} finally {451log.flush();452}453}454455public void handleOptions(String[] args) throws BadArgs {456handleOptions(Arrays.asList(args), true);457}458459private void handleOptions(Iterable<String> args, boolean allowClasses) throws BadArgs {460if (log == null) {461log = getPrintWriterForStream(System.out);462if (diagnosticListener == null)463diagnosticListener = getDiagnosticListenerForStream(System.err);464} else {465if (diagnosticListener == null)466diagnosticListener = getDiagnosticListenerForWriter(log);467}468469470if (fileManager == null)471fileManager = getDefaultFileManager(diagnosticListener, log);472473Iterator<String> iter = args.iterator();474boolean noArgs = !iter.hasNext();475476while (iter.hasNext()) {477String arg = iter.next();478if (arg.startsWith("-"))479handleOption(arg, iter);480else if (allowClasses) {481if (classes == null)482classes = new ArrayList<String>();483classes.add(arg);484while (iter.hasNext())485classes.add(iter.next());486} else487throw new BadArgs("err.unknown.option", arg).showUsage(true);488}489490if (options.accessOptions.size() > 1) {491StringBuilder sb = new StringBuilder();492for (String opt: options.accessOptions) {493if (sb.length() > 0)494sb.append(" ");495sb.append(opt);496}497throw new BadArgs("err.incompatible.options", sb);498}499500if ((classes == null || classes.size() == 0) &&501!(noArgs || options.help || options.version || options.fullVersion)) {502throw new BadArgs("err.no.classes.specified");503}504505if (noArgs || options.help)506showHelp();507508if (options.version || options.fullVersion)509showVersion(options.fullVersion);510}511512private void handleOption(String name, Iterator<String> rest) throws BadArgs {513for (Option o: recognizedOptions) {514if (o.matches(name)) {515if (o.hasArg) {516if (rest.hasNext())517o.process(this, name, rest.next());518else519throw new BadArgs("err.missing.arg", name).showUsage(true);520} else521o.process(this, name, null);522523if (o.ignoreRest()) {524while (rest.hasNext())525rest.next();526}527return;528}529}530531try {532if (fileManager.handleOption(name, rest))533return;534} catch (IllegalArgumentException e) {535throw new BadArgs("err.invalid.use.of.option", name).showUsage(true);536}537538throw new BadArgs("err.unknown.option", name).showUsage(true);539}540541public Boolean call() {542return run() == 0;543}544545public int run() {546if (classes == null || classes.isEmpty()) {547return EXIT_ERROR;548}549550context.put(PrintWriter.class, log);551ClassWriter classWriter = ClassWriter.instance(context);552SourceWriter sourceWriter = SourceWriter.instance(context);553sourceWriter.setFileManager(fileManager);554555int result = EXIT_OK;556557for (String className: classes) {558try {559result = writeClass(classWriter, className);560} catch (ConstantPoolException e) {561reportError("err.bad.constant.pool", className, e.getLocalizedMessage());562result = EXIT_ERROR;563} catch (EOFException e) {564reportError("err.end.of.file", className);565result = EXIT_ERROR;566} catch (FileNotFoundException e) {567reportError("err.file.not.found", e.getLocalizedMessage());568result = EXIT_ERROR;569} catch (IOException e) {570//e.printStackTrace();571Object msg = e.getLocalizedMessage();572if (msg == null) {573msg = e;574}575reportError("err.ioerror", className, msg);576result = EXIT_ERROR;577} catch (Throwable t) {578StringWriter sw = new StringWriter();579PrintWriter pw = new PrintWriter(sw);580t.printStackTrace(pw);581pw.close();582reportError("err.crash", t.toString(), sw.toString());583result = EXIT_ABNORMAL;584}585}586587return result;588}589590protected int writeClass(ClassWriter classWriter, String className)591throws IOException, ConstantPoolException {592JavaFileObject fo = open(className);593if (fo == null) {594reportError("err.class.not.found", className);595return EXIT_ERROR;596}597598ClassFileInfo cfInfo = read(fo);599if (!className.endsWith(".class")) {600String cfName = cfInfo.cf.getName();601if (!cfName.replaceAll("[/$]", ".").equals(className.replaceAll("[/$]", "."))) {602reportWarning("warn.unexpected.class", className, cfName.replace('/', '.'));603}604}605write(cfInfo);606607if (options.showInnerClasses) {608ClassFile cf = cfInfo.cf;609Attribute a = cf.getAttribute(Attribute.InnerClasses);610if (a instanceof InnerClasses_attribute) {611InnerClasses_attribute inners = (InnerClasses_attribute) a;612try {613int result = EXIT_OK;614for (int i = 0; i < inners.classes.length; i++) {615int outerIndex = inners.classes[i].outer_class_info_index;616ConstantPool.CONSTANT_Class_info outerClassInfo = cf.constant_pool.getClassInfo(outerIndex);617String outerClassName = outerClassInfo.getName();618if (outerClassName.equals(cf.getName())) {619int innerIndex = inners.classes[i].inner_class_info_index;620ConstantPool.CONSTANT_Class_info innerClassInfo = cf.constant_pool.getClassInfo(innerIndex);621String innerClassName = innerClassInfo.getName();622classWriter.println("// inner class " + innerClassName.replaceAll("[/$]", "."));623classWriter.println();624result = writeClass(classWriter, innerClassName);625if (result != EXIT_OK) return result;626}627}628return result;629} catch (ConstantPoolException e) {630reportError("err.bad.innerclasses.attribute", className);631return EXIT_ERROR;632}633} else if (a != null) {634reportError("err.bad.innerclasses.attribute", className);635return EXIT_ERROR;636}637}638639return EXIT_OK;640}641642protected JavaFileObject open(String className) throws IOException {643// for compatibility, first see if it is a class name644JavaFileObject fo = getClassFileObject(className);645if (fo != null)646return fo;647648// see if it is an inner class, by replacing dots to $, starting from the right649String cn = className;650int lastDot;651while ((lastDot = cn.lastIndexOf(".")) != -1) {652cn = cn.substring(0, lastDot) + "$" + cn.substring(lastDot + 1);653fo = getClassFileObject(cn);654if (fo != null)655return fo;656}657658if (!className.endsWith(".class"))659return null;660661if (fileManager instanceof StandardJavaFileManager) {662StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;663fo = sfm.getJavaFileObjects(className).iterator().next();664if (fo != null && fo.getLastModified() != 0) {665return fo;666}667}668669// see if it is a URL, and if so, wrap it in just enough of a JavaFileObject670// to suit javap's needs671if (className.matches("^[A-Za-z]+:.*")) {672try {673final URI uri = new URI(className);674final URL url = uri.toURL();675final URLConnection conn = url.openConnection();676return new JavaFileObject() {677public Kind getKind() {678return JavaFileObject.Kind.CLASS;679}680681public boolean isNameCompatible(String simpleName, Kind kind) {682throw new UnsupportedOperationException();683}684685public NestingKind getNestingKind() {686throw new UnsupportedOperationException();687}688689public Modifier getAccessLevel() {690throw new UnsupportedOperationException();691}692693public URI toUri() {694return uri;695}696697public String getName() {698return url.toString();699}700701public InputStream openInputStream() throws IOException {702return conn.getInputStream();703}704705public OutputStream openOutputStream() throws IOException {706throw new UnsupportedOperationException();707}708709public Reader openReader(boolean ignoreEncodingErrors) throws IOException {710throw new UnsupportedOperationException();711}712713public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {714throw new UnsupportedOperationException();715}716717public Writer openWriter() throws IOException {718throw new UnsupportedOperationException();719}720721public long getLastModified() {722return conn.getLastModified();723}724725public boolean delete() {726throw new UnsupportedOperationException();727}728729};730} catch (URISyntaxException ignore) {731} catch (IOException ignore) {732}733}734735return null;736}737738public static class ClassFileInfo {739ClassFileInfo(JavaFileObject fo, ClassFile cf, byte[] digest, int size) {740this.fo = fo;741this.cf = cf;742this.digest = digest;743this.size = size;744}745public final JavaFileObject fo;746public final ClassFile cf;747public final byte[] digest;748public final int size;749}750751public ClassFileInfo read(JavaFileObject fo) throws IOException, ConstantPoolException {752InputStream in = fo.openInputStream();753try {754SizeInputStream sizeIn = null;755MessageDigest md = null;756if (options.sysInfo || options.verbose) {757try {758md = MessageDigest.getInstance("MD5");759} catch (NoSuchAlgorithmException ignore) {760}761in = new DigestInputStream(in, md);762in = sizeIn = new SizeInputStream(in);763}764765ClassFile cf = ClassFile.read(in, attributeFactory);766byte[] digest = (md == null) ? null : md.digest();767int size = (sizeIn == null) ? -1 : sizeIn.size();768return new ClassFileInfo(fo, cf, digest, size);769} finally {770in.close();771}772}773774public void write(ClassFileInfo info) {775ClassWriter classWriter = ClassWriter.instance(context);776if (options.sysInfo || options.verbose) {777classWriter.setFile(info.fo.toUri());778classWriter.setLastModified(info.fo.getLastModified());779classWriter.setDigest("MD5", info.digest);780classWriter.setFileSize(info.size);781}782783classWriter.write(info.cf);784}785786protected void setClassFile(ClassFile classFile) {787ClassWriter classWriter = ClassWriter.instance(context);788classWriter.setClassFile(classFile);789}790791protected void setMethod(Method enclosingMethod) {792ClassWriter classWriter = ClassWriter.instance(context);793classWriter.setMethod(enclosingMethod);794}795796protected void write(Attribute value) {797AttributeWriter attrWriter = AttributeWriter.instance(context);798ClassWriter classWriter = ClassWriter.instance(context);799ClassFile cf = classWriter.getClassFile();800attrWriter.write(cf, value, cf.constant_pool);801}802803protected void write(Attributes attrs) {804AttributeWriter attrWriter = AttributeWriter.instance(context);805ClassWriter classWriter = ClassWriter.instance(context);806ClassFile cf = classWriter.getClassFile();807attrWriter.write(cf, attrs, cf.constant_pool);808}809810protected void write(ConstantPool constant_pool) {811ConstantWriter constantWriter = ConstantWriter.instance(context);812constantWriter.writeConstantPool(constant_pool);813}814815protected void write(ConstantPool constant_pool, int value) {816ConstantWriter constantWriter = ConstantWriter.instance(context);817constantWriter.write(value);818}819820protected void write(ConstantPool.CPInfo value) {821ConstantWriter constantWriter = ConstantWriter.instance(context);822constantWriter.println(value);823}824825protected void write(Field value) {826ClassWriter classWriter = ClassWriter.instance(context);827classWriter.writeField(value);828}829830protected void write(Method value) {831ClassWriter classWriter = ClassWriter.instance(context);832classWriter.writeMethod(value);833}834835private JavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {836if (defaultFileManager == null)837defaultFileManager = JavapFileManager.create(dl, log);838return defaultFileManager;839}840841private JavaFileObject getClassFileObject(String className) throws IOException {842JavaFileObject fo;843fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);844if (fo == null)845fo = fileManager.getJavaFileForInput(StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);846return fo;847}848849private void showHelp() {850printLines(getMessage("main.usage", progname));851for (Option o: recognizedOptions) {852String name = o.aliases[0].substring(1); // there must always be at least one name853if (name.startsWith("X") || name.equals("fullversion") || name.equals("h") || name.equals("verify"))854continue;855printLines(getMessage("main.opt." + name));856}857String[] fmOptions = { "-classpath", "-cp", "-bootclasspath" };858for (String o: fmOptions) {859if (fileManager.isSupportedOption(o) == -1)860continue;861String name = o.substring(1);862printLines(getMessage("main.opt." + name));863}864865}866867private void showVersion(boolean full) {868printLines(version(full ? "full" : "release"));869}870871private void printLines(String msg) {872log.println(msg.replace("\n", nl));873}874875private static final String nl = System.getProperty("line.separator");876877private static final String versionRBName = "com.sun.tools.javap.resources.version";878private static ResourceBundle versionRB;879880private String version(String key) {881// key=version: mm.nn.oo[-milestone]882// key=full: mm.mm.oo[-milestone]-build883if (versionRB == null) {884try {885versionRB = ResourceBundle.getBundle(versionRBName);886} catch (MissingResourceException e) {887return getMessage("version.resource.missing", System.getProperty("java.version"));888}889}890try {891return versionRB.getString(key);892}893catch (MissingResourceException e) {894return getMessage("version.unknown", System.getProperty("java.version"));895}896}897898private void reportError(String key, Object... args) {899diagnosticListener.report(createDiagnostic(Diagnostic.Kind.ERROR, key, args));900}901902private void reportNote(String key, Object... args) {903diagnosticListener.report(createDiagnostic(Diagnostic.Kind.NOTE, key, args));904}905906private void reportWarning(String key, Object... args) {907diagnosticListener.report(createDiagnostic(Diagnostic.Kind.WARNING, key, args));908}909910private Diagnostic<JavaFileObject> createDiagnostic(911final Diagnostic.Kind kind, final String key, final Object... args) {912return new Diagnostic<JavaFileObject>() {913public Kind getKind() {914return kind;915}916917public JavaFileObject getSource() {918return null;919}920921public long getPosition() {922return Diagnostic.NOPOS;923}924925public long getStartPosition() {926return Diagnostic.NOPOS;927}928929public long getEndPosition() {930return Diagnostic.NOPOS;931}932933public long getLineNumber() {934return Diagnostic.NOPOS;935}936937public long getColumnNumber() {938return Diagnostic.NOPOS;939}940941public String getCode() {942return key;943}944945public String getMessage(Locale locale) {946return JavapTask.this.getMessage(locale, key, args);947}948949@Override950public String toString() {951return getClass().getName() + "[key=" + key + ",args=" + Arrays.asList(args) + "]";952}953954};955956}957958public String getMessage(String key, Object... args) {959return getMessage(task_locale, key, args);960}961962public String getMessage(Locale locale, String key, Object... args) {963if (bundles == null) {964// could make this a HashMap<Locale,SoftReference<ResourceBundle>>965// and for efficiency, keep a hard reference to the bundle for the task966// locale967bundles = new HashMap<Locale, ResourceBundle>();968}969970if (locale == null)971locale = Locale.getDefault();972973ResourceBundle b = bundles.get(locale);974if (b == null) {975try {976b = ResourceBundle.getBundle("com.sun.tools.javap.resources.javap", locale);977bundles.put(locale, b);978} catch (MissingResourceException e) {979throw new InternalError("Cannot find javap resource bundle for locale " + locale);980}981}982983try {984return MessageFormat.format(b.getString(key), args);985} catch (MissingResourceException e) {986throw new InternalError(e, key);987}988}989990protected Context context;991JavaFileManager fileManager;992JavaFileManager defaultFileManager;993PrintWriter log;994DiagnosticListener<? super JavaFileObject> diagnosticListener;995List<String> classes;996Options options;997//ResourceBundle bundle;998Locale task_locale;999Map<Locale, ResourceBundle> bundles;1000protected Attribute.Factory attributeFactory;10011002private static final String progname = "javap";10031004private static class SizeInputStream extends FilterInputStream {1005SizeInputStream(InputStream in) {1006super(in);1007}10081009int size() {1010return size;1011}10121013@Override1014public int read(byte[] buf, int offset, int length) throws IOException {1015int n = super.read(buf, offset, length);1016if (n > 0)1017size += n;1018return n;1019}10201021@Override1022public int read() throws IOException {1023int b = super.read();1024size += 1;1025return b;1026}10271028private int size;1029}1030}103110321033