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

Tue, 08 Nov 2011 17:06:58 -0800

author
jjg
date
Tue, 08 Nov 2011 17:06:58 -0800
changeset 1136
ae361e7f435a
parent 1116
d830d28fc72e
permissions
-rw-r--r--

7108669: cleanup Log methods for direct printing to streams
Reviewed-by: mcimadamore

duke@1 1 /*
jjg@1116 2 * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
duke@1 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1 4 *
duke@1 5 * This code is free software; you can redistribute it and/or modify it
duke@1 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
duke@1 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
duke@1 10 *
duke@1 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@1 15 * accompanied this code).
duke@1 16 *
duke@1 17 * You should have received a copy of the GNU General Public License version
duke@1 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@1 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
duke@1 24 */
duke@1 25
duke@1 26 package com.sun.tools.apt.main;
duke@1 27
duke@1 28 import java.io.File;
duke@1 29 import java.io.FileWriter;
duke@1 30 import java.io.IOException;
duke@1 31 import java.io.PrintWriter;
duke@1 32 import java.text.MessageFormat;
duke@1 33 import java.util.ResourceBundle;
duke@1 34 import java.util.MissingResourceException;
duke@1 35 import java.util.StringTokenizer;
duke@1 36 import java.util.Map;
duke@1 37 import java.util.HashMap;
duke@1 38 import java.util.Collections;
duke@1 39
duke@1 40 import java.net.URLClassLoader;
duke@1 41 import java.net.URL;
duke@1 42 import java.net.MalformedURLException;
duke@1 43
jjg@285 44 import javax.tools.JavaFileManager;
jjg@285 45 import javax.tools.StandardLocation;
jjg@285 46
jjg@285 47 import com.sun.tools.javac.file.JavacFileManager;
duke@1 48 import com.sun.tools.javac.code.Source;
duke@1 49 import com.sun.tools.javac.code.Symbol;
duke@1 50 import com.sun.tools.javac.code.Type;
duke@1 51 import com.sun.tools.javac.jvm.Target;
duke@1 52 import com.sun.tools.javac.util.*;
duke@1 53
duke@1 54 import com.sun.tools.apt.comp.AnnotationProcessingError;
duke@1 55 import com.sun.tools.apt.comp.UsageMessageNeededException;
duke@1 56 import com.sun.tools.apt.util.Bark;
duke@1 57 import com.sun.mirror.apt.AnnotationProcessorFactory;
duke@1 58
jjg@1116 59 import static com.sun.tools.javac.file.Locations.pathToURLs;
darcy@497 60
duke@1 61 /** This class provides a commandline interface to the apt build-time
duke@1 62 * tool.
duke@1 63 *
jjg@581 64 * <p><b>This is NOT part of any supported API.
duke@1 65 * If you write code that depends on this, you do so at your own
duke@1 66 * risk. This code and its internal interfaces are subject to change
duke@1 67 * or deletion without notice.</b>
duke@1 68 */
darcy@331 69 @SuppressWarnings("deprecation")
duke@1 70 public class Main {
duke@1 71
duke@1 72 /** For testing: enter any options you want to be set implicitly
duke@1 73 * here.
duke@1 74 */
duke@1 75 static String[] forcedOpts = {
duke@1 76 // Preserve parameter names from class files if the class was
duke@1 77 // compiled with debug enabled
duke@1 78 "-XDsave-parameter-names"
duke@1 79 };
duke@1 80
duke@1 81 /** The name of the compiler, for use in diagnostics.
duke@1 82 */
duke@1 83 String ownName;
duke@1 84
duke@1 85 /** The writer to use for diagnostic output.
duke@1 86 */
duke@1 87 PrintWriter out;
duke@1 88
duke@1 89
duke@1 90 /** Instantiated factory to use in lieu of discovery process.
duke@1 91 */
duke@1 92 AnnotationProcessorFactory providedFactory = null;
duke@1 93
duke@1 94 /** Map representing original command-line arguments.
duke@1 95 */
duke@1 96 Map<String,String> origOptions = new HashMap<String, String>();
duke@1 97
duke@1 98 /** Classloader to use for finding factories.
duke@1 99 */
duke@1 100 ClassLoader aptCL = null;
duke@1 101
duke@1 102 /** Result codes.
duke@1 103 */
duke@1 104 static final int
duke@1 105 EXIT_OK = 0, // Compilation completed with no errors.
duke@1 106 EXIT_ERROR = 1, // Completed but reported errors.
duke@1 107 EXIT_CMDERR = 2, // Bad command-line arguments
duke@1 108 EXIT_SYSERR = 3, // System error or resource exhaustion.
duke@1 109 EXIT_ABNORMAL = 4; // Compiler terminated abnormally
duke@1 110
duke@1 111 /** This class represents an option recognized by the main program
duke@1 112 */
duke@1 113 private class Option {
duke@1 114 /** Whether or not the option is used only aptOnly.
duke@1 115 */
duke@1 116 boolean aptOnly = false;
duke@1 117
duke@1 118 /** Option string.
duke@1 119 */
duke@1 120 String name;
duke@1 121
duke@1 122 /** Documentation key for arguments.
duke@1 123 */
duke@1 124 String argsNameKey;
duke@1 125
duke@1 126 /** Documentation key for description.
duke@1 127 */
duke@1 128 String descrKey;
duke@1 129
duke@1 130 /** Suffix option (-foo=bar or -foo:bar)
duke@1 131 */
duke@1 132 boolean hasSuffix;
duke@1 133
duke@1 134 Option(String name, String argsNameKey, String descrKey) {
duke@1 135 this.name = name;
duke@1 136 this.argsNameKey = argsNameKey;
duke@1 137 this.descrKey = descrKey;
duke@1 138 char lastChar = name.charAt(name.length()-1);
duke@1 139 hasSuffix = lastChar == ':' || lastChar == '=';
duke@1 140 }
duke@1 141 Option(String name, String descrKey) {
duke@1 142 this(name, null, descrKey);
duke@1 143 }
duke@1 144
duke@1 145 public String toString() {
duke@1 146 return name;
duke@1 147 }
duke@1 148
duke@1 149 /** Does this option take a (separate) operand?
duke@1 150 */
duke@1 151 boolean hasArg() {
duke@1 152 return argsNameKey != null && !hasSuffix;
duke@1 153 }
duke@1 154
duke@1 155 /** Does argument string match option pattern?
duke@1 156 * @param arg The command line argument string.
duke@1 157 */
duke@1 158 boolean matches(String arg) {
duke@1 159 return hasSuffix ? arg.startsWith(name) : arg.equals(name);
duke@1 160 }
duke@1 161
duke@1 162 /** For javac-only options, print nothing.
duke@1 163 */
duke@1 164 void help() {
duke@1 165 }
duke@1 166
duke@1 167 String helpSynopsis() {
duke@1 168 return name +
duke@1 169 (argsNameKey == null ? "" :
duke@1 170 ((hasSuffix ? "" : " ") +
duke@1 171 getLocalizedString(argsNameKey)));
duke@1 172 }
duke@1 173
duke@1 174 /** Print a line of documentation describing this option, if non-standard.
duke@1 175 */
duke@1 176 void xhelp() {}
duke@1 177
duke@1 178 /** Process the option (with arg). Return true if error detected.
duke@1 179 */
duke@1 180 boolean process(String option, String arg) {
duke@1 181 options.put(option, arg);
duke@1 182 return false;
duke@1 183 }
duke@1 184
duke@1 185 /** Process the option (without arg). Return true if error detected.
duke@1 186 */
duke@1 187 boolean process(String option) {
duke@1 188 if (hasSuffix)
duke@1 189 return process(name, option.substring(name.length()));
duke@1 190 else
duke@1 191 return process(option, option);
duke@1 192 }
duke@1 193 };
duke@1 194
duke@1 195 private class SharedOption extends Option {
duke@1 196 SharedOption(String name, String argsNameKey, String descrKey) {
duke@1 197 super(name, argsNameKey, descrKey);
duke@1 198 }
duke@1 199
duke@1 200 SharedOption(String name, String descrKey) {
duke@1 201 super(name, descrKey);
duke@1 202 }
duke@1 203
duke@1 204 void help() {
duke@1 205 String s = " " + helpSynopsis();
duke@1 206 out.print(s);
duke@1 207 for (int j = s.length(); j < 29; j++) out.print(" ");
jjg@1136 208 Bark.printRawLines(out, getLocalizedString(descrKey));
duke@1 209 }
duke@1 210
duke@1 211 }
duke@1 212
duke@1 213 private class AptOption extends Option {
duke@1 214 AptOption(String name, String argsNameKey, String descrKey) {
duke@1 215 super(name, argsNameKey, descrKey);
duke@1 216 aptOnly = true;
duke@1 217 }
duke@1 218
duke@1 219 AptOption(String name, String descrKey) {
duke@1 220 super(name, descrKey);
duke@1 221 aptOnly = true;
duke@1 222 }
duke@1 223
duke@1 224 /** Print a line of documentation describing this option, if standard.
duke@1 225 */
duke@1 226 void help() {
duke@1 227 String s = " " + helpSynopsis();
duke@1 228 out.print(s);
duke@1 229 for (int j = s.length(); j < 29; j++) out.print(" ");
jjg@1136 230 Bark.printRawLines(out, getLocalizedString(descrKey));
duke@1 231 }
duke@1 232
duke@1 233 }
duke@1 234
duke@1 235 /** A nonstandard or extended (-X) option
duke@1 236 */
duke@1 237 private class XOption extends Option {
duke@1 238 XOption(String name, String argsNameKey, String descrKey) {
duke@1 239 super(name, argsNameKey, descrKey);
duke@1 240 }
duke@1 241 XOption(String name, String descrKey) {
duke@1 242 this(name, null, descrKey);
duke@1 243 }
duke@1 244 void help() {}
duke@1 245 void xhelp() {}
duke@1 246 };
duke@1 247
duke@1 248 /** A nonstandard or extended (-X) option
duke@1 249 */
duke@1 250 private class AptXOption extends Option {
duke@1 251 AptXOption(String name, String argsNameKey, String descrKey) {
duke@1 252 super(name, argsNameKey, descrKey);
duke@1 253 aptOnly = true;
duke@1 254 }
duke@1 255 AptXOption(String name, String descrKey) {
duke@1 256 this(name, null, descrKey);
duke@1 257 }
duke@1 258 void xhelp() {
duke@1 259 String s = " " + helpSynopsis();
duke@1 260 out.print(s);
duke@1 261 for (int j = s.length(); j < 29; j++) out.print(" ");
jjg@1136 262 Log.printRawLines(out, getLocalizedString(descrKey));
duke@1 263 }
duke@1 264 };
duke@1 265
duke@1 266 /** A hidden (implementor) option
duke@1 267 */
duke@1 268 private class HiddenOption extends Option {
duke@1 269 HiddenOption(String name) {
duke@1 270 super(name, null, null);
duke@1 271 }
duke@1 272 HiddenOption(String name, String argsNameKey) {
duke@1 273 super(name, argsNameKey, null);
duke@1 274 }
duke@1 275 void help() {}
duke@1 276 void xhelp() {}
duke@1 277 };
duke@1 278
duke@1 279 private class AptHiddenOption extends HiddenOption {
duke@1 280 AptHiddenOption(String name) {
duke@1 281 super(name);
duke@1 282 aptOnly = true;
duke@1 283 }
duke@1 284 AptHiddenOption(String name, String argsNameKey) {
duke@1 285 super(name, argsNameKey);
duke@1 286 aptOnly = true;
duke@1 287 }
duke@1 288 }
duke@1 289
duke@1 290 private Option[] recognizedOptions = {
duke@1 291 new Option("-g", "opt.g"),
duke@1 292 new Option("-g:none", "opt.g.none") {
duke@1 293 boolean process(String option) {
duke@1 294 options.put("-g:", "none");
duke@1 295 return false;
duke@1 296 }
duke@1 297 },
duke@1 298
duke@1 299 new Option("-g:{lines,vars,source}", "opt.g.lines.vars.source") {
duke@1 300 boolean matches(String s) {
duke@1 301 return s.startsWith("-g:");
duke@1 302 }
duke@1 303 boolean process(String option) {
duke@1 304 String suboptions = option.substring(3);
duke@1 305 options.put("-g:", suboptions);
duke@1 306 // enter all the -g suboptions as "-g:suboption"
duke@1 307 for (StringTokenizer t = new StringTokenizer(suboptions, ","); t.hasMoreTokens(); ) {
duke@1 308 String tok = t.nextToken();
duke@1 309 String opt = "-g:" + tok;
duke@1 310 options.put(opt, opt);
duke@1 311 }
duke@1 312 return false;
duke@1 313 }
duke@1 314 },
duke@1 315
duke@1 316 new XOption("-Xlint", "opt.Xlint"),
duke@1 317 new XOption("-Xlint:{"
duke@1 318 + "all,"
duke@1 319 + "cast,deprecation,divzero,empty,unchecked,fallthrough,path,serial,finally,overrides,"
duke@1 320 + "-cast,-deprecation,-divzero,-empty,-unchecked,-fallthrough,-path,-serial,-finally,-overrides,"
duke@1 321 + "none}",
duke@1 322 "opt.Xlint.suboptlist") {
duke@1 323 boolean matches(String s) {
duke@1 324 return s.startsWith("-Xlint:");
duke@1 325 }
duke@1 326 boolean process(String option) {
duke@1 327 String suboptions = option.substring(7);
duke@1 328 options.put("-Xlint:", suboptions);
duke@1 329 // enter all the -Xlint suboptions as "-Xlint:suboption"
duke@1 330 for (StringTokenizer t = new StringTokenizer(suboptions, ","); t.hasMoreTokens(); ) {
duke@1 331 String tok = t.nextToken();
duke@1 332 String opt = "-Xlint:" + tok;
duke@1 333 options.put(opt, opt);
duke@1 334 }
duke@1 335 return false;
duke@1 336 }
duke@1 337 },
duke@1 338
duke@1 339 new Option("-nowarn", "opt.nowarn"),
duke@1 340 new Option("-verbose", "opt.verbose"),
duke@1 341
duke@1 342 // -deprecation is retained for command-line backward compatibility
duke@1 343 new Option("-deprecation", "opt.deprecation") {
duke@1 344 boolean process(String option) {
duke@1 345 options.put("-Xlint:deprecation", option);
duke@1 346 return false;
duke@1 347 }
duke@1 348 },
duke@1 349
duke@1 350 new SharedOption("-classpath", "opt.arg.path", "opt.classpath"),
duke@1 351 new SharedOption("-cp", "opt.arg.path", "opt.classpath") {
duke@1 352 boolean process(String option, String arg) {
duke@1 353 return super.process("-classpath", arg);
duke@1 354 }
duke@1 355 },
duke@1 356 new Option("-sourcepath", "opt.arg.path", "opt.sourcepath"),
duke@1 357 new Option("-bootclasspath", "opt.arg.path", "opt.bootclasspath") {
duke@1 358 boolean process(String option, String arg) {
duke@1 359 options.remove("-Xbootclasspath/p:");
duke@1 360 options.remove("-Xbootclasspath/a:");
duke@1 361 return super.process(option, arg);
duke@1 362 }
duke@1 363 },
duke@1 364 new XOption("-Xbootclasspath/p:", "opt.arg.path", "opt.Xbootclasspath.p"),
duke@1 365 new XOption("-Xbootclasspath/a:", "opt.arg.path", "opt.Xbootclasspath.a"),
duke@1 366 new XOption("-Xbootclasspath:", "opt.arg.path", "opt.bootclasspath") {
duke@1 367 boolean process(String option, String arg) {
duke@1 368 options.remove("-Xbootclasspath/p:");
duke@1 369 options.remove("-Xbootclasspath/a:");
duke@1 370 return super.process("-bootclasspath", arg);
duke@1 371 }
duke@1 372 },
duke@1 373 new Option("-extdirs", "opt.arg.dirs", "opt.extdirs"),
duke@1 374 new XOption("-Djava.ext.dirs=", "opt.arg.dirs", "opt.extdirs") {
duke@1 375 boolean process(String option, String arg) {
duke@1 376 return super.process("-extdirs", arg);
duke@1 377 }
duke@1 378 },
duke@1 379 new Option("-endorseddirs", "opt.arg.dirs", "opt.endorseddirs"),
duke@1 380 new XOption("-Djava.endorsed.dirs=","opt.arg.dirs", "opt.endorseddirs") {
duke@1 381 boolean process(String option, String arg) {
duke@1 382 return super.process("-endorseddirs", arg);
duke@1 383 }
duke@1 384 },
duke@1 385 new Option("-proc:{none, only}", "opt.proc.none.only") {
duke@1 386 public boolean matches(String s) {
duke@1 387 return s.equals("-proc:none") || s.equals("-proc:only");
duke@1 388 }
duke@1 389 },
duke@1 390 new Option("-processor", "opt.arg.class", "opt.processor"),
duke@1 391 new Option("-processorpath", "opt.arg.path", "opt.processorpath"),
duke@1 392
duke@1 393 new SharedOption("-d", "opt.arg.path", "opt.d"),
duke@1 394 new SharedOption("-s", "opt.arg.path", "opt.s"),
duke@1 395 new Option("-encoding", "opt.arg.encoding", "opt.encoding"),
duke@1 396 new SharedOption("-source", "opt.arg.release", "opt.source") {
duke@1 397 boolean process(String option, String operand) {
duke@1 398 Source source = Source.lookup(operand);
duke@1 399 if (source == null) {
duke@1 400 error("err.invalid.source", operand);
duke@1 401 return true;
duke@1 402 } else if (source.compareTo(Source.JDK1_5) > 0) {
duke@1 403 error("err.unsupported.source.version", operand);
duke@1 404 return true;
duke@1 405 }
duke@1 406 return super.process(option, operand);
duke@1 407 }
duke@1 408 },
duke@1 409 new Option("-target", "opt.arg.release", "opt.target") {
duke@1 410 boolean process(String option, String operand) {
duke@1 411 Target target = Target.lookup(operand);
duke@1 412 if (target == null) {
duke@1 413 error("err.invalid.target", operand);
duke@1 414 return true;
duke@1 415 } else if (target.compareTo(Target.JDK1_5) > 0) {
duke@1 416 error("err.unsupported.target.version", operand);
duke@1 417 return true;
duke@1 418 }
duke@1 419 return super.process(option, operand);
duke@1 420 }
duke@1 421 },
duke@1 422 new AptOption("-version", "opt.version") {
duke@1 423 boolean process(String option) {
jjg@1136 424 Bark.printRawLines(out, ownName + " " + AptJavaCompiler.version());
duke@1 425 return super.process(option);
duke@1 426 }
duke@1 427 },
duke@1 428 new HiddenOption("-fullversion"),
duke@1 429 new AptOption("-help", "opt.help") {
duke@1 430 boolean process(String option) {
duke@1 431 Main.this.help();
duke@1 432 return super.process(option);
duke@1 433 }
duke@1 434 },
duke@1 435 new SharedOption("-X", "opt.X") {
duke@1 436 boolean process(String option) {
duke@1 437 Main.this.xhelp();
duke@1 438 return super.process(option);
duke@1 439 }
duke@1 440 },
duke@1 441
duke@1 442 // This option exists only for the purpose of documenting itself.
duke@1 443 // It's actually implemented by the launcher.
duke@1 444 new AptOption("-J", "opt.arg.flag", "opt.J") {
duke@1 445 String helpSynopsis() {
duke@1 446 hasSuffix = true;
duke@1 447 return super.helpSynopsis();
duke@1 448 }
duke@1 449 boolean process(String option) {
duke@1 450 throw new AssertionError
duke@1 451 ("the -J flag should be caught by the launcher.");
duke@1 452 }
duke@1 453 },
duke@1 454
duke@1 455
duke@1 456 new SharedOption("-A", "opt.proc.flag", "opt.A") {
duke@1 457 String helpSynopsis() {
duke@1 458 hasSuffix = true;
duke@1 459 return super.helpSynopsis();
duke@1 460 }
duke@1 461
duke@1 462 boolean matches(String arg) {
duke@1 463 return arg.startsWith("-A");
duke@1 464 }
duke@1 465
duke@1 466 boolean hasArg() {
duke@1 467 return false;
duke@1 468 }
duke@1 469
duke@1 470 boolean process(String option) {
duke@1 471 return process(option, option);
duke@1 472 }
duke@1 473 },
duke@1 474
duke@1 475 new AptOption("-nocompile", "opt.nocompile"),
duke@1 476
duke@1 477 new AptOption("-print", "opt.print"),
duke@1 478
duke@1 479 new AptOption("-factorypath", "opt.arg.path", "opt.factorypath"),
duke@1 480
duke@1 481 new AptOption("-factory", "opt.arg.class", "opt.factory"),
duke@1 482
duke@1 483 new AptXOption("-XListAnnotationTypes", "opt.XListAnnotationTypes"),
duke@1 484
duke@1 485 new AptXOption("-XListDeclarations", "opt.XListDeclarations"),
duke@1 486
duke@1 487 new AptXOption("-XPrintAptRounds", "opt.XPrintAptRounds"),
duke@1 488
duke@1 489 new AptXOption("-XPrintFactoryInfo", "opt.XPrintFactoryInfo"),
duke@1 490
duke@1 491 /*
duke@1 492 * Option to treat both classes and source files as
duke@1 493 * declarations that can be given on the command line and
duke@1 494 * processed as the result of an apt round.
duke@1 495 */
duke@1 496 new AptXOption("-XclassesAsDecls", "opt.XClassesAsDecls"),
duke@1 497
duke@1 498 // new Option("-moreinfo", "opt.moreinfo") {
duke@1 499 new HiddenOption("-moreinfo") {
duke@1 500 boolean process(String option) {
duke@1 501 Type.moreInfo = true;
duke@1 502 return super.process(option);
duke@1 503 }
duke@1 504 },
duke@1 505
duke@1 506 // treat warnings as errors
duke@1 507 new HiddenOption("-Werror"),
duke@1 508
duke@1 509 // use complex inference from context in the position of a method call argument
duke@1 510 new HiddenOption("-complexinference"),
duke@1 511
duke@1 512 // prompt after each error
duke@1 513 // new Option("-prompt", "opt.prompt"),
duke@1 514 new HiddenOption("-prompt"),
duke@1 515
duke@1 516 // dump stack on error
duke@1 517 new HiddenOption("-doe"),
duke@1 518
duke@1 519 // display warnings for generic unchecked and unsafe operations
duke@1 520 new HiddenOption("-warnunchecked") {
duke@1 521 boolean process(String option) {
duke@1 522 options.put("-Xlint:unchecked", option);
duke@1 523 return false;
duke@1 524 }
duke@1 525 },
duke@1 526
duke@1 527 new HiddenOption("-Xswitchcheck") {
duke@1 528 boolean process(String option) {
duke@1 529 options.put("-Xlint:switchcheck", option);
duke@1 530 return false;
duke@1 531 }
duke@1 532 },
duke@1 533
duke@1 534 // generate trace output for subtyping operations
duke@1 535 new HiddenOption("-debugsubtyping"),
duke@1 536
duke@1 537 new XOption("-Xmaxerrs", "opt.arg.number", "opt.maxerrs"),
duke@1 538 new XOption("-Xmaxwarns", "opt.arg.number", "opt.maxwarns"),
duke@1 539 new XOption("-Xstdout", "opt.arg.file", "opt.Xstdout") {
duke@1 540 boolean process(String option, String arg) {
duke@1 541 try {
duke@1 542 out = new PrintWriter(new FileWriter(arg), true);
duke@1 543 } catch (java.io.IOException e) {
duke@1 544 error("err.error.writing.file", arg, e);
duke@1 545 return true;
duke@1 546 }
duke@1 547 return super.process(option, arg);
duke@1 548 }
duke@1 549 },
duke@1 550
duke@1 551 new XOption("-Xprint", "opt.print"),
duke@1 552
duke@1 553 new XOption("-XprintRounds", "opt.printRounds"),
duke@1 554
duke@1 555 new XOption("-XprintProcessorInfo", "opt.printProcessorInfo"),
duke@1 556
duke@1 557
duke@1 558 /* -O is a no-op, accepted for backward compatibility. */
duke@1 559 new HiddenOption("-O"),
duke@1 560
duke@1 561 /* -Xjcov produces tables to support the code coverage tool jcov. */
duke@1 562 new HiddenOption("-Xjcov"),
duke@1 563
duke@1 564 /* This is a back door to the compiler's option table.
duke@1 565 * -Dx=y sets the option x to the value y.
duke@1 566 * -Dx sets the option x to the value x.
duke@1 567 */
duke@1 568 new HiddenOption("-XD") {
duke@1 569 String s;
duke@1 570 boolean matches(String s) {
duke@1 571 this.s = s;
duke@1 572 return s.startsWith(name);
duke@1 573 }
duke@1 574 boolean process(String option) {
duke@1 575 s = s.substring(name.length());
duke@1 576 int eq = s.indexOf('=');
duke@1 577 String key = (eq < 0) ? s : s.substring(0, eq);
duke@1 578 String value = (eq < 0) ? s : s.substring(eq+1);
duke@1 579 options.put(key, value);
duke@1 580 return false;
duke@1 581 }
duke@1 582 },
duke@1 583
duke@1 584 new HiddenOption("sourcefile") {
duke@1 585 String s;
duke@1 586 boolean matches(String s) {
duke@1 587 this.s = s;
duke@1 588 return s.endsWith(".java") ||
duke@1 589 (options.get("-XclassesAsDecls") != null);
duke@1 590 }
duke@1 591 boolean process(String option) {
duke@1 592 if (s.endsWith(".java")) {
duke@1 593 if (!sourceFileNames.contains(s))
duke@1 594 sourceFileNames.add(s);
duke@1 595 } else if (options.get("-XclassesAsDecls") != null) {
duke@1 596 classFileNames.add(s);
duke@1 597 }
duke@1 598 return false;
duke@1 599 }
duke@1 600 },
duke@1 601 };
duke@1 602
duke@1 603 /**
duke@1 604 * Construct a compiler instance.
duke@1 605 */
duke@1 606 public Main(String name) {
duke@1 607 this(name, new PrintWriter(System.err, true));
duke@1 608 }
duke@1 609
duke@1 610 /**
duke@1 611 * Construct a compiler instance.
duke@1 612 */
duke@1 613 public Main(String name, PrintWriter out) {
duke@1 614 this.ownName = name;
duke@1 615 this.out = out;
duke@1 616 }
duke@1 617
duke@1 618 /** A table of all options that's passed to the JavaCompiler constructor. */
duke@1 619 private Options options = null;
duke@1 620
duke@1 621 /** The list of source files to process
duke@1 622 */
duke@1 623 java.util.List<String> sourceFileNames = new java.util.LinkedList<String>();
duke@1 624
duke@1 625 /** The list of class files to process
duke@1 626 */
duke@1 627 java.util.List<String> classFileNames = new java.util.LinkedList<String>();
duke@1 628
duke@1 629 /** List of top level names of generated source files from most recent apt round.
duke@1 630 */
duke@1 631 java.util.Set<String> genSourceFileNames = new java.util.LinkedHashSet<String>();
duke@1 632
duke@1 633 /** List of names of generated class files from most recent apt round.
duke@1 634 */
duke@1 635 java.util.Set<String> genClassFileNames = new java.util.LinkedHashSet<String>();
duke@1 636
duke@1 637 /**
duke@1 638 * List of all the generated source file names across all apt rounds.
duke@1 639 */
duke@1 640 java.util.Set<String> aggregateGenSourceFileNames = new java.util.LinkedHashSet<String>();
duke@1 641
duke@1 642 /**
duke@1 643 * List of all the generated class file names across all apt rounds.
duke@1 644 */
duke@1 645 java.util.Set<String> aggregateGenClassFileNames = new java.util.LinkedHashSet<String>();
duke@1 646
duke@1 647 /**
duke@1 648 * List of all the generated file names across all apt rounds.
duke@1 649 */
duke@1 650 java.util.Set<java.io.File> aggregateGenFiles = new java.util.LinkedHashSet<java.io.File>();
duke@1 651
duke@1 652 /**
duke@1 653 * Set of all factories that have provided a processor on some apt round.
duke@1 654 */
duke@1 655 java.util.Set<Class<? extends AnnotationProcessorFactory> > productiveFactories =
duke@1 656 new java.util.LinkedHashSet<Class<? extends AnnotationProcessorFactory> >();
duke@1 657
duke@1 658
duke@1 659
duke@1 660 /** Print a string that explains usage.
duke@1 661 */
duke@1 662 void help() {
jjg@1136 663 Bark.printRawLines(out, getLocalizedString("msg.usage.header", ownName));
duke@1 664 for (int i=0; i < recognizedOptions.length; i++) {
duke@1 665 recognizedOptions[i].help();
duke@1 666 }
jjg@1136 667 Bark.printRawLines(out, getLocalizedString("msg.usage.footer"));
duke@1 668 out.println();
duke@1 669 }
duke@1 670
duke@1 671 /** Print a string that explains usage for X options.
duke@1 672 */
duke@1 673 void xhelp() {
duke@1 674 for (int i=0; i<recognizedOptions.length; i++) {
duke@1 675 recognizedOptions[i].xhelp();
duke@1 676 }
duke@1 677 out.println();
jjg@1136 678 Bark.printRawLines(out, getLocalizedString("msg.usage.nonstandard.footer"));
duke@1 679 }
duke@1 680
duke@1 681 /** Report a usage error.
duke@1 682 */
duke@1 683 void error(String key, Object... args) {
duke@1 684 warning(key, args);
duke@1 685 help();
duke@1 686 }
duke@1 687
duke@1 688 /** Report a warning.
duke@1 689 */
duke@1 690 void warning(String key, Object... args) {
jjg@1136 691 Bark.printRawLines(out, ownName + ": "
duke@1 692 + getLocalizedString(key, args));
duke@1 693 }
duke@1 694
duke@1 695 /** Process command line arguments: store all command line options
duke@1 696 * in `options' table and return all source filenames.
duke@1 697 * @param args The array of command line arguments.
duke@1 698 */
duke@1 699 protected java.util.List<String> processArgs(String[] flags) {
duke@1 700 int ac = 0;
duke@1 701 while (ac < flags.length) {
duke@1 702 String flag = flags[ac];
duke@1 703 ac++;
duke@1 704
duke@1 705 int j;
duke@1 706 for (j=0; j < recognizedOptions.length; j++)
duke@1 707 if (recognizedOptions[j].matches(flag))
duke@1 708 break;
duke@1 709
duke@1 710 if (j == recognizedOptions.length) {
duke@1 711 error("err.invalid.flag", flag);
duke@1 712 return null;
duke@1 713 }
duke@1 714
duke@1 715 Option option = recognizedOptions[j];
duke@1 716 if (option.hasArg()) {
duke@1 717 if (ac == flags.length) {
duke@1 718 error("err.req.arg", flag);
duke@1 719 return null;
duke@1 720 }
duke@1 721 String operand = flags[ac];
duke@1 722 ac++;
duke@1 723 if (option.process(flag, operand))
duke@1 724 return null;
duke@1 725 } else {
duke@1 726 if (option.process(flag))
duke@1 727 return null;
duke@1 728 }
duke@1 729 }
duke@1 730
duke@1 731 String sourceString = options.get("-source");
duke@1 732 Source source = (sourceString != null)
duke@1 733 ? Source.lookup(sourceString)
duke@1 734 : Source.JDK1_5; // JDK 5 is the latest supported source version
duke@1 735 String targetString = options.get("-target");
duke@1 736 Target target = (targetString != null)
duke@1 737 ? Target.lookup(targetString)
duke@1 738 : Target.JDK1_5; // JDK 5 is the latest supported source version
duke@1 739 // We don't check source/target consistency for CLDC, as J2ME
duke@1 740 // profiles are not aligned with J2SE targets; moreover, a
duke@1 741 // single CLDC target may have many profiles. In addition,
duke@1 742 // this is needed for the continued functioning of the JSR14
duke@1 743 // prototype.
duke@1 744 if (Character.isDigit(target.name.charAt(0)) &&
duke@1 745 target.compareTo(source.requiredTarget()) < 0) {
duke@1 746 if (targetString != null) {
duke@1 747 if (sourceString == null) {
duke@1 748 warning("warn.target.default.source.conflict",
duke@1 749 targetString,
duke@1 750 source.requiredTarget().name);
duke@1 751 } else {
duke@1 752 warning("warn.source.target.conflict",
duke@1 753 sourceString,
duke@1 754 source.requiredTarget().name);
duke@1 755 }
duke@1 756 return null;
duke@1 757 } else {
duke@1 758 options.put("-target", source.requiredTarget().name);
duke@1 759 }
duke@1 760 }
duke@1 761 return sourceFileNames;
duke@1 762 }
duke@1 763
duke@1 764 /** Programmatic interface for main function.
duke@1 765 * @param args The command line parameters.
duke@1 766 */
duke@1 767 public int compile(String[] args, AnnotationProcessorFactory factory) {
duke@1 768 int returnCode = 0;
duke@1 769 providedFactory = factory;
duke@1 770
duke@1 771 Context context = new Context();
jjg@285 772 JavacFileManager.preRegister(context);
duke@1 773 options = Options.instance(context);
duke@1 774 Bark bark;
duke@1 775
duke@1 776 /*
duke@1 777 * Process the command line options to create the intial
duke@1 778 * options data. This processing is at least partially reused
duke@1 779 * by any recursive apt calls.
duke@1 780 */
duke@1 781
duke@1 782 // For testing: assume all arguments in forcedOpts are
duke@1 783 // prefixed to command line arguments.
duke@1 784 processArgs(forcedOpts);
duke@1 785
duke@1 786 /*
duke@1 787 * A run of apt only gets passed the most recently generated
duke@1 788 * files; the initial run of apt gets passed the files from
duke@1 789 * the command line.
duke@1 790 */
duke@1 791
duke@1 792 java.util.List<String> origFilenames;
duke@1 793 try {
duke@1 794 // assign args the result of parse to capture results of
duke@1 795 // '@file' expansion
duke@1 796 origFilenames = processArgs((args=CommandLine.parse(args)));
darcy@331 797
darcy@331 798 if (options.get("suppress-tool-api-removal-message") == null) {
jjg@1136 799 Bark.printRawLines(out, getLocalizedString("misc.Deprecation"));
darcy@331 800 }
darcy@331 801
duke@1 802 if (origFilenames == null) {
duke@1 803 return EXIT_CMDERR;
duke@1 804 } else if (origFilenames.size() == 0) {
duke@1 805 // it is allowed to compile nothing if just asking for help
duke@1 806 if (options.get("-help") != null ||
duke@1 807 options.get("-X") != null)
duke@1 808 return EXIT_OK;
duke@1 809 }
duke@1 810 } catch (java.io.FileNotFoundException e) {
jjg@1136 811 Bark.printRawLines(out, ownName + ": " +
duke@1 812 getLocalizedString("err.file.not.found",
duke@1 813 e.getMessage()));
duke@1 814 return EXIT_SYSERR;
duke@1 815 } catch (IOException ex) {
duke@1 816 ioMessage(ex);
duke@1 817 return EXIT_SYSERR;
duke@1 818 } catch (OutOfMemoryError ex) {
duke@1 819 resourceMessage(ex);
duke@1 820 return EXIT_SYSERR;
duke@1 821 } catch (StackOverflowError ex) {
duke@1 822 resourceMessage(ex);
duke@1 823 return EXIT_SYSERR;
duke@1 824 } catch (FatalError ex) {
duke@1 825 feMessage(ex);
duke@1 826 return EXIT_SYSERR;
duke@1 827 } catch (sun.misc.ServiceConfigurationError sce) {
duke@1 828 sceMessage(sce);
duke@1 829 return EXIT_ABNORMAL;
duke@1 830 } catch (Throwable ex) {
duke@1 831 bugMessage(ex);
duke@1 832 return EXIT_ABNORMAL;
duke@1 833 }
duke@1 834
duke@1 835
duke@1 836 boolean firstRound = true;
duke@1 837 boolean needSourcePath = false;
duke@1 838 boolean needClassPath = false;
duke@1 839 boolean classesAsDecls = options.get("-XclassesAsDecls") != null;
duke@1 840
duke@1 841 /*
duke@1 842 * Create augumented classpath and sourcepath values.
duke@1 843 *
duke@1 844 * If any of the prior apt rounds generated any new source
duke@1 845 * files, the n'th apt round (and any javac invocation) has the
duke@1 846 * source destination path ("-s path") as the last element of
duke@1 847 * the "-sourcepath" to the n'th call.
duke@1 848 *
duke@1 849 * If any of the prior apt rounds generated any new class files,
duke@1 850 * the n'th apt round (and any javac invocation) has the class
duke@1 851 * destination path ("-d path") as the last element of the
duke@1 852 * "-classpath" to the n'th call.
duke@1 853 */
duke@1 854 String augmentedSourcePath = "";
duke@1 855 String augmentedClassPath = "";
duke@1 856 String baseClassPath = "";
duke@1 857
duke@1 858 try {
duke@1 859 /*
duke@1 860 * Record original options for future annotation processor
duke@1 861 * invocations.
duke@1 862 */
duke@1 863 origOptions = new HashMap<String, String>(options.size());
duke@1 864 for(String s: options.keySet()) {
duke@1 865 String value;
duke@1 866 if (s.equals(value = options.get(s)))
duke@1 867 origOptions.put(s, (String)null);
duke@1 868 else
duke@1 869 origOptions.put(s, value);
duke@1 870 }
duke@1 871 origOptions = Collections.unmodifiableMap(origOptions);
duke@1 872
jjg@285 873 JavacFileManager fm = (JavacFileManager) context.get(JavaFileManager.class);
duke@1 874 {
duke@1 875 // Note: it might be necessary to check for an empty
duke@1 876 // component ("") of the source path or class path
duke@1 877
duke@1 878 String sourceDest = options.get("-s");
jjg@285 879 if (fm.hasLocation(StandardLocation.SOURCE_PATH)) {
jjg@285 880 for(File f: fm.getLocation(StandardLocation.SOURCE_PATH))
duke@1 881 augmentedSourcePath += (f + File.pathSeparator);
duke@1 882 augmentedSourcePath += (sourceDest == null)?".":sourceDest;
duke@1 883 } else {
duke@1 884 augmentedSourcePath = ".";
duke@1 885
duke@1 886 if (sourceDest != null)
duke@1 887 augmentedSourcePath += (File.pathSeparator + sourceDest);
duke@1 888 }
duke@1 889
duke@1 890 String classDest = options.get("-d");
jjg@285 891 if (fm.hasLocation(StandardLocation.CLASS_PATH)) {
jjg@285 892 for(File f: fm.getLocation(StandardLocation.CLASS_PATH))
duke@1 893 baseClassPath += (f + File.pathSeparator);
duke@1 894 // put baseClassPath into map to handle any
duke@1 895 // value needed for the classloader
duke@1 896 options.put("-classpath", baseClassPath);
duke@1 897
duke@1 898 augmentedClassPath = baseClassPath + ((classDest == null)?".":classDest);
duke@1 899 } else {
duke@1 900 baseClassPath = ".";
duke@1 901 if (classDest != null)
duke@1 902 augmentedClassPath = baseClassPath + (File.pathSeparator + classDest);
duke@1 903 }
duke@1 904 assert options.get("-classpath") != null;
duke@1 905 }
duke@1 906
duke@1 907 /*
duke@1 908 * Create base and augmented class loaders
duke@1 909 */
duke@1 910 ClassLoader augmentedAptCL = null;
duke@1 911 {
duke@1 912 /*
duke@1 913 * Use a url class loader to look for classes on the
duke@1 914 * user-specified class path. Prepend computed bootclass
duke@1 915 * path, which includes extdirs, to the URLClassLoader apt
duke@1 916 * uses.
duke@1 917 */
duke@1 918 String aptclasspath = "";
duke@1 919 String bcp = "";
jjg@285 920 Iterable<? extends File> bootclasspath = fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH);
duke@1 921
duke@1 922 if (bootclasspath != null) {
duke@1 923 for(File f: bootclasspath)
duke@1 924 bcp += (f + File.pathSeparator);
duke@1 925 }
duke@1 926
duke@1 927 // If the factory path is set, use that path
duke@1 928 if (providedFactory == null)
duke@1 929 aptclasspath = options.get("-factorypath");
duke@1 930 if (aptclasspath == null)
duke@1 931 aptclasspath = options.get("-classpath");
duke@1 932
duke@1 933 assert aptclasspath != null;
duke@1 934 aptclasspath = (bcp + aptclasspath);
duke@1 935 aptCL = new URLClassLoader(pathToURLs(aptclasspath));
duke@1 936
duke@1 937 if (providedFactory == null &&
duke@1 938 options.get("-factorypath") != null) // same CL even if new class files written
duke@1 939 augmentedAptCL = aptCL;
duke@1 940 else {
duke@1 941 // Create class loader in case new class files are
duke@1 942 // written
duke@1 943 augmentedAptCL = new URLClassLoader(pathToURLs(augmentedClassPath.
duke@1 944 substring(baseClassPath.length())),
duke@1 945 aptCL);
duke@1 946 }
duke@1 947 }
duke@1 948
duke@1 949 int round = 0; // For -XPrintAptRounds
duke@1 950 do {
duke@1 951 round++;
duke@1 952
duke@1 953 Context newContext = new Context();
duke@1 954 Options newOptions = Options.instance(newContext); // creates a new context
duke@1 955 newOptions.putAll(options);
duke@1 956
duke@1 957 // populate with old options... don't bother reparsing command line, etc.
duke@1 958
duke@1 959 // if genSource files, must add destination to source path
duke@1 960 if (genSourceFileNames.size() > 0 && !firstRound) {
duke@1 961 newOptions.put("-sourcepath", augmentedSourcePath);
duke@1 962 needSourcePath = true;
duke@1 963 }
duke@1 964 aggregateGenSourceFileNames.addAll(genSourceFileNames);
duke@1 965 sourceFileNames.addAll(genSourceFileNames);
duke@1 966 genSourceFileNames.clear();
duke@1 967
duke@1 968 // Don't really need to track this; just have to add -d
duke@1 969 // "foo" to class path if any class files are generated
duke@1 970 if (genClassFileNames.size() > 0) {
duke@1 971 newOptions.put("-classpath", augmentedClassPath);
duke@1 972 aptCL = augmentedAptCL;
duke@1 973 needClassPath = true;
duke@1 974 }
duke@1 975 aggregateGenClassFileNames.addAll(genClassFileNames);
duke@1 976 classFileNames.addAll(genClassFileNames);
duke@1 977 genClassFileNames.clear();
duke@1 978
duke@1 979 options = newOptions;
duke@1 980
duke@1 981 if (options.get("-XPrintAptRounds") != null) {
duke@1 982 out.println("apt Round : " + round);
duke@1 983 out.println("filenames: " + sourceFileNames);
duke@1 984 if (classesAsDecls)
duke@1 985 out.println("classnames: " + classFileNames);
duke@1 986 out.println("options: " + options);
duke@1 987 }
duke@1 988
duke@1 989 returnCode = compile(args, newContext);
duke@1 990 firstRound = false;
duke@1 991
duke@1 992 // Check for reported errors before continuing
duke@1 993 bark = Bark.instance(newContext);
duke@1 994 } while(((genSourceFileNames.size() != 0 ) ||
duke@1 995 (classesAsDecls && genClassFileNames.size() != 0)) &&
duke@1 996 bark.nerrors == 0);
duke@1 997 } catch (UsageMessageNeededException umne) {
duke@1 998 help();
duke@1 999 return EXIT_CMDERR; // will cause usage message to be printed
duke@1 1000 }
duke@1 1001
duke@1 1002 /*
duke@1 1003 * Do not compile if a processor has reported an error or if
duke@1 1004 * there are no source files to process. A more sophisticated
duke@1 1005 * test would also fail for syntax errors caught by javac.
duke@1 1006 */
duke@1 1007 if (options.get("-nocompile") == null &&
duke@1 1008 options.get("-print") == null &&
duke@1 1009 bark.nerrors == 0 &&
duke@1 1010 (origFilenames.size() > 0 || aggregateGenSourceFileNames.size() > 0 )) {
duke@1 1011 /*
duke@1 1012 * Need to create new argument string for calling javac:
duke@1 1013 * 1. apt specific arguments (e.g. -factory) must be stripped out
duke@1 1014 * 2. proper settings for sourcepath and classpath must be used
duke@1 1015 * 3. generated class names must be added
duke@1 1016 * 4. class file names as declarations must be removed
duke@1 1017 */
duke@1 1018
duke@1 1019 int newArgsLength = args.length +
duke@1 1020 (needSourcePath?1:0) +
duke@1 1021 (needClassPath?1:0) +
duke@1 1022 aggregateGenSourceFileNames.size();
duke@1 1023
duke@1 1024 // Null out apt-specific options and don't copy over into
duke@1 1025 // newArgs. This loop should be a lot faster; the options
duke@1 1026 // array should be replaced with a better data structure
duke@1 1027 // which includes a map from strings to options.
duke@1 1028 //
duke@1 1029 // If treating classes as declarations, must strip out
duke@1 1030 // class names from the javac argument list
duke@1 1031 argLoop:
duke@1 1032 for(int i = 0; i < args.length; i++) {
duke@1 1033 int matchPosition = -1;
duke@1 1034
duke@1 1035 // "-A" by itself is recognized by apt but not javac
duke@1 1036 if (args[i] != null && args[i].equals("-A")) {
duke@1 1037 newArgsLength--;
duke@1 1038 args[i] = null;
duke@1 1039 continue argLoop;
duke@1 1040 } else {
duke@1 1041 optionLoop:
duke@1 1042 for(int j = 0; j < recognizedOptions.length; j++) {
duke@1 1043 if (args[i] != null && recognizedOptions[j].matches(args[i])) {
duke@1 1044 matchPosition = j;
duke@1 1045 break optionLoop;
duke@1 1046 }
duke@1 1047 }
duke@1 1048
duke@1 1049 if (matchPosition != -1) {
duke@1 1050 Option op = recognizedOptions[matchPosition];
duke@1 1051 if (op.aptOnly) {
duke@1 1052 newArgsLength--;
duke@1 1053 args[i] = null;
duke@1 1054 if (op.hasArg()) {
duke@1 1055 newArgsLength--;
duke@1 1056 args[i+1] = null;
duke@1 1057 }
duke@1 1058 } else {
duke@1 1059 if (op.hasArg()) { // skip over next string
duke@1 1060 i++;
duke@1 1061 continue argLoop;
duke@1 1062 }
duke@1 1063
duke@1 1064 if ((options.get("-XclassesAsDecls") != null) &&
duke@1 1065 (matchPosition == (recognizedOptions.length-1)) ){
duke@1 1066 // Remove class file names from
duke@1 1067 // consideration by javac.
duke@1 1068 if (! args[i].endsWith(".java")) {
duke@1 1069 newArgsLength--;
duke@1 1070 args[i] = null;
duke@1 1071 }
duke@1 1072 }
duke@1 1073 }
duke@1 1074 }
duke@1 1075 }
duke@1 1076 }
duke@1 1077
duke@1 1078 String newArgs[] = new String[newArgsLength];
duke@1 1079
duke@1 1080 int j = 0;
duke@1 1081 for(int i=0; i < args.length; i++) {
duke@1 1082 if (args[i] != null)
duke@1 1083 newArgs[j++] = args[i];
duke@1 1084 }
duke@1 1085
duke@1 1086 if (needClassPath)
duke@1 1087 newArgs[j++] = "-XD-classpath=" + augmentedClassPath;
duke@1 1088
duke@1 1089 if (needSourcePath) {
duke@1 1090 newArgs[j++] = "-XD-sourcepath=" + augmentedSourcePath;
duke@1 1091
duke@1 1092 for(String s: aggregateGenSourceFileNames)
duke@1 1093 newArgs[j++] = s;
duke@1 1094 }
duke@1 1095
duke@1 1096 returnCode = com.sun.tools.javac.Main.compile(newArgs);
duke@1 1097 }
duke@1 1098
duke@1 1099 return returnCode;
duke@1 1100 }
duke@1 1101
duke@1 1102 /** Programmatic interface for main function.
duke@1 1103 * @param args The command line parameters.
duke@1 1104 */
duke@1 1105 int compile(String[] args, Context context) {
duke@1 1106 boolean assertionsEnabled = false;
duke@1 1107 assert assertionsEnabled = true;
duke@1 1108 if (!assertionsEnabled) {
duke@1 1109 // Bark.printLines(out, "fatal error: assertions must be enabled when running javac");
duke@1 1110 // return EXIT_ABNORMAL;
duke@1 1111 }
duke@1 1112 int exitCode = EXIT_OK;
duke@1 1113
jjg@789 1114 AptJavaCompiler comp = null;
duke@1 1115 try {
duke@1 1116 context.put(Bark.outKey, out);
duke@1 1117
jjg@789 1118 comp = AptJavaCompiler.instance(context);
duke@1 1119 if (comp == null)
duke@1 1120 return EXIT_SYSERR;
duke@1 1121
duke@1 1122 java.util.List<String> nameList = new java.util.LinkedList<String>();
duke@1 1123 nameList.addAll(sourceFileNames);
duke@1 1124 if (options.get("-XclassesAsDecls") != null)
duke@1 1125 nameList.addAll(classFileNames);
duke@1 1126
duke@1 1127 List<Symbol.ClassSymbol> cs
duke@1 1128 = comp.compile(List.from(nameList.toArray(new String[0])),
duke@1 1129 origOptions,
duke@1 1130 aptCL,
duke@1 1131 providedFactory,
duke@1 1132 productiveFactories,
duke@1 1133 aggregateGenFiles);
duke@1 1134
duke@1 1135 /*
duke@1 1136 * If there aren't new source files, we shouldn't bother
duke@1 1137 * running javac if there were errors.
duke@1 1138 *
duke@1 1139 * If there are new files, we should try running javac in
duke@1 1140 * case there were typing errors.
duke@1 1141 *
duke@1 1142 */
duke@1 1143
duke@1 1144 if (comp.errorCount() != 0 ||
duke@1 1145 options.get("-Werror") != null && comp.warningCount() != 0)
duke@1 1146 return EXIT_ERROR;
duke@1 1147 } catch (IOException ex) {
duke@1 1148 ioMessage(ex);
duke@1 1149 return EXIT_SYSERR;
duke@1 1150 } catch (OutOfMemoryError ex) {
duke@1 1151 resourceMessage(ex);
duke@1 1152 return EXIT_SYSERR;
duke@1 1153 } catch (StackOverflowError ex) {
duke@1 1154 resourceMessage(ex);
duke@1 1155 return EXIT_SYSERR;
duke@1 1156 } catch (FatalError ex) {
duke@1 1157 feMessage(ex);
duke@1 1158 return EXIT_SYSERR;
duke@1 1159 } catch (UsageMessageNeededException umne) {
duke@1 1160 help();
duke@1 1161 return EXIT_CMDERR; // will cause usage message to be printed
duke@1 1162 } catch (AnnotationProcessingError ex) {
duke@1 1163 apMessage(ex);
duke@1 1164 return EXIT_ABNORMAL;
duke@1 1165 } catch (sun.misc.ServiceConfigurationError sce) {
duke@1 1166 sceMessage(sce);
duke@1 1167 return EXIT_ABNORMAL;
duke@1 1168 } catch (Throwable ex) {
duke@1 1169 bugMessage(ex);
duke@1 1170 return EXIT_ABNORMAL;
duke@1 1171 } finally {
duke@1 1172 if (comp != null) {
duke@1 1173 comp.close();
duke@1 1174 genSourceFileNames.addAll(comp.getSourceFileNames());
duke@1 1175 genClassFileNames.addAll(comp.getClassFileNames());
duke@1 1176 }
duke@1 1177 sourceFileNames = new java.util.LinkedList<String>();
duke@1 1178 classFileNames = new java.util.LinkedList<String>();
duke@1 1179 }
duke@1 1180 return exitCode;
duke@1 1181 }
duke@1 1182
duke@1 1183 /** Print a message reporting an internal error.
duke@1 1184 */
duke@1 1185 void bugMessage(Throwable ex) {
jjg@1136 1186 Bark.printRawLines(out, getLocalizedString("msg.bug",
jjg@789 1187 AptJavaCompiler.version()));
duke@1 1188 ex.printStackTrace(out);
duke@1 1189 }
duke@1 1190
duke@1 1191 /** Print a message reporting an fatal error.
duke@1 1192 */
duke@1 1193 void apMessage(AnnotationProcessingError ex) {
jjg@1136 1194 Bark.printRawLines(out, getLocalizedString("misc.Problem"));
duke@1 1195 ex.getCause().printStackTrace(out);
duke@1 1196 }
duke@1 1197
duke@1 1198 /** Print a message about sun.misc.Service problem.
duke@1 1199 */
duke@1 1200 void sceMessage(sun.misc.ServiceConfigurationError ex) {
jjg@1136 1201 Bark.printRawLines(out, getLocalizedString("misc.SunMiscService"));
duke@1 1202 ex.printStackTrace(out);
duke@1 1203 }
duke@1 1204
duke@1 1205 /** Print a message reporting an fatal error.
duke@1 1206 */
duke@1 1207 void feMessage(Throwable ex) {
jjg@1136 1208 Bark.printRawLines(out, ex.toString());
duke@1 1209 }
duke@1 1210
duke@1 1211 /** Print a message reporting an input/output error.
duke@1 1212 */
duke@1 1213 void ioMessage(Throwable ex) {
jjg@1136 1214 Bark.printRawLines(out, getLocalizedString("msg.io"));
duke@1 1215 ex.printStackTrace(out);
duke@1 1216 }
duke@1 1217
duke@1 1218 /** Print a message reporting an out-of-resources error.
duke@1 1219 */
duke@1 1220 void resourceMessage(Throwable ex) {
jjg@1136 1221 Bark.printRawLines(out, getLocalizedString("msg.resource"));
duke@1 1222 ex.printStackTrace(out);
duke@1 1223 }
duke@1 1224
duke@1 1225 /* ************************************************************************
duke@1 1226 * Internationalization
duke@1 1227 *************************************************************************/
duke@1 1228
duke@1 1229 /** Find a localized string in the resource bundle.
duke@1 1230 * @param key The key for the localized string.
duke@1 1231 */
duke@1 1232 private static String getLocalizedString(String key, Object... args) {
duke@1 1233 return getText(key, args);
duke@1 1234 }
duke@1 1235
duke@1 1236 private static final String javacRB =
duke@1 1237 "com.sun.tools.javac.resources.javac";
duke@1 1238
duke@1 1239 private static final String aptRB =
duke@1 1240 "com.sun.tools.apt.resources.apt";
duke@1 1241
duke@1 1242 private static ResourceBundle messageRBjavac;
duke@1 1243 private static ResourceBundle messageRBapt;
duke@1 1244
duke@1 1245 /** Initialize ResourceBundle.
duke@1 1246 */
duke@1 1247 private static void initResource() {
duke@1 1248 try {
duke@1 1249 messageRBapt = ResourceBundle.getBundle(aptRB);
duke@1 1250 messageRBjavac = ResourceBundle.getBundle(javacRB);
duke@1 1251 } catch (MissingResourceException e) {
duke@1 1252 Error x = new FatalError("Fatal Error: Resource for apt or javac is missing");
duke@1 1253 x.initCause(e);
duke@1 1254 throw x;
duke@1 1255 }
duke@1 1256 }
duke@1 1257
duke@1 1258 /** Get and format message string from resource.
duke@1 1259 */
duke@1 1260 private static String getText(String key, Object... _args) {
duke@1 1261 String[] args = new String[_args.length];
duke@1 1262 for (int i=0; i<_args.length; i++) {
duke@1 1263 args[i] = "" + _args[i];
duke@1 1264 }
duke@1 1265 if (messageRBapt == null || messageRBjavac == null )
duke@1 1266 initResource();
duke@1 1267 try {
duke@1 1268 return MessageFormat.format(messageRBapt.getString("apt." + key),
duke@1 1269 (Object[]) args);
duke@1 1270 } catch (MissingResourceException e) {
duke@1 1271 try {
duke@1 1272 return MessageFormat.format(messageRBjavac.getString("javac." + key),
duke@1 1273 (Object[]) args);
duke@1 1274 } catch (MissingResourceException f) {
duke@1 1275 String msg = "apt or javac message file broken: key={0} "
duke@1 1276 + "arguments={1}, {2}";
duke@1 1277 return MessageFormat.format(msg, (Object[]) args);
duke@1 1278 }
duke@1 1279 }
duke@1 1280 }
duke@1 1281 }

mercurial