src/share/classes/com/sun/tools/javac/main/Main.java

Thu, 06 Oct 2011 18:39:31 +0100

author
mcimadamore
date
Thu, 06 Oct 2011 18:39:31 +0100
changeset 1103
47147081d5b4
parent 1097
497571d34112
child 1135
36553cb94345
permissions
-rw-r--r--

7090499: missing rawtypes warnings in anonymous inner class
Summary: javac does not detect raw types inside anonymous inner classes
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 1999, 2011, 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.javac.main;
    28 import java.io.File;
    29 import java.io.IOException;
    30 import java.io.PrintWriter;
    31 import java.net.URL;
    32 import java.security.DigestInputStream;
    33 import java.security.MessageDigest;
    34 import java.util.Collection;
    35 import java.util.LinkedHashSet;
    36 import java.util.MissingResourceException;
    37 import java.util.Set;
    38 import javax.tools.JavaFileManager;
    39 import javax.tools.JavaFileObject;
    40 import javax.annotation.processing.Processor;
    42 import com.sun.tools.javac.code.Source;
    43 import com.sun.tools.javac.file.CacheFSInfo;
    44 import com.sun.tools.javac.file.JavacFileManager;
    45 import com.sun.tools.javac.jvm.Target;
    46 import com.sun.tools.javac.main.JavacOption.Option;
    47 import com.sun.tools.javac.main.RecognizedOptions.OptionHelper;
    48 import com.sun.tools.javac.util.*;
    49 import com.sun.tools.javac.processing.AnnotationProcessingError;
    51 import static com.sun.tools.javac.main.OptionName.*;
    53 /** This class provides a commandline interface to the GJC compiler.
    54  *
    55  *  <p><b>This is NOT part of any supported API.
    56  *  If you write code that depends on this, you do so at your own risk.
    57  *  This code and its internal interfaces are subject to change or
    58  *  deletion without notice.</b>
    59  */
    60 public class Main {
    62     /** The name of the compiler, for use in diagnostics.
    63      */
    64     String ownName;
    66     /** The writer to use for diagnostic output.
    67      */
    68     PrintWriter out;
    70     /**
    71      * If true, certain errors will cause an exception, such as command line
    72      * arg errors, or exceptions in user provided code.
    73      */
    74     boolean apiMode;
    77     /** Result codes.
    78      */
    79     public enum Result {
    80         OK(0),        // Compilation completed with no errors.
    81         ERROR(1),     // Completed but reported errors.
    82         CMDERR(2),    // Bad command-line arguments
    83         SYSERR(3),    // System error or resource exhaustion.
    84         ABNORMAL(4);  // Compiler terminated abnormally
    86         Result(int exitCode) {
    87             this.exitCode = exitCode;
    88         }
    90         public boolean isOK() {
    91             return (exitCode == 0);
    92         }
    94         public final int exitCode;
    95     }
    97     private Option[] recognizedOptions = RecognizedOptions.getJavaCompilerOptions(new OptionHelper() {
    99         public void setOut(PrintWriter out) {
   100             Main.this.out = out;
   101         }
   103         public void error(String key, Object... args) {
   104             Main.this.error(key, args);
   105         }
   107         public void printVersion() {
   108             Log.printLines(out, getLocalizedString("version", ownName,  JavaCompiler.version()));
   109         }
   111         public void printFullVersion() {
   112             Log.printLines(out, getLocalizedString("fullVersion", ownName,  JavaCompiler.fullVersion()));
   113         }
   115         public void printHelp() {
   116             help();
   117         }
   119         public void printXhelp() {
   120             xhelp();
   121         }
   123         public void addFile(File f) {
   124             filenames.add(f);
   125         }
   127         public void addClassName(String s) {
   128             classnames.append(s);
   129         }
   131     });
   133     /**
   134      * Construct a compiler instance.
   135      */
   136     public Main(String name) {
   137         this(name, new PrintWriter(System.err, true));
   138     }
   140     /**
   141      * Construct a compiler instance.
   142      */
   143     public Main(String name, PrintWriter out) {
   144         this.ownName = name;
   145         this.out = out;
   146     }
   147     /** A table of all options that's passed to the JavaCompiler constructor.  */
   148     private Options options = null;
   150     /** The list of source files to process
   151      */
   152     public Set<File> filenames = null; // XXX sb protected
   154     /** List of class files names passed on the command line
   155      */
   156     public ListBuffer<String> classnames = null; // XXX sb protected
   158     /** Print a string that explains usage.
   159      */
   160     void help() {
   161         Log.printLines(out, getLocalizedString("msg.usage.header", ownName));
   162         for (int i=0; i<recognizedOptions.length; i++) {
   163             recognizedOptions[i].help(out);
   164         }
   165         out.println();
   166     }
   168     /** Print a string that explains usage for X options.
   169      */
   170     void xhelp() {
   171         for (int i=0; i<recognizedOptions.length; i++) {
   172             recognizedOptions[i].xhelp(out);
   173         }
   174         out.println();
   175         Log.printLines(out, getLocalizedString("msg.usage.nonstandard.footer"));
   176     }
   178     /** Report a usage error.
   179      */
   180     void error(String key, Object... args) {
   181         if (apiMode) {
   182             String msg = getLocalizedString(key, args);
   183             throw new PropagatedException(new IllegalStateException(msg));
   184         }
   185         warning(key, args);
   186         Log.printLines(out, getLocalizedString("msg.usage", ownName));
   187     }
   189     /** Report a warning.
   190      */
   191     void warning(String key, Object... args) {
   192         Log.printLines(out, ownName + ": "
   193                        + getLocalizedString(key, args));
   194     }
   196     public Option getOption(String flag) {
   197         for (Option option : recognizedOptions) {
   198             if (option.matches(flag))
   199                 return option;
   200         }
   201         return null;
   202     }
   204     public void setOptions(Options options) {
   205         if (options == null)
   206             throw new NullPointerException();
   207         this.options = options;
   208     }
   210     public void setAPIMode(boolean apiMode) {
   211         this.apiMode = apiMode;
   212     }
   214     /** Process command line arguments: store all command line options
   215      *  in `options' table and return all source filenames.
   216      *  @param flags    The array of command line arguments.
   217      */
   218     public Collection<File> processArgs(String[] flags) { // XXX sb protected
   219         int ac = 0;
   220         while (ac < flags.length) {
   221             String flag = flags[ac];
   222             ac++;
   224             Option option = null;
   226             if (flag.length() > 0) {
   227                 // quick hack to speed up file processing:
   228                 // if the option does not begin with '-', there is no need to check
   229                 // most of the compiler options.
   230                 int firstOptionToCheck = flag.charAt(0) == '-' ? 0 : recognizedOptions.length-1;
   231                 for (int j=firstOptionToCheck; j<recognizedOptions.length; j++) {
   232                     if (recognizedOptions[j].matches(flag)) {
   233                         option = recognizedOptions[j];
   234                         break;
   235                     }
   236                 }
   237             }
   239             if (option == null) {
   240                 error("err.invalid.flag", flag);
   241                 return null;
   242             }
   244             if (option.hasArg()) {
   245                 if (ac == flags.length) {
   246                     error("err.req.arg", flag);
   247                     return null;
   248                 }
   249                 String operand = flags[ac];
   250                 ac++;
   251                 if (option.process(options, flag, operand))
   252                     return null;
   253             } else {
   254                 if (option.process(options, flag))
   255                     return null;
   256             }
   257         }
   259         if (!checkDirectory(D))
   260             return null;
   261         if (!checkDirectory(S))
   262             return null;
   264         String sourceString = options.get(SOURCE);
   265         Source source = (sourceString != null)
   266             ? Source.lookup(sourceString)
   267             : Source.DEFAULT;
   268         String targetString = options.get(TARGET);
   269         Target target = (targetString != null)
   270             ? Target.lookup(targetString)
   271             : Target.DEFAULT;
   272         // We don't check source/target consistency for CLDC, as J2ME
   273         // profiles are not aligned with J2SE targets; moreover, a
   274         // single CLDC target may have many profiles.  In addition,
   275         // this is needed for the continued functioning of the JSR14
   276         // prototype.
   277         if (Character.isDigit(target.name.charAt(0))) {
   278             if (target.compareTo(source.requiredTarget()) < 0) {
   279                 if (targetString != null) {
   280                     if (sourceString == null) {
   281                         warning("warn.target.default.source.conflict",
   282                                 targetString,
   283                                 source.requiredTarget().name);
   284                     } else {
   285                         warning("warn.source.target.conflict",
   286                                 sourceString,
   287                                 source.requiredTarget().name);
   288                     }
   289                     return null;
   290                 } else {
   291                     target = source.requiredTarget();
   292                     options.put("-target", target.name);
   293                 }
   294             } else {
   295                 if (targetString == null && !source.allowGenerics()) {
   296                     target = Target.JDK1_4;
   297                     options.put("-target", target.name);
   298                 }
   299             }
   300         }
   302         // handle this here so it works even if no other options given
   303         String showClass = options.get("showClass");
   304         if (showClass != null) {
   305             if (showClass.equals("showClass")) // no value given for option
   306                 showClass = "com.sun.tools.javac.Main";
   307             showClass(showClass);
   308         }
   310         return filenames;
   311     }
   312     // where
   313         private boolean checkDirectory(OptionName optName) {
   314             String value = options.get(optName);
   315             if (value == null)
   316                 return true;
   317             File file = new File(value);
   318             if (!file.exists()) {
   319                 error("err.dir.not.found", value);
   320                 return false;
   321             }
   322             if (!file.isDirectory()) {
   323                 error("err.file.not.directory", value);
   324                 return false;
   325             }
   326             return true;
   327         }
   329     /** Programmatic interface for main function.
   330      * @param args    The command line parameters.
   331      */
   332     public Result compile(String[] args) {
   333         Context context = new Context();
   334         JavacFileManager.preRegister(context); // can't create it until Log has been set up
   335         Result result = compile(args, context);
   336         if (fileManager instanceof JavacFileManager) {
   337             // A fresh context was created above, so jfm must be a JavacFileManager
   338             ((JavacFileManager)fileManager).close();
   339         }
   340         return result;
   341     }
   343     public Result compile(String[] args, Context context) {
   344         return compile(args, context, List.<JavaFileObject>nil(), null);
   345     }
   347     /** Programmatic interface for main function.
   348      * @param args    The command line parameters.
   349      */
   350     public Result compile(String[] args,
   351                        Context context,
   352                        List<JavaFileObject> fileObjects,
   353                        Iterable<? extends Processor> processors)
   354     {
   355         if (options == null)
   356             options = Options.instance(context); // creates a new one
   358         filenames = new LinkedHashSet<File>();
   359         classnames = new ListBuffer<String>();
   360         JavaCompiler comp = null;
   361         /*
   362          * TODO: Logic below about what is an acceptable command line
   363          * should be updated to take annotation processing semantics
   364          * into account.
   365          */
   366         try {
   367             if (args.length == 0 && fileObjects.isEmpty()) {
   368                 help();
   369                 return Result.CMDERR;
   370             }
   372             Collection<File> files;
   373             try {
   374                 files = processArgs(CommandLine.parse(args));
   375                 if (files == null) {
   376                     // null signals an error in options, abort
   377                     return Result.CMDERR;
   378                 } else if (files.isEmpty() && fileObjects.isEmpty() && classnames.isEmpty()) {
   379                     // it is allowed to compile nothing if just asking for help or version info
   380                     if (options.isSet(HELP)
   381                         || options.isSet(X)
   382                         || options.isSet(VERSION)
   383                         || options.isSet(FULLVERSION))
   384                         return Result.OK;
   385                     if (JavaCompiler.explicitAnnotationProcessingRequested(options)) {
   386                         error("err.no.source.files.classes");
   387                     } else {
   388                         error("err.no.source.files");
   389                     }
   390                     return Result.CMDERR;
   391                 }
   392             } catch (java.io.FileNotFoundException e) {
   393                 Log.printLines(out, ownName + ": " +
   394                                getLocalizedString("err.file.not.found",
   395                                                   e.getMessage()));
   396                 return Result.SYSERR;
   397             }
   399             boolean forceStdOut = options.isSet("stdout");
   400             if (forceStdOut) {
   401                 out.flush();
   402                 out = new PrintWriter(System.out, true);
   403             }
   405             context.put(Log.outKey, out);
   407             // allow System property in following line as a Mustang legacy
   408             boolean batchMode = (options.isUnset("nonBatchMode")
   409                         && System.getProperty("nonBatchMode") == null);
   410             if (batchMode)
   411                 CacheFSInfo.preRegister(context);
   413             fileManager = context.get(JavaFileManager.class);
   415             comp = JavaCompiler.instance(context);
   416             if (comp == null) return Result.SYSERR;
   418             Log log = Log.instance(context);
   420             if (!files.isEmpty()) {
   421                 // add filenames to fileObjects
   422                 comp = JavaCompiler.instance(context);
   423                 List<JavaFileObject> otherFiles = List.nil();
   424                 JavacFileManager dfm = (JavacFileManager)fileManager;
   425                 for (JavaFileObject fo : dfm.getJavaFileObjectsFromFiles(files))
   426                     otherFiles = otherFiles.prepend(fo);
   427                 for (JavaFileObject fo : otherFiles)
   428                     fileObjects = fileObjects.prepend(fo);
   429             }
   430             comp.compile(fileObjects,
   431                          classnames.toList(),
   432                          processors);
   434             if (log.expectDiagKeys != null) {
   435                 if (log.expectDiagKeys.isEmpty()) {
   436                     Log.printLines(log.noticeWriter, "all expected diagnostics found");
   437                     return Result.OK;
   438                 } else {
   439                     Log.printLines(log.noticeWriter, "expected diagnostic keys not found: " + log.expectDiagKeys);
   440                     return Result.ERROR;
   441                 }
   442             }
   444             if (comp.errorCount() != 0)
   445                 return Result.ERROR;
   446         } catch (IOException ex) {
   447             ioMessage(ex);
   448             return Result.SYSERR;
   449         } catch (OutOfMemoryError ex) {
   450             resourceMessage(ex);
   451             return Result.SYSERR;
   452         } catch (StackOverflowError ex) {
   453             resourceMessage(ex);
   454             return Result.SYSERR;
   455         } catch (FatalError ex) {
   456             feMessage(ex);
   457             return Result.SYSERR;
   458         } catch (AnnotationProcessingError ex) {
   459             if (apiMode)
   460                 throw new RuntimeException(ex.getCause());
   461             apMessage(ex);
   462             return Result.SYSERR;
   463         } catch (ClientCodeException ex) {
   464             // as specified by javax.tools.JavaCompiler#getTask
   465             // and javax.tools.JavaCompiler.CompilationTask#call
   466             throw new RuntimeException(ex.getCause());
   467         } catch (PropagatedException ex) {
   468             throw ex.getCause();
   469         } catch (Throwable ex) {
   470             // Nasty.  If we've already reported an error, compensate
   471             // for buggy compiler error recovery by swallowing thrown
   472             // exceptions.
   473             if (comp == null || comp.errorCount() == 0 ||
   474                 options == null || options.isSet("dev"))
   475                 bugMessage(ex);
   476             return Result.ABNORMAL;
   477         } finally {
   478             if (comp != null) {
   479                 try {
   480                     comp.close();
   481                 } catch (ClientCodeException ex) {
   482                     throw new RuntimeException(ex.getCause());
   483                 }
   484             }
   485             filenames = null;
   486             options = null;
   487         }
   488         return Result.OK;
   489     }
   491     /** Print a message reporting an internal error.
   492      */
   493     void bugMessage(Throwable ex) {
   494         Log.printLines(out, getLocalizedString("msg.bug",
   495                                                JavaCompiler.version()));
   496         ex.printStackTrace(out);
   497     }
   499     /** Print a message reporting a fatal error.
   500      */
   501     void feMessage(Throwable ex) {
   502         Log.printLines(out, ex.getMessage());
   503         if (ex.getCause() != null && options.isSet("dev")) {
   504             ex.getCause().printStackTrace(out);
   505         }
   506     }
   508     /** Print a message reporting an input/output error.
   509      */
   510     void ioMessage(Throwable ex) {
   511         Log.printLines(out, getLocalizedString("msg.io"));
   512         ex.printStackTrace(out);
   513     }
   515     /** Print a message reporting an out-of-resources error.
   516      */
   517     void resourceMessage(Throwable ex) {
   518         Log.printLines(out, getLocalizedString("msg.resource"));
   519 //      System.out.println("(name buffer len = " + Name.names.length + " " + Name.nc);//DEBUG
   520         ex.printStackTrace(out);
   521     }
   523     /** Print a message reporting an uncaught exception from an
   524      * annotation processor.
   525      */
   526     void apMessage(AnnotationProcessingError ex) {
   527         Log.printLines(out,
   528                        getLocalizedString("msg.proc.annotation.uncaught.exception"));
   529         ex.getCause().printStackTrace(out);
   530     }
   532     /** Display the location and checksum of a class. */
   533     void showClass(String className) {
   534         out.println("javac: show class: " + className);
   535         URL url = getClass().getResource('/' + className.replace('.', '/') + ".class");
   536         if (url == null)
   537             out.println("  class not found");
   538         else {
   539             out.println("  " + url);
   540             try {
   541                 final String algorithm = "MD5";
   542                 byte[] digest;
   543                 MessageDigest md = MessageDigest.getInstance(algorithm);
   544                 DigestInputStream in = new DigestInputStream(url.openStream(), md);
   545                 try {
   546                     byte[] buf = new byte[8192];
   547                     int n;
   548                     do { n = in.read(buf); } while (n > 0);
   549                     digest = md.digest();
   550                 } finally {
   551                     in.close();
   552                 }
   553                 StringBuilder sb = new StringBuilder();
   554                 for (byte b: digest)
   555                     sb.append(String.format("%02x", b));
   556                 out.println("  " + algorithm + " checksum: " + sb);
   557             } catch (Exception e) {
   558                 out.println("  cannot compute digest: " + e);
   559             }
   560         }
   561     }
   563     private JavaFileManager fileManager;
   565     /* ************************************************************************
   566      * Internationalization
   567      *************************************************************************/
   569     /** Find a localized string in the resource bundle.
   570      *  @param key     The key for the localized string.
   571      */
   572     public static String getLocalizedString(String key, Object... args) { // FIXME sb private
   573         try {
   574             if (messages == null)
   575                 messages = new JavacMessages(javacBundleName);
   576             return messages.getLocalizedString("javac." + key, args);
   577         }
   578         catch (MissingResourceException e) {
   579             throw new Error("Fatal Error: Resource for javac is missing", e);
   580         }
   581     }
   583     public static void useRawMessages(boolean enable) {
   584         if (enable) {
   585             messages = new JavacMessages(javacBundleName) {
   586                     @Override
   587                     public String getLocalizedString(String key, Object... args) {
   588                         return key;
   589                     }
   590                 };
   591         } else {
   592             messages = new JavacMessages(javacBundleName);
   593         }
   594     }
   596     private static final String javacBundleName =
   597         "com.sun.tools.javac.resources.javac";
   599     private static JavacMessages messages;
   600 }

mercurial