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

changeset 1
9a66ca7c79fa
child 50
b9bcea8bbe24
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/classes/com/sun/tools/apt/main/Main.java	Sat Dec 01 00:00:00 2007 +0000
     1.3 @@ -0,0 +1,1329 @@
     1.4 +/*
     1.5 + * Copyright 2004-2006 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Sun designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Sun in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    1.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
    1.26 + * have any questions.
    1.27 + */
    1.28 +
    1.29 +package com.sun.tools.apt.main;
    1.30 +
    1.31 +import java.io.File;
    1.32 +import java.io.FileOutputStream;
    1.33 +import java.io.FileWriter;
    1.34 +import java.io.IOException;
    1.35 +import java.io.PrintWriter;
    1.36 +import java.text.MessageFormat;
    1.37 +import java.util.ResourceBundle;
    1.38 +import java.util.MissingResourceException;
    1.39 +import java.util.StringTokenizer;
    1.40 +import java.util.Map;
    1.41 +import java.util.HashMap;
    1.42 +import java.util.Collections;
    1.43 +import java.util.Collection;
    1.44 +
    1.45 +import java.net.URLClassLoader;
    1.46 +import java.net.URL;
    1.47 +import java.io.File;
    1.48 +import java.net.MalformedURLException;
    1.49 +
    1.50 +import com.sun.tools.javac.util.Paths;
    1.51 +import com.sun.tools.javac.code.Source;
    1.52 +import com.sun.tools.javac.code.Symbol;
    1.53 +import com.sun.tools.javac.code.Type;
    1.54 +import com.sun.tools.javac.jvm.Target;
    1.55 +import com.sun.tools.javac.util.*;
    1.56 +
    1.57 +import com.sun.tools.apt.comp.AnnotationProcessingError;
    1.58 +import com.sun.tools.apt.comp.UsageMessageNeededException;
    1.59 +import com.sun.tools.apt.util.Bark;
    1.60 +import com.sun.mirror.apt.AnnotationProcessorFactory;
    1.61 +
    1.62 +/** This class provides a commandline interface to the apt build-time
    1.63 + *  tool.
    1.64 + *
    1.65 + *  <p><b>This is NOT part of any API supported by Sun Microsystems.
    1.66 + *  If you write code that depends on this, you do so at your own
    1.67 + *  risk.  This code and its internal interfaces are subject to change
    1.68 + *  or deletion without notice.</b>
    1.69 + */
    1.70 +public class Main {
    1.71 +
    1.72 +    /** For testing: enter any options you want to be set implicitly
    1.73 +     *  here.
    1.74 +     */
    1.75 +    static String[] forcedOpts = {
    1.76 +        // Preserve parameter names from class files if the class was
    1.77 +        // compiled with debug enabled
    1.78 +        "-XDsave-parameter-names"
    1.79 +    };
    1.80 +
    1.81 +    /** The name of the compiler, for use in diagnostics.
    1.82 +     */
    1.83 +    String ownName;
    1.84 +
    1.85 +    /** The writer to use for diagnostic output.
    1.86 +     */
    1.87 +    PrintWriter out;
    1.88 +
    1.89 +
    1.90 +    /** Instantiated factory to use in lieu of discovery process.
    1.91 +     */
    1.92 +    AnnotationProcessorFactory providedFactory = null;
    1.93 +
    1.94 +    /** Map representing original command-line arguments.
    1.95 +     */
    1.96 +    Map<String,String> origOptions = new HashMap<String, String>();
    1.97 +
    1.98 +    /** Classloader to use for finding factories.
    1.99 +     */
   1.100 +    ClassLoader aptCL = null;
   1.101 +
   1.102 +    /** Result codes.
   1.103 +     */
   1.104 +    static final int
   1.105 +        EXIT_OK = 0,        // Compilation completed with no errors.
   1.106 +        EXIT_ERROR = 1,     // Completed but reported errors.
   1.107 +        EXIT_CMDERR = 2,    // Bad command-line arguments
   1.108 +        EXIT_SYSERR = 3,    // System error or resource exhaustion.
   1.109 +        EXIT_ABNORMAL = 4;  // Compiler terminated abnormally
   1.110 +
   1.111 +    /** This class represents an option recognized by the main program
   1.112 +     */
   1.113 +    private class Option {
   1.114 +        /** Whether or not the option is used only aptOnly.
   1.115 +         */
   1.116 +        boolean aptOnly = false;
   1.117 +
   1.118 +        /** Option string.
   1.119 +         */
   1.120 +        String name;
   1.121 +
   1.122 +        /** Documentation key for arguments.
   1.123 +         */
   1.124 +        String argsNameKey;
   1.125 +
   1.126 +        /** Documentation key for description.
   1.127 +         */
   1.128 +        String descrKey;
   1.129 +
   1.130 +        /** Suffix option (-foo=bar or -foo:bar)
   1.131 +         */
   1.132 +        boolean hasSuffix;
   1.133 +
   1.134 +        Option(String name, String argsNameKey, String descrKey) {
   1.135 +            this.name = name;
   1.136 +            this.argsNameKey = argsNameKey;
   1.137 +            this.descrKey = descrKey;
   1.138 +            char lastChar = name.charAt(name.length()-1);
   1.139 +            hasSuffix = lastChar == ':' || lastChar == '=';
   1.140 +        }
   1.141 +        Option(String name, String descrKey) {
   1.142 +            this(name, null, descrKey);
   1.143 +        }
   1.144 +
   1.145 +        public String toString() {
   1.146 +            return name;
   1.147 +        }
   1.148 +
   1.149 +        /** Does this option take a (separate) operand?
   1.150 +         */
   1.151 +        boolean hasArg() {
   1.152 +            return argsNameKey != null && !hasSuffix;
   1.153 +        }
   1.154 +
   1.155 +        /** Does argument string match option pattern?
   1.156 +         *  @param arg        The command line argument string.
   1.157 +         */
   1.158 +        boolean matches(String arg) {
   1.159 +            return hasSuffix ? arg.startsWith(name) : arg.equals(name);
   1.160 +        }
   1.161 +
   1.162 +        /** For javac-only options, print nothing.
   1.163 +         */
   1.164 +        void help() {
   1.165 +        }
   1.166 +
   1.167 +        String helpSynopsis() {
   1.168 +            return name +
   1.169 +                (argsNameKey == null ? "" :
   1.170 +                 ((hasSuffix ? "" : " ") +
   1.171 +                  getLocalizedString(argsNameKey)));
   1.172 +        }
   1.173 +
   1.174 +        /** Print a line of documentation describing this option, if non-standard.
   1.175 +         */
   1.176 +        void xhelp() {}
   1.177 +
   1.178 +        /** Process the option (with arg). Return true if error detected.
   1.179 +         */
   1.180 +        boolean process(String option, String arg) {
   1.181 +            options.put(option, arg);
   1.182 +            return false;
   1.183 +        }
   1.184 +
   1.185 +        /** Process the option (without arg). Return true if error detected.
   1.186 +         */
   1.187 +        boolean process(String option) {
   1.188 +            if (hasSuffix)
   1.189 +                return process(name, option.substring(name.length()));
   1.190 +            else
   1.191 +                return process(option, option);
   1.192 +        }
   1.193 +    };
   1.194 +
   1.195 +    private class SharedOption extends Option {
   1.196 +        SharedOption(String name, String argsNameKey, String descrKey) {
   1.197 +            super(name, argsNameKey, descrKey);
   1.198 +        }
   1.199 +
   1.200 +        SharedOption(String name, String descrKey) {
   1.201 +            super(name, descrKey);
   1.202 +        }
   1.203 +
   1.204 +        void help() {
   1.205 +            String s = "  " + helpSynopsis();
   1.206 +            out.print(s);
   1.207 +            for (int j = s.length(); j < 29; j++) out.print(" ");
   1.208 +            Bark.printLines(out, getLocalizedString(descrKey));
   1.209 +        }
   1.210 +
   1.211 +    }
   1.212 +
   1.213 +    private class AptOption extends Option {
   1.214 +        AptOption(String name, String argsNameKey, String descrKey) {
   1.215 +            super(name, argsNameKey, descrKey);
   1.216 +            aptOnly = true;
   1.217 +        }
   1.218 +
   1.219 +        AptOption(String name, String descrKey) {
   1.220 +            super(name, descrKey);
   1.221 +            aptOnly = true;
   1.222 +        }
   1.223 +
   1.224 +        /** Print a line of documentation describing this option, if standard.
   1.225 +         */
   1.226 +        void help() {
   1.227 +            String s = "  " + helpSynopsis();
   1.228 +            out.print(s);
   1.229 +            for (int j = s.length(); j < 29; j++) out.print(" ");
   1.230 +            Bark.printLines(out, getLocalizedString(descrKey));
   1.231 +        }
   1.232 +
   1.233 +    }
   1.234 +
   1.235 +    /** A nonstandard or extended (-X) option
   1.236 +     */
   1.237 +    private class XOption extends Option {
   1.238 +        XOption(String name, String argsNameKey, String descrKey) {
   1.239 +            super(name, argsNameKey, descrKey);
   1.240 +        }
   1.241 +        XOption(String name, String descrKey) {
   1.242 +            this(name, null, descrKey);
   1.243 +        }
   1.244 +        void help() {}
   1.245 +        void xhelp() {}
   1.246 +    };
   1.247 +
   1.248 +    /** A nonstandard or extended (-X) option
   1.249 +     */
   1.250 +    private class AptXOption extends Option {
   1.251 +        AptXOption(String name, String argsNameKey, String descrKey) {
   1.252 +            super(name, argsNameKey, descrKey);
   1.253 +            aptOnly = true;
   1.254 +        }
   1.255 +        AptXOption(String name, String descrKey) {
   1.256 +            this(name, null, descrKey);
   1.257 +        }
   1.258 +        void xhelp() {
   1.259 +            String s = "  " + helpSynopsis();
   1.260 +            out.print(s);
   1.261 +            for (int j = s.length(); j < 29; j++) out.print(" ");
   1.262 +            Log.printLines(out, getLocalizedString(descrKey));
   1.263 +        }
   1.264 +    };
   1.265 +
   1.266 +    /** A hidden (implementor) option
   1.267 +     */
   1.268 +    private class HiddenOption extends Option {
   1.269 +        HiddenOption(String name) {
   1.270 +            super(name, null, null);
   1.271 +        }
   1.272 +        HiddenOption(String name, String argsNameKey) {
   1.273 +            super(name, argsNameKey, null);
   1.274 +        }
   1.275 +        void help() {}
   1.276 +        void xhelp() {}
   1.277 +    };
   1.278 +
   1.279 +    private class AptHiddenOption extends HiddenOption {
   1.280 +        AptHiddenOption(String name) {
   1.281 +            super(name);
   1.282 +            aptOnly = true;
   1.283 +        }
   1.284 +        AptHiddenOption(String name, String argsNameKey) {
   1.285 +            super(name, argsNameKey);
   1.286 +            aptOnly = true;
   1.287 +        }
   1.288 +    }
   1.289 +
   1.290 +    private Option[] recognizedOptions = {
   1.291 +        new Option("-g",                                        "opt.g"),
   1.292 +        new Option("-g:none",                                   "opt.g.none") {
   1.293 +            boolean process(String option) {
   1.294 +                options.put("-g:", "none");
   1.295 +                return false;
   1.296 +            }
   1.297 +        },
   1.298 +
   1.299 +        new Option("-g:{lines,vars,source}",                    "opt.g.lines.vars.source") {
   1.300 +            boolean matches(String s) {
   1.301 +                return s.startsWith("-g:");
   1.302 +            }
   1.303 +            boolean process(String option) {
   1.304 +                String suboptions = option.substring(3);
   1.305 +                options.put("-g:", suboptions);
   1.306 +                // enter all the -g suboptions as "-g:suboption"
   1.307 +                for (StringTokenizer t = new StringTokenizer(suboptions, ","); t.hasMoreTokens(); ) {
   1.308 +                    String tok = t.nextToken();
   1.309 +                    String opt = "-g:" + tok;
   1.310 +                    options.put(opt, opt);
   1.311 +                }
   1.312 +                return false;
   1.313 +            }
   1.314 +        },
   1.315 +
   1.316 +        new XOption("-Xlint",                                   "opt.Xlint"),
   1.317 +        new XOption("-Xlint:{"
   1.318 +                    + "all,"
   1.319 +                    + "cast,deprecation,divzero,empty,unchecked,fallthrough,path,serial,finally,overrides,"
   1.320 +                    + "-cast,-deprecation,-divzero,-empty,-unchecked,-fallthrough,-path,-serial,-finally,-overrides,"
   1.321 +                    + "none}",
   1.322 +                                                                "opt.Xlint.suboptlist") {
   1.323 +            boolean matches(String s) {
   1.324 +                return s.startsWith("-Xlint:");
   1.325 +            }
   1.326 +            boolean process(String option) {
   1.327 +                String suboptions = option.substring(7);
   1.328 +                options.put("-Xlint:", suboptions);
   1.329 +                // enter all the -Xlint suboptions as "-Xlint:suboption"
   1.330 +                for (StringTokenizer t = new StringTokenizer(suboptions, ","); t.hasMoreTokens(); ) {
   1.331 +                    String tok = t.nextToken();
   1.332 +                    String opt = "-Xlint:" + tok;
   1.333 +                    options.put(opt, opt);
   1.334 +                }
   1.335 +                return false;
   1.336 +            }
   1.337 +        },
   1.338 +
   1.339 +        new Option("-nowarn",                                   "opt.nowarn"),
   1.340 +        new Option("-verbose",                                  "opt.verbose"),
   1.341 +
   1.342 +        // -deprecation is retained for command-line backward compatibility
   1.343 +        new Option("-deprecation",                              "opt.deprecation") {
   1.344 +                boolean process(String option) {
   1.345 +                    options.put("-Xlint:deprecation", option);
   1.346 +                    return false;
   1.347 +                }
   1.348 +            },
   1.349 +
   1.350 +        new SharedOption("-classpath",     "opt.arg.path",      "opt.classpath"),
   1.351 +        new SharedOption("-cp",            "opt.arg.path",      "opt.classpath") {
   1.352 +            boolean process(String option, String arg) {
   1.353 +                return super.process("-classpath", arg);
   1.354 +            }
   1.355 +        },
   1.356 +        new Option("-sourcepath",          "opt.arg.path",      "opt.sourcepath"),
   1.357 +        new Option("-bootclasspath",       "opt.arg.path",      "opt.bootclasspath") {
   1.358 +            boolean process(String option, String arg) {
   1.359 +                options.remove("-Xbootclasspath/p:");
   1.360 +                options.remove("-Xbootclasspath/a:");
   1.361 +                return super.process(option, arg);
   1.362 +            }
   1.363 +        },
   1.364 +        new XOption("-Xbootclasspath/p:",  "opt.arg.path", "opt.Xbootclasspath.p"),
   1.365 +        new XOption("-Xbootclasspath/a:",  "opt.arg.path", "opt.Xbootclasspath.a"),
   1.366 +        new XOption("-Xbootclasspath:",    "opt.arg.path", "opt.bootclasspath") {
   1.367 +            boolean process(String option, String arg) {
   1.368 +                options.remove("-Xbootclasspath/p:");
   1.369 +                options.remove("-Xbootclasspath/a:");
   1.370 +                return super.process("-bootclasspath", arg);
   1.371 +            }
   1.372 +        },
   1.373 +        new Option("-extdirs",             "opt.arg.dirs",      "opt.extdirs"),
   1.374 +        new XOption("-Djava.ext.dirs=",    "opt.arg.dirs",      "opt.extdirs") {
   1.375 +            boolean process(String option, String arg) {
   1.376 +                return super.process("-extdirs", arg);
   1.377 +            }
   1.378 +        },
   1.379 +        new Option("-endorseddirs",        "opt.arg.dirs",      "opt.endorseddirs"),
   1.380 +        new XOption("-Djava.endorsed.dirs=","opt.arg.dirs",     "opt.endorseddirs") {
   1.381 +            boolean process(String option, String arg) {
   1.382 +                return super.process("-endorseddirs", arg);
   1.383 +            }
   1.384 +        },
   1.385 +        new Option("-proc:{none, only}",                        "opt.proc.none.only") {
   1.386 +            public boolean matches(String s) {
   1.387 +                return s.equals("-proc:none") || s.equals("-proc:only");
   1.388 +            }
   1.389 +        },
   1.390 +        new Option("-processor",        "opt.arg.class",        "opt.processor"),
   1.391 +        new Option("-processorpath",    "opt.arg.path",         "opt.processorpath"),
   1.392 +
   1.393 +        new SharedOption("-d",          "opt.arg.path", "opt.d"),
   1.394 +        new SharedOption("-s",          "opt.arg.path", "opt.s"),
   1.395 +        new Option("-encoding",         "opt.arg.encoding",     "opt.encoding"),
   1.396 +        new SharedOption("-source",             "opt.arg.release",      "opt.source") {
   1.397 +            boolean process(String option, String operand) {
   1.398 +                Source source = Source.lookup(operand);
   1.399 +                if (source == null) {
   1.400 +                    error("err.invalid.source", operand);
   1.401 +                    return true;
   1.402 +                } else if (source.compareTo(Source.JDK1_5) > 0) {
   1.403 +                    error("err.unsupported.source.version", operand);
   1.404 +                    return true;
   1.405 +                }
   1.406 +                return super.process(option, operand);
   1.407 +            }
   1.408 +        },
   1.409 +        new Option("-target",           "opt.arg.release",      "opt.target") {
   1.410 +            boolean process(String option, String operand) {
   1.411 +                Target target = Target.lookup(operand);
   1.412 +                if (target == null) {
   1.413 +                    error("err.invalid.target", operand);
   1.414 +                    return true;
   1.415 +                } else if (target.compareTo(Target.JDK1_5) > 0) {
   1.416 +                    error("err.unsupported.target.version", operand);
   1.417 +                    return true;
   1.418 +                }
   1.419 +                return super.process(option, operand);
   1.420 +            }
   1.421 +        },
   1.422 +        new AptOption("-version",               "opt.version") {
   1.423 +            boolean process(String option) {
   1.424 +                Bark.printLines(out, ownName + " " + JavaCompiler.version());
   1.425 +                return super.process(option);
   1.426 +            }
   1.427 +        },
   1.428 +        new HiddenOption("-fullversion"),
   1.429 +        new AptOption("-help",                                  "opt.help") {
   1.430 +            boolean process(String option) {
   1.431 +                Main.this.help();
   1.432 +                return super.process(option);
   1.433 +            }
   1.434 +        },
   1.435 +        new SharedOption("-X",                                  "opt.X") {
   1.436 +            boolean process(String option) {
   1.437 +                Main.this.xhelp();
   1.438 +                return super.process(option);
   1.439 +            }
   1.440 +        },
   1.441 +
   1.442 +        // This option exists only for the purpose of documenting itself.
   1.443 +        // It's actually implemented by the launcher.
   1.444 +        new AptOption("-J",             "opt.arg.flag",         "opt.J") {
   1.445 +            String helpSynopsis() {
   1.446 +                hasSuffix = true;
   1.447 +                return super.helpSynopsis();
   1.448 +            }
   1.449 +            boolean process(String option) {
   1.450 +                throw new AssertionError
   1.451 +                    ("the -J flag should be caught by the launcher.");
   1.452 +            }
   1.453 +        },
   1.454 +
   1.455 +
   1.456 +        new SharedOption("-A",          "opt.proc.flag",        "opt.A") {
   1.457 +                String helpSynopsis() {
   1.458 +                    hasSuffix = true;
   1.459 +                    return super.helpSynopsis();
   1.460 +                }
   1.461 +
   1.462 +                boolean matches(String arg) {
   1.463 +                    return arg.startsWith("-A");
   1.464 +                }
   1.465 +
   1.466 +                boolean hasArg() {
   1.467 +                    return false;
   1.468 +                }
   1.469 +
   1.470 +                boolean process(String option) {
   1.471 +                    return process(option, option);
   1.472 +                }
   1.473 +            },
   1.474 +
   1.475 +        new AptOption("-nocompile",     "opt.nocompile"),
   1.476 +
   1.477 +        new AptOption("-print",         "opt.print"),
   1.478 +
   1.479 +        new AptOption("-factorypath", "opt.arg.path", "opt.factorypath"),
   1.480 +
   1.481 +        new AptOption("-factory",     "opt.arg.class", "opt.factory"),
   1.482 +
   1.483 +        new AptXOption("-XListAnnotationTypes", "opt.XListAnnotationTypes"),
   1.484 +
   1.485 +        new AptXOption("-XListDeclarations",    "opt.XListDeclarations"),
   1.486 +
   1.487 +        new AptXOption("-XPrintAptRounds",      "opt.XPrintAptRounds"),
   1.488 +
   1.489 +        new AptXOption("-XPrintFactoryInfo",    "opt.XPrintFactoryInfo"),
   1.490 +
   1.491 +        /*
   1.492 +         * Option to treat both classes and source files as
   1.493 +         * declarations that can be given on the command line and
   1.494 +         * processed as the result of an apt round.
   1.495 +         */
   1.496 +        new AptXOption("-XclassesAsDecls", "opt.XClassesAsDecls"),
   1.497 +
   1.498 +        // new Option("-moreinfo",                                      "opt.moreinfo") {
   1.499 +        new HiddenOption("-moreinfo") {
   1.500 +            boolean process(String option) {
   1.501 +                Type.moreInfo = true;
   1.502 +                return super.process(option);
   1.503 +            }
   1.504 +        },
   1.505 +
   1.506 +        // treat warnings as errors
   1.507 +        new HiddenOption("-Werror"),
   1.508 +
   1.509 +        // use complex inference from context in the position of a method call argument
   1.510 +        new HiddenOption("-complexinference"),
   1.511 +
   1.512 +        // prompt after each error
   1.513 +        // new Option("-prompt",                                        "opt.prompt"),
   1.514 +        new HiddenOption("-prompt"),
   1.515 +
   1.516 +        // dump stack on error
   1.517 +        new HiddenOption("-doe"),
   1.518 +
   1.519 +        // display warnings for generic unchecked and unsafe operations
   1.520 +        new HiddenOption("-warnunchecked") {
   1.521 +            boolean process(String option) {
   1.522 +                options.put("-Xlint:unchecked", option);
   1.523 +                return false;
   1.524 +            }
   1.525 +        },
   1.526 +
   1.527 +        new HiddenOption("-Xswitchcheck") {
   1.528 +            boolean process(String option) {
   1.529 +                options.put("-Xlint:switchcheck", option);
   1.530 +                return false;
   1.531 +            }
   1.532 +        },
   1.533 +
   1.534 +        // generate trace output for subtyping operations
   1.535 +        new HiddenOption("-debugsubtyping"),
   1.536 +
   1.537 +        new XOption("-Xmaxerrs",        "opt.arg.number",       "opt.maxerrs"),
   1.538 +        new XOption("-Xmaxwarns",       "opt.arg.number",       "opt.maxwarns"),
   1.539 +        new XOption("-Xstdout",         "opt.arg.file",         "opt.Xstdout") {
   1.540 +            boolean process(String option, String arg) {
   1.541 +                try {
   1.542 +                    out = new PrintWriter(new FileWriter(arg), true);
   1.543 +                } catch (java.io.IOException e) {
   1.544 +                    error("err.error.writing.file", arg, e);
   1.545 +                    return true;
   1.546 +                }
   1.547 +                return super.process(option, arg);
   1.548 +            }
   1.549 +        },
   1.550 +
   1.551 +        new XOption("-Xprint",                                  "opt.print"),
   1.552 +
   1.553 +        new XOption("-XprintRounds",                            "opt.printRounds"),
   1.554 +
   1.555 +        new XOption("-XprintProcessorInfo",                     "opt.printProcessorInfo"),
   1.556 +
   1.557 +
   1.558 +        /* -O is a no-op, accepted for backward compatibility. */
   1.559 +        new HiddenOption("-O"),
   1.560 +
   1.561 +        /* -Xjcov produces tables to support the code coverage tool jcov. */
   1.562 +        new HiddenOption("-Xjcov"),
   1.563 +
   1.564 +        /* This is a back door to the compiler's option table.
   1.565 +         * -Dx=y sets the option x to the value y.
   1.566 +         * -Dx sets the option x to the value x.
   1.567 +         */
   1.568 +        new HiddenOption("-XD") {
   1.569 +            String s;
   1.570 +            boolean matches(String s) {
   1.571 +                this.s = s;
   1.572 +                return s.startsWith(name);
   1.573 +            }
   1.574 +            boolean process(String option) {
   1.575 +                s = s.substring(name.length());
   1.576 +                int eq = s.indexOf('=');
   1.577 +                String key = (eq < 0) ? s : s.substring(0, eq);
   1.578 +                String value = (eq < 0) ? s : s.substring(eq+1);
   1.579 +                options.put(key, value);
   1.580 +                return false;
   1.581 +            }
   1.582 +        },
   1.583 +
   1.584 +        new HiddenOption("sourcefile") {
   1.585 +                String s;
   1.586 +                boolean matches(String s) {
   1.587 +                    this.s = s;
   1.588 +                    return s.endsWith(".java") ||
   1.589 +                        (options.get("-XclassesAsDecls") != null);
   1.590 +                }
   1.591 +                boolean process(String option) {
   1.592 +                    if (s.endsWith(".java")) {
   1.593 +                        if (!sourceFileNames.contains(s))
   1.594 +                            sourceFileNames.add(s);
   1.595 +                    } else if (options.get("-XclassesAsDecls") != null) {
   1.596 +                        classFileNames.add(s);
   1.597 +                    }
   1.598 +                    return false;
   1.599 +                }
   1.600 +            },
   1.601 +    };
   1.602 +
   1.603 +    /**
   1.604 +     * Construct a compiler instance.
   1.605 +     */
   1.606 +    public Main(String name) {
   1.607 +        this(name, new PrintWriter(System.err, true));
   1.608 +    }
   1.609 +
   1.610 +    /**
   1.611 +     * Construct a compiler instance.
   1.612 +     */
   1.613 +    public Main(String name, PrintWriter out) {
   1.614 +        this.ownName = name;
   1.615 +        this.out = out;
   1.616 +    }
   1.617 +
   1.618 +    /** A table of all options that's passed to the JavaCompiler constructor.  */
   1.619 +    private Options options = null;
   1.620 +
   1.621 +    /** The list of source files to process
   1.622 +     */
   1.623 +    java.util.List<String> sourceFileNames = new java.util.LinkedList<String>();
   1.624 +
   1.625 +    /** The list of class files to process
   1.626 +     */
   1.627 +    java.util.List<String> classFileNames = new java.util.LinkedList<String>();
   1.628 +
   1.629 +    /** List of top level names of generated source files from most recent apt round.
   1.630 +     */
   1.631 +    java.util.Set<String> genSourceFileNames = new java.util.LinkedHashSet<String>();
   1.632 +
   1.633 +    /** List of names of generated class files from most recent apt round.
   1.634 +     */
   1.635 +    java.util.Set<String> genClassFileNames  = new java.util.LinkedHashSet<String>();
   1.636 +
   1.637 +    /**
   1.638 +     * List of all the generated source file names across all apt rounds.
   1.639 +     */
   1.640 +    java.util.Set<String> aggregateGenSourceFileNames = new java.util.LinkedHashSet<String>();
   1.641 +
   1.642 +    /**
   1.643 +     * List of all the generated class file names across all apt rounds.
   1.644 +     */
   1.645 +    java.util.Set<String> aggregateGenClassFileNames  = new java.util.LinkedHashSet<String>();
   1.646 +
   1.647 +    /**
   1.648 +     * List of all the generated file names across all apt rounds.
   1.649 +     */
   1.650 +    java.util.Set<java.io.File> aggregateGenFiles = new java.util.LinkedHashSet<java.io.File>();
   1.651 +
   1.652 +    /**
   1.653 +     * Set of all factories that have provided a processor on some apt round.
   1.654 +     */
   1.655 +    java.util.Set<Class<? extends AnnotationProcessorFactory> > productiveFactories  =
   1.656 +        new java.util.LinkedHashSet<Class<? extends AnnotationProcessorFactory> >();
   1.657 +
   1.658 +
   1.659 +
   1.660 +    /** Print a string that explains usage.
   1.661 +     */
   1.662 +    void help() {
   1.663 +        Bark.printLines(out, getLocalizedString("msg.usage.header", ownName));
   1.664 +        for (int i=0; i < recognizedOptions.length; i++) {
   1.665 +            recognizedOptions[i].help();
   1.666 +        }
   1.667 +        Bark.printLines(out, getLocalizedString("msg.usage.footer"));
   1.668 +        out.println();
   1.669 +    }
   1.670 +
   1.671 +    /** Print a string that explains usage for X options.
   1.672 +     */
   1.673 +    void xhelp() {
   1.674 +        for (int i=0; i<recognizedOptions.length; i++) {
   1.675 +            recognizedOptions[i].xhelp();
   1.676 +        }
   1.677 +        out.println();
   1.678 +        Bark.printLines(out, getLocalizedString("msg.usage.nonstandard.footer"));
   1.679 +    }
   1.680 +
   1.681 +    /** Report a usage error.
   1.682 +     */
   1.683 +    void error(String key, Object... args) {
   1.684 +        warning(key, args);
   1.685 +        help();
   1.686 +    }
   1.687 +
   1.688 +    /** Report a warning.
   1.689 +     */
   1.690 +    void warning(String key, Object... args) {
   1.691 +        Bark.printLines(out, ownName + ": "
   1.692 +                       + getLocalizedString(key, args));
   1.693 +    }
   1.694 +
   1.695 +    /** Process command line arguments: store all command line options
   1.696 +     *  in `options' table and return all source filenames.
   1.697 +     *  @param args    The array of command line arguments.
   1.698 +     */
   1.699 +    protected java.util.List<String> processArgs(String[] flags) {
   1.700 +        int ac = 0;
   1.701 +        while (ac < flags.length) {
   1.702 +            String flag = flags[ac];
   1.703 +            ac++;
   1.704 +
   1.705 +            int j;
   1.706 +            for (j=0; j < recognizedOptions.length; j++)
   1.707 +                if (recognizedOptions[j].matches(flag))
   1.708 +                    break;
   1.709 +
   1.710 +            if (j == recognizedOptions.length) {
   1.711 +                error("err.invalid.flag", flag);
   1.712 +                return null;
   1.713 +            }
   1.714 +
   1.715 +            Option option = recognizedOptions[j];
   1.716 +            if (option.hasArg()) {
   1.717 +                if (ac == flags.length) {
   1.718 +                    error("err.req.arg", flag);
   1.719 +                    return null;
   1.720 +                }
   1.721 +                String operand = flags[ac];
   1.722 +                ac++;
   1.723 +                if (option.process(flag, operand))
   1.724 +                    return null;
   1.725 +            } else {
   1.726 +                if (option.process(flag))
   1.727 +                    return null;
   1.728 +            }
   1.729 +        }
   1.730 +
   1.731 +        String sourceString = options.get("-source");
   1.732 +        Source source = (sourceString != null)
   1.733 +            ? Source.lookup(sourceString)
   1.734 +            : Source.JDK1_5; // JDK 5 is the latest supported source version
   1.735 +        String targetString = options.get("-target");
   1.736 +        Target target = (targetString != null)
   1.737 +            ? Target.lookup(targetString)
   1.738 +            : Target.JDK1_5; // JDK 5 is the latest supported source version
   1.739 +        // We don't check source/target consistency for CLDC, as J2ME
   1.740 +        // profiles are not aligned with J2SE targets; moreover, a
   1.741 +        // single CLDC target may have many profiles.  In addition,
   1.742 +        // this is needed for the continued functioning of the JSR14
   1.743 +        // prototype.
   1.744 +        if (Character.isDigit(target.name.charAt(0)) &&
   1.745 +            target.compareTo(source.requiredTarget()) < 0) {
   1.746 +            if (targetString != null) {
   1.747 +                if (sourceString == null) {
   1.748 +                    warning("warn.target.default.source.conflict",
   1.749 +                            targetString,
   1.750 +                            source.requiredTarget().name);
   1.751 +                } else {
   1.752 +                    warning("warn.source.target.conflict",
   1.753 +                            sourceString,
   1.754 +                            source.requiredTarget().name);
   1.755 +                }
   1.756 +                return null;
   1.757 +            } else {
   1.758 +                options.put("-target", source.requiredTarget().name);
   1.759 +            }
   1.760 +        }
   1.761 +        return sourceFileNames;
   1.762 +    }
   1.763 +
   1.764 +    /** Programmatic interface for main function.
   1.765 +     * @param args    The command line parameters.
   1.766 +     */
   1.767 +    public int compile(String[] args, AnnotationProcessorFactory factory) {
   1.768 +        int returnCode = 0;
   1.769 +        providedFactory = factory;
   1.770 +
   1.771 +        Context context = new Context();
   1.772 +        options = Options.instance(context);
   1.773 +        Bark bark;
   1.774 +
   1.775 +        /*
   1.776 +         * Process the command line options to create the intial
   1.777 +         * options data.  This processing is at least partially reused
   1.778 +         * by any recursive apt calls.
   1.779 +         */
   1.780 +
   1.781 +        // For testing: assume all arguments in forcedOpts are
   1.782 +        // prefixed to command line arguments.
   1.783 +        processArgs(forcedOpts);
   1.784 +
   1.785 +
   1.786 +        /*
   1.787 +         * A run of apt only gets passed the most recently generated
   1.788 +         * files; the initial run of apt gets passed the files from
   1.789 +         * the command line.
   1.790 +         */
   1.791 +
   1.792 +        java.util.List<String> origFilenames;
   1.793 +        try {
   1.794 +            // assign args the result of parse to capture results of
   1.795 +            // '@file' expansion
   1.796 +            origFilenames = processArgs((args=CommandLine.parse(args)));
   1.797 +            if (origFilenames == null) {
   1.798 +                return EXIT_CMDERR;
   1.799 +            } else if (origFilenames.size() == 0) {
   1.800 +                // it is allowed to compile nothing if just asking for help
   1.801 +                if (options.get("-help") != null ||
   1.802 +                    options.get("-X") != null)
   1.803 +                    return EXIT_OK;
   1.804 +            }
   1.805 +        } catch (java.io.FileNotFoundException e) {
   1.806 +            Bark.printLines(out, ownName + ": " +
   1.807 +                           getLocalizedString("err.file.not.found",
   1.808 +                                              e.getMessage()));
   1.809 +            return EXIT_SYSERR;
   1.810 +        } catch (IOException ex) {
   1.811 +            ioMessage(ex);
   1.812 +            return EXIT_SYSERR;
   1.813 +        } catch (OutOfMemoryError ex) {
   1.814 +            resourceMessage(ex);
   1.815 +            return EXIT_SYSERR;
   1.816 +        } catch (StackOverflowError ex) {
   1.817 +            resourceMessage(ex);
   1.818 +            return EXIT_SYSERR;
   1.819 +        } catch (FatalError ex) {
   1.820 +            feMessage(ex);
   1.821 +            return EXIT_SYSERR;
   1.822 +        } catch (sun.misc.ServiceConfigurationError sce) {
   1.823 +            sceMessage(sce);
   1.824 +            return EXIT_ABNORMAL;
   1.825 +        } catch (Throwable ex) {
   1.826 +            bugMessage(ex);
   1.827 +            return EXIT_ABNORMAL;
   1.828 +        }
   1.829 +
   1.830 +
   1.831 +        boolean firstRound = true;
   1.832 +        boolean needSourcePath = false;
   1.833 +        boolean needClassPath  = false;
   1.834 +        boolean classesAsDecls = options.get("-XclassesAsDecls") != null;
   1.835 +
   1.836 +        /*
   1.837 +         * Create augumented classpath and sourcepath values.
   1.838 +         *
   1.839 +         * If any of the prior apt rounds generated any new source
   1.840 +         * files, the n'th apt round (and any javac invocation) has the
   1.841 +         * source destination path ("-s path") as the last element of
   1.842 +         * the "-sourcepath" to the n'th call.
   1.843 +         *
   1.844 +         * If any of the prior apt rounds generated any new class files,
   1.845 +         * the n'th apt round (and any javac invocation) has the class
   1.846 +         * destination path ("-d path") as the last element of the
   1.847 +         * "-classpath" to the n'th call.
   1.848 +         */
   1.849 +        String augmentedSourcePath = "";
   1.850 +        String augmentedClassPath = "";
   1.851 +        String baseClassPath = "";
   1.852 +
   1.853 +        try {
   1.854 +            /*
   1.855 +             * Record original options for future annotation processor
   1.856 +             * invocations.
   1.857 +             */
   1.858 +            origOptions = new HashMap<String, String>(options.size());
   1.859 +            for(String s: options.keySet()) {
   1.860 +                String value;
   1.861 +                if (s.equals(value = options.get(s)))
   1.862 +                    origOptions.put(s, (String)null);
   1.863 +                else
   1.864 +                    origOptions.put(s, value);
   1.865 +            }
   1.866 +            origOptions = Collections.unmodifiableMap(origOptions);
   1.867 +
   1.868 +            {
   1.869 +                // Note: it might be necessary to check for an empty
   1.870 +                // component ("") of the source path or class path
   1.871 +                Paths paths = Paths.instance(context);
   1.872 +
   1.873 +                String sourceDest = options.get("-s");
   1.874 +                if (paths.sourcePath() != null) {
   1.875 +                    for(File f: paths.sourcePath())
   1.876 +                        augmentedSourcePath += (f + File.pathSeparator);
   1.877 +                    augmentedSourcePath += (sourceDest == null)?".":sourceDest;
   1.878 +                } else {
   1.879 +                    augmentedSourcePath = ".";
   1.880 +
   1.881 +                    if (sourceDest != null)
   1.882 +                        augmentedSourcePath += (File.pathSeparator + sourceDest);
   1.883 +                }
   1.884 +
   1.885 +                String classDest = options.get("-d");
   1.886 +                if (paths.userClassPath() != null) {
   1.887 +                    for(File f: paths.userClassPath())
   1.888 +                        baseClassPath += (f + File.pathSeparator);
   1.889 +                    // put baseClassPath into map to handle any
   1.890 +                    // value needed for the classloader
   1.891 +                    options.put("-classpath", baseClassPath);
   1.892 +
   1.893 +                    augmentedClassPath = baseClassPath + ((classDest == null)?".":classDest);
   1.894 +                } else {
   1.895 +                    baseClassPath = ".";
   1.896 +                    if (classDest != null)
   1.897 +                        augmentedClassPath = baseClassPath + (File.pathSeparator + classDest);
   1.898 +                }
   1.899 +                assert options.get("-classpath") != null;
   1.900 +            }
   1.901 +
   1.902 +            /*
   1.903 +             * Create base and augmented class loaders
   1.904 +             */
   1.905 +            ClassLoader augmentedAptCL = null;
   1.906 +            {
   1.907 +            /*
   1.908 +             * Use a url class loader to look for classes on the
   1.909 +             * user-specified class path. Prepend computed bootclass
   1.910 +             * path, which includes extdirs, to the URLClassLoader apt
   1.911 +             * uses.
   1.912 +             */
   1.913 +                String aptclasspath = "";
   1.914 +                Paths paths = Paths.instance(context);
   1.915 +                String bcp = "";
   1.916 +                Collection<File> bootclasspath = paths.bootClassPath();
   1.917 +
   1.918 +                if (bootclasspath != null) {
   1.919 +                    for(File f: bootclasspath)
   1.920 +                        bcp += (f + File.pathSeparator);
   1.921 +                }
   1.922 +
   1.923 +                // If the factory path is set, use that path
   1.924 +                if (providedFactory == null)
   1.925 +                    aptclasspath = options.get("-factorypath");
   1.926 +                if (aptclasspath == null)
   1.927 +                    aptclasspath = options.get("-classpath");
   1.928 +
   1.929 +                assert aptclasspath != null;
   1.930 +                aptclasspath = (bcp + aptclasspath);
   1.931 +                aptCL = new URLClassLoader(pathToURLs(aptclasspath));
   1.932 +
   1.933 +                if (providedFactory == null &&
   1.934 +                    options.get("-factorypath") != null) // same CL even if new class files written
   1.935 +                    augmentedAptCL = aptCL;
   1.936 +                else {
   1.937 +                    // Create class loader in case new class files are
   1.938 +                    // written
   1.939 +                    augmentedAptCL = new URLClassLoader(pathToURLs(augmentedClassPath.
   1.940 +                                                                   substring(baseClassPath.length())),
   1.941 +                                                        aptCL);
   1.942 +                }
   1.943 +            }
   1.944 +
   1.945 +            int round = 0; // For -XPrintAptRounds
   1.946 +            do {
   1.947 +                round++;
   1.948 +
   1.949 +                Context newContext = new Context();
   1.950 +                Options newOptions = Options.instance(newContext); // creates a new context
   1.951 +                newOptions.putAll(options);
   1.952 +
   1.953 +                // populate with old options... don't bother reparsing command line, etc.
   1.954 +
   1.955 +                // if genSource files, must add destination to source path
   1.956 +                if (genSourceFileNames.size() > 0 && !firstRound) {
   1.957 +                    newOptions.put("-sourcepath", augmentedSourcePath);
   1.958 +                    needSourcePath = true;
   1.959 +                }
   1.960 +                aggregateGenSourceFileNames.addAll(genSourceFileNames);
   1.961 +                sourceFileNames.addAll(genSourceFileNames);
   1.962 +                genSourceFileNames.clear();
   1.963 +
   1.964 +                // Don't really need to track this; just have to add -d
   1.965 +                // "foo" to class path if any class files are generated
   1.966 +                if (genClassFileNames.size() > 0) {
   1.967 +                    newOptions.put("-classpath", augmentedClassPath);
   1.968 +                    aptCL = augmentedAptCL;
   1.969 +                    needClassPath = true;
   1.970 +                }
   1.971 +                aggregateGenClassFileNames.addAll(genClassFileNames);
   1.972 +                classFileNames.addAll(genClassFileNames);
   1.973 +                genClassFileNames.clear();
   1.974 +
   1.975 +                options = newOptions;
   1.976 +
   1.977 +                if (options.get("-XPrintAptRounds") != null) {
   1.978 +                    out.println("apt Round : " + round);
   1.979 +                    out.println("filenames: " + sourceFileNames);
   1.980 +                    if (classesAsDecls)
   1.981 +                        out.println("classnames: " + classFileNames);
   1.982 +                    out.println("options: " + options);
   1.983 +                }
   1.984 +
   1.985 +                returnCode = compile(args, newContext);
   1.986 +                firstRound = false;
   1.987 +
   1.988 +                // Check for reported errors before continuing
   1.989 +                bark = Bark.instance(newContext);
   1.990 +            } while(((genSourceFileNames.size() != 0 ) ||
   1.991 +                     (classesAsDecls && genClassFileNames.size() != 0)) &&
   1.992 +                    bark.nerrors == 0);
   1.993 +        } catch (UsageMessageNeededException umne) {
   1.994 +            help();
   1.995 +            return EXIT_CMDERR; // will cause usage message to be printed
   1.996 +        }
   1.997 +
   1.998 +        /*
   1.999 +         * Do not compile if a processor has reported an error or if
  1.1000 +         * there are no source files to process.  A more sophisticated
  1.1001 +         * test would also fail for syntax errors caught by javac.
  1.1002 +         */
  1.1003 +        if (options.get("-nocompile") == null &&
  1.1004 +            options.get("-print")     == null &&
  1.1005 +            bark.nerrors == 0 &&
  1.1006 +            (origFilenames.size() > 0 || aggregateGenSourceFileNames.size() > 0 )) {
  1.1007 +            /*
  1.1008 +             * Need to create new argument string for calling javac:
  1.1009 +             * 1. apt specific arguments (e.g. -factory) must be stripped out
  1.1010 +             * 2. proper settings for sourcepath and classpath must be used
  1.1011 +             * 3. generated class names must be added
  1.1012 +             * 4. class file names as declarations must be removed
  1.1013 +             */
  1.1014 +
  1.1015 +            int newArgsLength = args.length +
  1.1016 +                (needSourcePath?1:0) +
  1.1017 +                (needClassPath?1:0) +
  1.1018 +                aggregateGenSourceFileNames.size();
  1.1019 +
  1.1020 +            // Null out apt-specific options and don't copy over into
  1.1021 +            // newArgs. This loop should be a lot faster; the options
  1.1022 +            // array should be replaced with a better data structure
  1.1023 +            // which includes a map from strings to options.
  1.1024 +            //
  1.1025 +            // If treating classes as declarations, must strip out
  1.1026 +            // class names from the javac argument list
  1.1027 +            argLoop:
  1.1028 +            for(int i = 0; i < args.length; i++) {
  1.1029 +                int matchPosition = -1;
  1.1030 +
  1.1031 +                // "-A" by itself is recognized by apt but not javac
  1.1032 +                if (args[i] != null && args[i].equals("-A")) {
  1.1033 +                    newArgsLength--;
  1.1034 +                    args[i] = null;
  1.1035 +                    continue argLoop;
  1.1036 +                } else {
  1.1037 +                    optionLoop:
  1.1038 +                    for(int j = 0; j < recognizedOptions.length; j++) {
  1.1039 +                        if (args[i] != null && recognizedOptions[j].matches(args[i])) {
  1.1040 +                            matchPosition = j;
  1.1041 +                            break optionLoop;
  1.1042 +                        }
  1.1043 +                    }
  1.1044 +
  1.1045 +                    if (matchPosition != -1) {
  1.1046 +                        Option op = recognizedOptions[matchPosition];
  1.1047 +                        if (op.aptOnly) {
  1.1048 +                            newArgsLength--;
  1.1049 +                            args[i] = null;
  1.1050 +                            if (op.hasArg()) {
  1.1051 +                                newArgsLength--;
  1.1052 +                                args[i+1] = null;
  1.1053 +                            }
  1.1054 +                        } else {
  1.1055 +                            if (op.hasArg()) { // skip over next string
  1.1056 +                                i++;
  1.1057 +                                continue argLoop;
  1.1058 +                            }
  1.1059 +
  1.1060 +                            if ((options.get("-XclassesAsDecls") != null) &&
  1.1061 +                                (matchPosition == (recognizedOptions.length-1)) ){
  1.1062 +                                // Remove class file names from
  1.1063 +                                // consideration by javac.
  1.1064 +                                if (! args[i].endsWith(".java")) {
  1.1065 +                                    newArgsLength--;
  1.1066 +                                    args[i] = null;
  1.1067 +                                }
  1.1068 +                            }
  1.1069 +                        }
  1.1070 +                    }
  1.1071 +                }
  1.1072 +            }
  1.1073 +
  1.1074 +            String newArgs[] = new String[newArgsLength];
  1.1075 +
  1.1076 +            int j = 0;
  1.1077 +            for(int i=0; i < args.length; i++) {
  1.1078 +                if (args[i] != null)
  1.1079 +                    newArgs[j++] = args[i];
  1.1080 +            }
  1.1081 +
  1.1082 +            if (needClassPath)
  1.1083 +                newArgs[j++] = "-XD-classpath=" + augmentedClassPath;
  1.1084 +
  1.1085 +            if (needSourcePath) {
  1.1086 +                newArgs[j++] = "-XD-sourcepath=" + augmentedSourcePath;
  1.1087 +
  1.1088 +                for(String s: aggregateGenSourceFileNames)
  1.1089 +                    newArgs[j++] = s;
  1.1090 +            }
  1.1091 +
  1.1092 +            returnCode = com.sun.tools.javac.Main.compile(newArgs);
  1.1093 +        }
  1.1094 +
  1.1095 +        return returnCode;
  1.1096 +    }
  1.1097 +
  1.1098 +    /** Programmatic interface for main function.
  1.1099 +     * @param args    The command line parameters.
  1.1100 +     */
  1.1101 +    int compile(String[] args, Context context) {
  1.1102 +        boolean assertionsEnabled = false;
  1.1103 +        assert assertionsEnabled = true;
  1.1104 +        if (!assertionsEnabled) {
  1.1105 +            // Bark.printLines(out, "fatal error: assertions must be enabled when running javac");
  1.1106 +            // return EXIT_ABNORMAL;
  1.1107 +        }
  1.1108 +        int exitCode = EXIT_OK;
  1.1109 +
  1.1110 +        JavaCompiler comp = null;
  1.1111 +        try {
  1.1112 +            context.put(Bark.outKey, out);
  1.1113 +
  1.1114 +            comp = JavaCompiler.instance(context);
  1.1115 +            if (comp == null)
  1.1116 +                return EXIT_SYSERR;
  1.1117 +
  1.1118 +            java.util.List<String> nameList = new java.util.LinkedList<String>();
  1.1119 +            nameList.addAll(sourceFileNames);
  1.1120 +            if (options.get("-XclassesAsDecls") != null)
  1.1121 +                nameList.addAll(classFileNames);
  1.1122 +
  1.1123 +            List<Symbol.ClassSymbol> cs
  1.1124 +                = comp.compile(List.from(nameList.toArray(new String[0])),
  1.1125 +                               origOptions,
  1.1126 +                               aptCL,
  1.1127 +                               providedFactory,
  1.1128 +                               productiveFactories,
  1.1129 +                               aggregateGenFiles);
  1.1130 +
  1.1131 +            /*
  1.1132 +             * If there aren't new source files, we shouldn't bother
  1.1133 +             *  running javac if there were errors.
  1.1134 +             *
  1.1135 +             * If there are new files, we should try running javac in
  1.1136 +             * case there were typing errors.
  1.1137 +             *
  1.1138 +             */
  1.1139 +
  1.1140 +            if (comp.errorCount() != 0 ||
  1.1141 +                options.get("-Werror") != null && comp.warningCount() != 0)
  1.1142 +                return EXIT_ERROR;
  1.1143 +        } catch (IOException ex) {
  1.1144 +            ioMessage(ex);
  1.1145 +            return EXIT_SYSERR;
  1.1146 +        } catch (OutOfMemoryError ex) {
  1.1147 +            resourceMessage(ex);
  1.1148 +            return EXIT_SYSERR;
  1.1149 +        } catch (StackOverflowError ex) {
  1.1150 +            resourceMessage(ex);
  1.1151 +            return EXIT_SYSERR;
  1.1152 +        } catch (FatalError ex) {
  1.1153 +            feMessage(ex);
  1.1154 +            return EXIT_SYSERR;
  1.1155 +        } catch (UsageMessageNeededException umne) {
  1.1156 +            help();
  1.1157 +            return EXIT_CMDERR; // will cause usage message to be printed
  1.1158 +        } catch (AnnotationProcessingError ex) {
  1.1159 +            apMessage(ex);
  1.1160 +            return EXIT_ABNORMAL;
  1.1161 +        } catch (sun.misc.ServiceConfigurationError sce) {
  1.1162 +            sceMessage(sce);
  1.1163 +            return EXIT_ABNORMAL;
  1.1164 +        } catch (Throwable ex) {
  1.1165 +            bugMessage(ex);
  1.1166 +            return EXIT_ABNORMAL;
  1.1167 +        } finally {
  1.1168 +            if (comp != null) {
  1.1169 +                comp.close();
  1.1170 +                genSourceFileNames.addAll(comp.getSourceFileNames());
  1.1171 +                genClassFileNames.addAll(comp.getClassFileNames());
  1.1172 +            }
  1.1173 +            sourceFileNames = new java.util.LinkedList<String>();
  1.1174 +            classFileNames  = new java.util.LinkedList<String>();
  1.1175 +        }
  1.1176 +        return exitCode;
  1.1177 +    }
  1.1178 +
  1.1179 +    /** Print a message reporting an internal error.
  1.1180 +     */
  1.1181 +    void bugMessage(Throwable ex) {
  1.1182 +        Bark.printLines(out, getLocalizedString("msg.bug",
  1.1183 +                                               JavaCompiler.version()));
  1.1184 +        ex.printStackTrace(out);
  1.1185 +    }
  1.1186 +
  1.1187 +    /** Print a message reporting an fatal error.
  1.1188 +     */
  1.1189 +    void apMessage(AnnotationProcessingError ex) {
  1.1190 +        Bark.printLines(out, getLocalizedString("misc.Problem"));
  1.1191 +        ex.getCause().printStackTrace(out);
  1.1192 +    }
  1.1193 +
  1.1194 +    /** Print a message about sun.misc.Service problem.
  1.1195 +     */
  1.1196 +    void sceMessage(sun.misc.ServiceConfigurationError ex) {
  1.1197 +        Bark.printLines(out, getLocalizedString("misc.SunMiscService"));
  1.1198 +        ex.printStackTrace(out);
  1.1199 +    }
  1.1200 +
  1.1201 +    /** Print a message reporting an fatal error.
  1.1202 +     */
  1.1203 +    void feMessage(Throwable ex) {
  1.1204 +        Bark.printLines(out, ex.toString());
  1.1205 +    }
  1.1206 +
  1.1207 +    /** Print a message reporting an input/output error.
  1.1208 +     */
  1.1209 +    void ioMessage(Throwable ex) {
  1.1210 +        Bark.printLines(out, getLocalizedString("msg.io"));
  1.1211 +        ex.printStackTrace(out);
  1.1212 +    }
  1.1213 +
  1.1214 +    /** Print a message reporting an out-of-resources error.
  1.1215 +     */
  1.1216 +    void resourceMessage(Throwable ex) {
  1.1217 +        Bark.printLines(out, getLocalizedString("msg.resource"));
  1.1218 +        ex.printStackTrace(out);
  1.1219 +    }
  1.1220 +
  1.1221 +    /* ************************************************************************
  1.1222 +     * Internationalization
  1.1223 +     *************************************************************************/
  1.1224 +
  1.1225 +    /** Find a localized string in the resource bundle.
  1.1226 +     *  @param key     The key for the localized string.
  1.1227 +     */
  1.1228 +    private static String getLocalizedString(String key, Object... args) {
  1.1229 +        return getText(key, args);
  1.1230 +    }
  1.1231 +
  1.1232 +    private static final String javacRB =
  1.1233 +        "com.sun.tools.javac.resources.javac";
  1.1234 +
  1.1235 +    private static final String aptRB =
  1.1236 +        "com.sun.tools.apt.resources.apt";
  1.1237 +
  1.1238 +    private static ResourceBundle messageRBjavac;
  1.1239 +    private static ResourceBundle messageRBapt;
  1.1240 +
  1.1241 +    /** Initialize ResourceBundle.
  1.1242 +     */
  1.1243 +    private static void initResource() {
  1.1244 +        try {
  1.1245 +            messageRBapt   = ResourceBundle.getBundle(aptRB);
  1.1246 +            messageRBjavac = ResourceBundle.getBundle(javacRB);
  1.1247 +        } catch (MissingResourceException e) {
  1.1248 +            Error x = new FatalError("Fatal Error: Resource for apt or javac is missing");
  1.1249 +            x.initCause(e);
  1.1250 +            throw x;
  1.1251 +        }
  1.1252 +    }
  1.1253 +
  1.1254 +    /** Get and format message string from resource.
  1.1255 +     */
  1.1256 +    private static String getText(String key, Object... _args) {
  1.1257 +        String[] args = new String[_args.length];
  1.1258 +        for (int i=0; i<_args.length; i++) {
  1.1259 +            args[i] = "" + _args[i];
  1.1260 +        }
  1.1261 +        if (messageRBapt == null || messageRBjavac == null )
  1.1262 +            initResource();
  1.1263 +        try {
  1.1264 +            return MessageFormat.format(messageRBapt.getString("apt." + key),
  1.1265 +                                        (Object[]) args);
  1.1266 +        } catch (MissingResourceException e) {
  1.1267 +            try {
  1.1268 +                return MessageFormat.format(messageRBjavac.getString("javac." + key),
  1.1269 +                                            (Object[]) args);
  1.1270 +            } catch (MissingResourceException f) {
  1.1271 +                String msg = "apt or javac message file broken: key={0} "
  1.1272 +                    + "arguments={1}, {2}";
  1.1273 +                return MessageFormat.format(msg, (Object[]) args);
  1.1274 +            }
  1.1275 +        }
  1.1276 +    }
  1.1277 +
  1.1278 +    // Borrowed from DocletInvoker
  1.1279 +    /**
  1.1280 +     * Utility method for converting a search path string to an array
  1.1281 +     * of directory and JAR file URLs.
  1.1282 +     *
  1.1283 +     * @param path the search path string
  1.1284 +     * @return the resulting array of directory and JAR file URLs
  1.1285 +     */
  1.1286 +    static URL[] pathToURLs(String path) {
  1.1287 +        StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
  1.1288 +        URL[] urls = new URL[st.countTokens()];
  1.1289 +        int count = 0;
  1.1290 +        while (st.hasMoreTokens()) {
  1.1291 +            URL url = fileToURL(new File(st.nextToken()));
  1.1292 +            if (url != null) {
  1.1293 +                urls[count++] = url;
  1.1294 +            }
  1.1295 +        }
  1.1296 +        if (urls.length != count) {
  1.1297 +            URL[] tmp = new URL[count];
  1.1298 +            System.arraycopy(urls, 0, tmp, 0, count);
  1.1299 +            urls = tmp;
  1.1300 +        }
  1.1301 +        return urls;
  1.1302 +    }
  1.1303 +
  1.1304 +    /**
  1.1305 +     * Returns the directory or JAR file URL corresponding to the specified
  1.1306 +     * local file name.
  1.1307 +     *
  1.1308 +     * @param file the File object
  1.1309 +     * @return the resulting directory or JAR file URL, or null if unknown
  1.1310 +     */
  1.1311 +    static URL fileToURL(File file) {
  1.1312 +        String name;
  1.1313 +        try {
  1.1314 +            name = file.getCanonicalPath();
  1.1315 +        } catch (IOException e) {
  1.1316 +            name = file.getAbsolutePath();
  1.1317 +        }
  1.1318 +        name = name.replace(File.separatorChar, '/');
  1.1319 +        if (!name.startsWith("/")) {
  1.1320 +            name = "/" + name;
  1.1321 +        }
  1.1322 +        // If the file does not exist, then assume that it's a directory
  1.1323 +        if (!file.isFile()) {
  1.1324 +            name = name + "/";
  1.1325 +        }
  1.1326 +        try {
  1.1327 +            return new URL("file", "", name);
  1.1328 +        } catch (MalformedURLException e) {
  1.1329 +            throw new IllegalArgumentException("file");
  1.1330 +        }
  1.1331 +    }
  1.1332 +}

mercurial