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

Tue, 18 Jun 2013 20:56:04 -0700

author
mfang
date
Tue, 18 Jun 2013 20:56:04 -0700
changeset 1841
792c40d5185a
parent 1819
7fe655cad9b1
child 1885
d6158f8d7235
permissions
-rw-r--r--

8015657: jdk8 l10n resource file translation update 3
Reviewed-by: yhuang

     1 /*
     2  * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.tools.javap;
    28 import java.io.EOFException;
    29 import java.io.FileNotFoundException;
    30 import java.io.FilterInputStream;
    31 import java.io.InputStream;
    32 import java.io.IOException;
    33 import java.io.OutputStream;
    34 import java.io.PrintWriter;
    35 import java.io.Reader;
    36 import java.io.StringWriter;
    37 import java.io.Writer;
    38 import java.net.URI;
    39 import java.security.DigestInputStream;
    40 import java.security.MessageDigest;
    41 import java.security.NoSuchAlgorithmException;
    42 import java.text.MessageFormat;
    43 import java.util.ArrayList;
    44 import java.util.Arrays;
    45 import java.util.EnumSet;
    46 import java.util.HashMap;
    47 import java.util.Iterator;
    48 import java.util.List;
    49 import java.util.Locale;
    50 import java.util.Map;
    51 import java.util.MissingResourceException;
    52 import java.util.ResourceBundle;
    54 import javax.lang.model.element.Modifier;
    55 import javax.lang.model.element.NestingKind;
    56 import javax.tools.Diagnostic;
    57 import javax.tools.DiagnosticListener;
    58 import javax.tools.JavaFileManager;
    59 import javax.tools.JavaFileObject;
    60 import javax.tools.StandardJavaFileManager;
    61 import javax.tools.StandardLocation;
    63 import com.sun.tools.classfile.*;
    64 import java.net.URISyntaxException;
    65 import java.net.URL;
    66 import java.net.URLConnection;
    68 /**
    69  *  "Main" class for javap, normally accessed from the command line
    70  *  via Main, or from JSR199 via DisassemblerTool.
    71  *
    72  *  <p><b>This is NOT part of any supported API.
    73  *  If you write code that depends on this, you do so at your own risk.
    74  *  This code and its internal interfaces are subject to change or
    75  *  deletion without notice.</b>
    76  */
    77 public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
    78     public class BadArgs extends Exception {
    79         static final long serialVersionUID = 8765093759964640721L;
    80         BadArgs(String key, Object... args) {
    81             super(JavapTask.this.getMessage(key, args));
    82             this.key = key;
    83             this.args = args;
    84         }
    86         BadArgs showUsage(boolean b) {
    87             showUsage = b;
    88             return this;
    89         }
    91         final String key;
    92         final Object[] args;
    93         boolean showUsage;
    94     }
    96     static abstract class Option {
    97         Option(boolean hasArg, String... aliases) {
    98             this.hasArg = hasArg;
    99             this.aliases = aliases;
   100         }
   102         boolean matches(String opt) {
   103             for (String a: aliases) {
   104                 if (a.equals(opt))
   105                     return true;
   106             }
   107             return false;
   108         }
   110         boolean ignoreRest() {
   111             return false;
   112         }
   114         abstract void process(JavapTask task, String opt, String arg) throws BadArgs;
   116         final boolean hasArg;
   117         final String[] aliases;
   118     }
   120     static final Option[] recognizedOptions = {
   122         new Option(false, "-help", "--help", "-?") {
   123             void process(JavapTask task, String opt, String arg) {
   124                 task.options.help = true;
   125             }
   126         },
   128         new Option(false, "-version") {
   129             void process(JavapTask task, String opt, String arg) {
   130                 task.options.version = true;
   131             }
   132         },
   134         new Option(false, "-fullversion") {
   135             void process(JavapTask task, String opt, String arg) {
   136                 task.options.fullVersion = true;
   137             }
   138         },
   140         new Option(false, "-v", "-verbose", "-all") {
   141             void process(JavapTask task, String opt, String arg) {
   142                 task.options.verbose = true;
   143                 task.options.showDescriptors = true;
   144                 task.options.showFlags = true;
   145                 task.options.showAllAttrs = true;
   146             }
   147         },
   149         new Option(false, "-l") {
   150             void process(JavapTask task, String opt, String arg) {
   151                 task.options.showLineAndLocalVariableTables = true;
   152             }
   153         },
   155         new Option(false, "-public") {
   156             void process(JavapTask task, String opt, String arg) {
   157                 task.options.accessOptions.add(opt);
   158                 task.options.showAccess = AccessFlags.ACC_PUBLIC;
   159             }
   160         },
   162         new Option(false, "-protected") {
   163             void process(JavapTask task, String opt, String arg) {
   164                 task.options.accessOptions.add(opt);
   165                 task.options.showAccess = AccessFlags.ACC_PROTECTED;
   166             }
   167         },
   169         new Option(false, "-package") {
   170             void process(JavapTask task, String opt, String arg) {
   171                 task.options.accessOptions.add(opt);
   172                 task.options.showAccess = 0;
   173             }
   174         },
   176         new Option(false, "-p", "-private") {
   177             void process(JavapTask task, String opt, String arg) {
   178                 if (!task.options.accessOptions.contains("-p") &&
   179                         !task.options.accessOptions.contains("-private")) {
   180                     task.options.accessOptions.add(opt);
   181                 }
   182                 task.options.showAccess = AccessFlags.ACC_PRIVATE;
   183             }
   184         },
   186         new Option(false, "-c") {
   187             void process(JavapTask task, String opt, String arg) {
   188                 task.options.showDisassembled = true;
   189             }
   190         },
   192         new Option(false, "-s") {
   193             void process(JavapTask task, String opt, String arg) {
   194                 task.options.showDescriptors = true;
   195             }
   196         },
   198 //        new Option(false, "-all") {
   199 //            void process(JavapTask task, String opt, String arg) {
   200 //                task.options.showAllAttrs = true;
   201 //            }
   202 //        },
   204         new Option(false, "-h") {
   205             void process(JavapTask task, String opt, String arg) throws BadArgs {
   206                 throw task.new BadArgs("err.h.not.supported");
   207             }
   208         },
   210         new Option(false, "-verify", "-verify-verbose") {
   211             void process(JavapTask task, String opt, String arg) throws BadArgs {
   212                 throw task.new BadArgs("err.verify.not.supported");
   213             }
   214         },
   216         new Option(false, "-sysinfo") {
   217             void process(JavapTask task, String opt, String arg) {
   218                 task.options.sysInfo = true;
   219             }
   220         },
   222         new Option(false, "-Xold") {
   223             void process(JavapTask task, String opt, String arg) throws BadArgs {
   224                 task.log.println(task.getMessage("warn.Xold.not.supported"));
   225             }
   226         },
   228         new Option(false, "-Xnew") {
   229             void process(JavapTask task, String opt, String arg) throws BadArgs {
   230                 // ignore: this _is_ the new version
   231             }
   232         },
   234         new Option(false, "-XDcompat") {
   235             void process(JavapTask task, String opt, String arg) {
   236                 task.options.compat = true;
   237             }
   238         },
   240         new Option(false, "-XDdetails") {
   241             void process(JavapTask task, String opt, String arg) {
   242                 task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);
   243             }
   245         },
   247         new Option(false, "-XDdetails:") {
   248             @Override
   249             boolean matches(String opt) {
   250                 int sep = opt.indexOf(":");
   251                 return sep != -1 && super.matches(opt.substring(0, sep + 1));
   252             }
   254             void process(JavapTask task, String opt, String arg) throws BadArgs {
   255                 int sep = opt.indexOf(":");
   256                 for (String v: opt.substring(sep + 1).split("[,: ]+")) {
   257                     if (!handleArg(task, v))
   258                         throw task.new BadArgs("err.invalid.arg.for.option", v);
   259                 }
   260             }
   262             boolean handleArg(JavapTask task, String arg) {
   263                 if (arg.length() == 0)
   264                     return true;
   266                 if (arg.equals("all")) {
   267                     task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);
   268                     return true;
   269                 }
   271                 boolean on = true;
   272                 if (arg.startsWith("-")) {
   273                     on = false;
   274                     arg = arg.substring(1);
   275                 }
   277                 for (InstructionDetailWriter.Kind k: InstructionDetailWriter.Kind.values()) {
   278                     if (arg.equalsIgnoreCase(k.option)) {
   279                         if (on)
   280                             task.options.details.add(k);
   281                         else
   282                             task.options.details.remove(k);
   283                         return true;
   284                     }
   285                 }
   286                 return false;
   287             }
   288         },
   290         new Option(false, "-constants") {
   291             void process(JavapTask task, String opt, String arg) {
   292                 task.options.showConstants = true;
   293             }
   294         },
   296         new Option(false, "-XDinner") {
   297             void process(JavapTask task, String opt, String arg) {
   298                 task.options.showInnerClasses = true;
   299             }
   300         },
   302         new Option(false, "-XDindent:") {
   303             @Override
   304             boolean matches(String opt) {
   305                 int sep = opt.indexOf(":");
   306                 return sep != -1 && super.matches(opt.substring(0, sep + 1));
   307             }
   309             void process(JavapTask task, String opt, String arg) throws BadArgs {
   310                 int sep = opt.indexOf(":");
   311                 try {
   312                     task.options.indentWidth = Integer.valueOf(opt.substring(sep + 1));
   313                 } catch (NumberFormatException e) {
   314                 }
   315             }
   316         },
   318         new Option(false, "-XDtab:") {
   319             @Override
   320             boolean matches(String opt) {
   321                 int sep = opt.indexOf(":");
   322                 return sep != -1 && super.matches(opt.substring(0, sep + 1));
   323             }
   325             void process(JavapTask task, String opt, String arg) throws BadArgs {
   326                 int sep = opt.indexOf(":");
   327                 try {
   328                     task.options.tabColumn = Integer.valueOf(opt.substring(sep + 1));
   329                 } catch (NumberFormatException e) {
   330                 }
   331             }
   332         }
   334     };
   336     public JavapTask() {
   337         context = new Context();
   338         context.put(Messages.class, this);
   339         options = Options.instance(context);
   340         attributeFactory = new Attribute.Factory();
   341     }
   343     public JavapTask(Writer out,
   344             JavaFileManager fileManager,
   345             DiagnosticListener<? super JavaFileObject> diagnosticListener) {
   346         this();
   347         this.log = getPrintWriterForWriter(out);
   348         this.fileManager = fileManager;
   349         this.diagnosticListener = diagnosticListener;
   350     }
   352     public JavapTask(Writer out,
   353             JavaFileManager fileManager,
   354             DiagnosticListener<? super JavaFileObject> diagnosticListener,
   355             Iterable<String> options,
   356             Iterable<String> classes) {
   357         this(out, fileManager, diagnosticListener);
   359         this.classes = new ArrayList<String>();
   360         for (String classname: classes) {
   361             classname.getClass(); // null-check
   362             this.classes.add(classname);
   363         }
   365         try {
   366             if (options != null)
   367                 handleOptions(options, false);
   368         } catch (BadArgs e) {
   369             throw new IllegalArgumentException(e.getMessage());
   370         }
   371     }
   373     public void setLocale(Locale locale) {
   374         if (locale == null)
   375             locale = Locale.getDefault();
   376         task_locale = locale;
   377     }
   379     public void setLog(Writer log) {
   380         this.log = getPrintWriterForWriter(log);
   381     }
   383     public void setLog(OutputStream s) {
   384         setLog(getPrintWriterForStream(s));
   385     }
   387     private static PrintWriter getPrintWriterForStream(OutputStream s) {
   388         return new PrintWriter(s == null ? System.err : s, true);
   389     }
   391     private static PrintWriter getPrintWriterForWriter(Writer w) {
   392         if (w == null)
   393             return getPrintWriterForStream(null);
   394         else if (w instanceof PrintWriter)
   395             return (PrintWriter) w;
   396         else
   397             return new PrintWriter(w, true);
   398     }
   400     public void setDiagnosticListener(DiagnosticListener<? super JavaFileObject> dl) {
   401         diagnosticListener = dl;
   402     }
   404     public void setDiagnosticListener(OutputStream s) {
   405         setDiagnosticListener(getDiagnosticListenerForStream(s));
   406     }
   408     private DiagnosticListener<JavaFileObject> getDiagnosticListenerForStream(OutputStream s) {
   409         return getDiagnosticListenerForWriter(getPrintWriterForStream(s));
   410     }
   412     private DiagnosticListener<JavaFileObject> getDiagnosticListenerForWriter(Writer w) {
   413         final PrintWriter pw = getPrintWriterForWriter(w);
   414         return new DiagnosticListener<JavaFileObject> () {
   415             public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   416                 switch (diagnostic.getKind()) {
   417                     case ERROR:
   418                         pw.print(getMessage("err.prefix"));
   419                         break;
   420                     case WARNING:
   421                         pw.print(getMessage("warn.prefix"));
   422                         break;
   423                     case NOTE:
   424                         pw.print(getMessage("note.prefix"));
   425                         break;
   426                 }
   427                 pw.print(" ");
   428                 pw.println(diagnostic.getMessage(null));
   429             }
   430         };
   431     }
   433     /** Result codes.
   434      */
   435     static final int
   436         EXIT_OK = 0,        // Compilation completed with no errors.
   437         EXIT_ERROR = 1,     // Completed but reported errors.
   438         EXIT_CMDERR = 2,    // Bad command-line arguments
   439         EXIT_SYSERR = 3,    // System error or resource exhaustion.
   440         EXIT_ABNORMAL = 4;  // Compiler terminated abnormally
   442     int run(String[] args) {
   443         try {
   444             handleOptions(args);
   446             // the following gives consistent behavior with javac
   447             if (classes == null || classes.size() == 0) {
   448                 if (options.help || options.version || options.fullVersion)
   449                     return EXIT_OK;
   450                 else
   451                     return EXIT_CMDERR;
   452             }
   454             try {
   455                 return run();
   456             } finally {
   457                 if (defaultFileManager != null) {
   458                     try {
   459                         defaultFileManager.close();
   460                         defaultFileManager = null;
   461                     } catch (IOException e) {
   462                         throw new InternalError(e);
   463                     }
   464                 }
   465             }
   466         } catch (BadArgs e) {
   467             reportError(e.key, e.args);
   468             if (e.showUsage) {
   469                 log.println(getMessage("main.usage.summary", progname));
   470             }
   471             return EXIT_CMDERR;
   472         } catch (InternalError e) {
   473             Object[] e_args;
   474             if (e.getCause() == null)
   475                 e_args = e.args;
   476             else {
   477                 e_args = new Object[e.args.length + 1];
   478                 e_args[0] = e.getCause();
   479                 System.arraycopy(e.args, 0, e_args, 1, e.args.length);
   480             }
   481             reportError("err.internal.error", e_args);
   482             return EXIT_ABNORMAL;
   483         } finally {
   484             log.flush();
   485         }
   486     }
   488     public void handleOptions(String[] args) throws BadArgs {
   489         handleOptions(Arrays.asList(args), true);
   490     }
   492     private void handleOptions(Iterable<String> args, boolean allowClasses) throws BadArgs {
   493         if (log == null) {
   494             log = getPrintWriterForStream(System.out);
   495             if (diagnosticListener == null)
   496               diagnosticListener = getDiagnosticListenerForStream(System.err);
   497         } else {
   498             if (diagnosticListener == null)
   499               diagnosticListener = getDiagnosticListenerForWriter(log);
   500         }
   503         if (fileManager == null)
   504             fileManager = getDefaultFileManager(diagnosticListener, log);
   506         Iterator<String> iter = args.iterator();
   507         boolean noArgs = !iter.hasNext();
   509         while (iter.hasNext()) {
   510             String arg = iter.next();
   511             if (arg.startsWith("-"))
   512                 handleOption(arg, iter);
   513             else if (allowClasses) {
   514                 if (classes == null)
   515                     classes = new ArrayList<String>();
   516                 classes.add(arg);
   517                 while (iter.hasNext())
   518                     classes.add(iter.next());
   519             } else
   520                 throw new BadArgs("err.unknown.option", arg).showUsage(true);
   521         }
   523         if (!options.compat && options.accessOptions.size() > 1) {
   524             StringBuilder sb = new StringBuilder();
   525             for (String opt: options.accessOptions) {
   526                 if (sb.length() > 0)
   527                     sb.append(" ");
   528                 sb.append(opt);
   529             }
   530             throw new BadArgs("err.incompatible.options", sb);
   531         }
   533         if ((classes == null || classes.size() == 0) &&
   534                 !(noArgs || options.help || options.version || options.fullVersion)) {
   535             throw new BadArgs("err.no.classes.specified");
   536         }
   538         if (noArgs || options.help)
   539             showHelp();
   541         if (options.version || options.fullVersion)
   542             showVersion(options.fullVersion);
   543     }
   545     private void handleOption(String name, Iterator<String> rest) throws BadArgs {
   546         for (Option o: recognizedOptions) {
   547             if (o.matches(name)) {
   548                 if (o.hasArg) {
   549                     if (rest.hasNext())
   550                         o.process(this, name, rest.next());
   551                     else
   552                         throw new BadArgs("err.missing.arg", name).showUsage(true);
   553                 } else
   554                     o.process(this, name, null);
   556                 if (o.ignoreRest()) {
   557                     while (rest.hasNext())
   558                         rest.next();
   559                 }
   560                 return;
   561             }
   562         }
   564         if (fileManager.handleOption(name, rest))
   565             return;
   567         throw new BadArgs("err.unknown.option", name).showUsage(true);
   568     }
   570     public Boolean call() {
   571         return run() == 0;
   572     }
   574     public int run() {
   575         if (classes == null || classes.isEmpty()) {
   576             return EXIT_ERROR;
   577         }
   579         context.put(PrintWriter.class, log);
   580         ClassWriter classWriter = ClassWriter.instance(context);
   581         SourceWriter sourceWriter = SourceWriter.instance(context);
   582         sourceWriter.setFileManager(fileManager);
   584         attributeFactory.setCompat(options.compat);
   586         int result = EXIT_OK;
   588         for (String className: classes) {
   589             try {
   590                 result = writeClass(classWriter, className);
   591             } catch (ConstantPoolException e) {
   592                 reportError("err.bad.constant.pool", className, e.getLocalizedMessage());
   593                 result = EXIT_ERROR;
   594             } catch (EOFException e) {
   595                 reportError("err.end.of.file", className);
   596                 result = EXIT_ERROR;
   597             } catch (FileNotFoundException e) {
   598                 reportError("err.file.not.found", e.getLocalizedMessage());
   599                 result = EXIT_ERROR;
   600             } catch (IOException e) {
   601                 //e.printStackTrace();
   602                 Object msg = e.getLocalizedMessage();
   603                 if (msg == null) {
   604                     msg = e;
   605                 }
   606                 reportError("err.ioerror", className, msg);
   607                 result = EXIT_ERROR;
   608             } catch (Throwable t) {
   609                 StringWriter sw = new StringWriter();
   610                 PrintWriter pw = new PrintWriter(sw);
   611                 t.printStackTrace(pw);
   612                 pw.close();
   613                 reportError("err.crash", t.toString(), sw.toString());
   614                 result = EXIT_ABNORMAL;
   615             }
   616         }
   618         return result;
   619     }
   621     protected int writeClass(ClassWriter classWriter, String className)
   622             throws IOException, ConstantPoolException {
   623         JavaFileObject fo = open(className);
   624         if (fo == null) {
   625             reportError("err.class.not.found", className);
   626             return EXIT_ERROR;
   627         }
   629         ClassFileInfo cfInfo = read(fo);
   630         if (!className.endsWith(".class")) {
   631             String cfName = cfInfo.cf.getName();
   632             if (!cfName.replaceAll("[/$]", ".").equals(className.replaceAll("[/$]", "."))) {
   633                 reportWarning("warn.unexpected.class", className, cfName.replace('/', '.'));
   634             }
   635         }
   636         write(cfInfo);
   638         if (options.showInnerClasses) {
   639             ClassFile cf = cfInfo.cf;
   640             Attribute a = cf.getAttribute(Attribute.InnerClasses);
   641             if (a instanceof InnerClasses_attribute) {
   642                 InnerClasses_attribute inners = (InnerClasses_attribute) a;
   643                 try {
   644                     int result = EXIT_OK;
   645                     for (int i = 0; i < inners.classes.length; i++) {
   646                         int outerIndex = inners.classes[i].outer_class_info_index;
   647                         ConstantPool.CONSTANT_Class_info outerClassInfo = cf.constant_pool.getClassInfo(outerIndex);
   648                         String outerClassName = outerClassInfo.getName();
   649                         if (outerClassName.equals(cf.getName())) {
   650                             int innerIndex = inners.classes[i].inner_class_info_index;
   651                             ConstantPool.CONSTANT_Class_info innerClassInfo = cf.constant_pool.getClassInfo(innerIndex);
   652                             String innerClassName = innerClassInfo.getName();
   653                             classWriter.println("// inner class " + innerClassName.replaceAll("[/$]", "."));
   654                             classWriter.println();
   655                             result = writeClass(classWriter, innerClassName);
   656                             if (result != EXIT_OK) return result;
   657                         }
   658                     }
   659                     return result;
   660                 } catch (ConstantPoolException e) {
   661                     reportError("err.bad.innerclasses.attribute", className);
   662                     return EXIT_ERROR;
   663                 }
   664             } else if (a != null) {
   665                 reportError("err.bad.innerclasses.attribute", className);
   666                 return EXIT_ERROR;
   667             }
   668         }
   670         return EXIT_OK;
   671     }
   673     protected JavaFileObject open(String className) throws IOException {
   674         // for compatibility, first see if it is a class name
   675         JavaFileObject fo = getClassFileObject(className);
   676         if (fo != null)
   677             return fo;
   679         // see if it is an inner class, by replacing dots to $, starting from the right
   680         String cn = className;
   681         int lastDot;
   682         while ((lastDot = cn.lastIndexOf(".")) != -1) {
   683             cn = cn.substring(0, lastDot) + "$" + cn.substring(lastDot + 1);
   684             fo = getClassFileObject(cn);
   685             if (fo != null)
   686                 return fo;
   687         }
   689         if (!className.endsWith(".class"))
   690             return null;
   692         if (fileManager instanceof StandardJavaFileManager) {
   693             StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
   694             fo = sfm.getJavaFileObjects(className).iterator().next();
   695             if (fo != null && fo.getLastModified() != 0) {
   696                 return fo;
   697             }
   698         }
   700         // see if it is a URL, and if so, wrap it in just enough of a JavaFileObject
   701         // to suit javap's needs
   702         if (className.matches("^[A-Za-z]+:.*")) {
   703             try {
   704                 final URI uri = new URI(className);
   705                 final URL url = uri.toURL();
   706                 final URLConnection conn = url.openConnection();
   707                 return new JavaFileObject() {
   708                     public Kind getKind() {
   709                         return JavaFileObject.Kind.CLASS;
   710                     }
   712                     public boolean isNameCompatible(String simpleName, Kind kind) {
   713                         throw new UnsupportedOperationException();
   714                     }
   716                     public NestingKind getNestingKind() {
   717                         throw new UnsupportedOperationException();
   718                     }
   720                     public Modifier getAccessLevel() {
   721                         throw new UnsupportedOperationException();
   722                     }
   724                     public URI toUri() {
   725                         return uri;
   726                     }
   728                     public String getName() {
   729                         return url.toString();
   730                     }
   732                     public InputStream openInputStream() throws IOException {
   733                         return conn.getInputStream();
   734                     }
   736                     public OutputStream openOutputStream() throws IOException {
   737                         throw new UnsupportedOperationException();
   738                     }
   740                     public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
   741                         throw new UnsupportedOperationException();
   742                     }
   744                     public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   745                         throw new UnsupportedOperationException();
   746                     }
   748                     public Writer openWriter() throws IOException {
   749                         throw new UnsupportedOperationException();
   750                     }
   752                     public long getLastModified() {
   753                         return conn.getLastModified();
   754                     }
   756                     public boolean delete() {
   757                         throw new UnsupportedOperationException();
   758                     }
   760                 };
   761             } catch (URISyntaxException ignore) {
   762             } catch (IOException ignore) {
   763             }
   764         }
   766         return null;
   767     }
   769     public static class ClassFileInfo {
   770         ClassFileInfo(JavaFileObject fo, ClassFile cf, byte[] digest, int size) {
   771             this.fo = fo;
   772             this.cf = cf;
   773             this.digest = digest;
   774             this.size = size;
   775         }
   776         public final JavaFileObject fo;
   777         public final ClassFile cf;
   778         public final byte[] digest;
   779         public final int size;
   780     }
   782     public ClassFileInfo read(JavaFileObject fo) throws IOException, ConstantPoolException {
   783         InputStream in = fo.openInputStream();
   784         try {
   785             SizeInputStream sizeIn = null;
   786             MessageDigest md  = null;
   787             if (options.sysInfo || options.verbose) {
   788                 try {
   789                     md = MessageDigest.getInstance("MD5");
   790                 } catch (NoSuchAlgorithmException ignore) {
   791                 }
   792                 in = new DigestInputStream(in, md);
   793                 in = sizeIn = new SizeInputStream(in);
   794             }
   796             ClassFile cf = ClassFile.read(in, attributeFactory);
   797             byte[] digest = (md == null) ? null : md.digest();
   798             int size = (sizeIn == null) ? -1 : sizeIn.size();
   799             return new ClassFileInfo(fo, cf, digest, size);
   800         } finally {
   801             in.close();
   802         }
   803     }
   805     public void write(ClassFileInfo info) {
   806         ClassWriter classWriter = ClassWriter.instance(context);
   807         if (options.sysInfo || options.verbose) {
   808             classWriter.setFile(info.fo.toUri());
   809             classWriter.setLastModified(info.fo.getLastModified());
   810             classWriter.setDigest("MD5", info.digest);
   811             classWriter.setFileSize(info.size);
   812         }
   814         classWriter.write(info.cf);
   815     }
   817     protected void setClassFile(ClassFile classFile) {
   818         ClassWriter classWriter = ClassWriter.instance(context);
   819         classWriter.setClassFile(classFile);
   820     }
   822     protected void setMethod(Method enclosingMethod) {
   823         ClassWriter classWriter = ClassWriter.instance(context);
   824         classWriter.setMethod(enclosingMethod);
   825     }
   827     protected void write(Attribute value) {
   828         AttributeWriter attrWriter = AttributeWriter.instance(context);
   829         ClassWriter classWriter = ClassWriter.instance(context);
   830         ClassFile cf = classWriter.getClassFile();
   831         attrWriter.write(cf, value, cf.constant_pool);
   832     }
   834     protected void write(Attributes attrs) {
   835         AttributeWriter attrWriter = AttributeWriter.instance(context);
   836         ClassWriter classWriter = ClassWriter.instance(context);
   837         ClassFile cf = classWriter.getClassFile();
   838         attrWriter.write(cf, attrs, cf.constant_pool);
   839     }
   841     protected void write(ConstantPool constant_pool) {
   842         ConstantWriter constantWriter = ConstantWriter.instance(context);
   843         constantWriter.writeConstantPool(constant_pool);
   844     }
   846     protected void write(ConstantPool constant_pool, int value) {
   847         ConstantWriter constantWriter = ConstantWriter.instance(context);
   848         constantWriter.write(value);
   849     }
   851     protected void write(ConstantPool.CPInfo value) {
   852         ConstantWriter constantWriter = ConstantWriter.instance(context);
   853         constantWriter.println(value);
   854     }
   856     protected void write(Field value) {
   857         ClassWriter classWriter = ClassWriter.instance(context);
   858         classWriter.writeField(value);
   859     }
   861     protected void write(Method value) {
   862         ClassWriter classWriter = ClassWriter.instance(context);
   863         classWriter.writeMethod(value);
   864     }
   866     private JavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
   867         if (defaultFileManager == null)
   868             defaultFileManager = JavapFileManager.create(dl, log);
   869         return defaultFileManager;
   870     }
   872     private JavaFileObject getClassFileObject(String className) throws IOException {
   873         JavaFileObject fo;
   874         fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
   875         if (fo == null)
   876             fo = fileManager.getJavaFileForInput(StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
   877         return fo;
   878     }
   880     private void showHelp() {
   881         log.println(getMessage("main.usage", progname));
   882         for (Option o: recognizedOptions) {
   883             String name = o.aliases[0].substring(1); // there must always be at least one name
   884             if (name.startsWith("X") || name.equals("fullversion") || name.equals("h") || name.equals("verify"))
   885                 continue;
   886             log.println(getMessage("main.opt." + name));
   887         }
   888         String[] fmOptions = { "-classpath", "-bootclasspath" };
   889         for (String o: fmOptions) {
   890             if (fileManager.isSupportedOption(o) == -1)
   891                 continue;
   892             String name = o.substring(1);
   893             log.println(getMessage("main.opt." + name));
   894         }
   896     }
   898     private void showVersion(boolean full) {
   899         log.println(version(full ? "full" : "release"));
   900     }
   902     private static final String versionRBName = "com.sun.tools.javap.resources.version";
   903     private static ResourceBundle versionRB;
   905     private String version(String key) {
   906         // key=version:  mm.nn.oo[-milestone]
   907         // key=full:     mm.mm.oo[-milestone]-build
   908         if (versionRB == null) {
   909             try {
   910                 versionRB = ResourceBundle.getBundle(versionRBName);
   911             } catch (MissingResourceException e) {
   912                 return getMessage("version.resource.missing", System.getProperty("java.version"));
   913             }
   914         }
   915         try {
   916             return versionRB.getString(key);
   917         }
   918         catch (MissingResourceException e) {
   919             return getMessage("version.unknown", System.getProperty("java.version"));
   920         }
   921     }
   923     private void reportError(String key, Object... args) {
   924         diagnosticListener.report(createDiagnostic(Diagnostic.Kind.ERROR, key, args));
   925     }
   927     private void reportNote(String key, Object... args) {
   928         diagnosticListener.report(createDiagnostic(Diagnostic.Kind.NOTE, key, args));
   929     }
   931     private void reportWarning(String key, Object... args) {
   932         diagnosticListener.report(createDiagnostic(Diagnostic.Kind.WARNING, key, args));
   933     }
   935     private Diagnostic<JavaFileObject> createDiagnostic(
   936             final Diagnostic.Kind kind, final String key, final Object... args) {
   937         return new Diagnostic<JavaFileObject>() {
   938             public Kind getKind() {
   939                 return kind;
   940             }
   942             public JavaFileObject getSource() {
   943                 return null;
   944             }
   946             public long getPosition() {
   947                 return Diagnostic.NOPOS;
   948             }
   950             public long getStartPosition() {
   951                 return Diagnostic.NOPOS;
   952             }
   954             public long getEndPosition() {
   955                 return Diagnostic.NOPOS;
   956             }
   958             public long getLineNumber() {
   959                 return Diagnostic.NOPOS;
   960             }
   962             public long getColumnNumber() {
   963                 return Diagnostic.NOPOS;
   964             }
   966             public String getCode() {
   967                 return key;
   968             }
   970             public String getMessage(Locale locale) {
   971                 return JavapTask.this.getMessage(locale, key, args);
   972             }
   974             @Override
   975             public String toString() {
   976                 return getClass().getName() + "[key=" + key + ",args=" + Arrays.asList(args) + "]";
   977             }
   979         };
   981     }
   983     public String getMessage(String key, Object... args) {
   984         return getMessage(task_locale, key, args);
   985     }
   987     public String getMessage(Locale locale, String key, Object... args) {
   988         if (bundles == null) {
   989             // could make this a HashMap<Locale,SoftReference<ResourceBundle>>
   990             // and for efficiency, keep a hard reference to the bundle for the task
   991             // locale
   992             bundles = new HashMap<Locale, ResourceBundle>();
   993         }
   995         if (locale == null)
   996             locale = Locale.getDefault();
   998         ResourceBundle b = bundles.get(locale);
   999         if (b == null) {
  1000             try {
  1001                 b = ResourceBundle.getBundle("com.sun.tools.javap.resources.javap", locale);
  1002                 bundles.put(locale, b);
  1003             } catch (MissingResourceException e) {
  1004                 throw new InternalError("Cannot find javap resource bundle for locale " + locale);
  1008         try {
  1009             return MessageFormat.format(b.getString(key), args);
  1010         } catch (MissingResourceException e) {
  1011             throw new InternalError(e, key);
  1015     protected Context context;
  1016     JavaFileManager fileManager;
  1017     JavaFileManager defaultFileManager;
  1018     PrintWriter log;
  1019     DiagnosticListener<? super JavaFileObject> diagnosticListener;
  1020     List<String> classes;
  1021     Options options;
  1022     //ResourceBundle bundle;
  1023     Locale task_locale;
  1024     Map<Locale, ResourceBundle> bundles;
  1025     protected Attribute.Factory attributeFactory;
  1027     private static final String progname = "javap";
  1029     private static class SizeInputStream extends FilterInputStream {
  1030         SizeInputStream(InputStream in) {
  1031             super(in);
  1034         int size() {
  1035             return size;
  1038         @Override
  1039         public int read(byte[] buf, int offset, int length) throws IOException {
  1040             int n = super.read(buf, offset, length);
  1041             if (n > 0)
  1042                 size += n;
  1043             return n;
  1046         @Override
  1047         public int read() throws IOException {
  1048             int b = super.read();
  1049             size += 1;
  1050             return b;
  1053         private int size;

mercurial