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

Wed, 19 Dec 2012 11:29:56 +0000

author
jjg
date
Wed, 19 Dec 2012 11:29:56 +0000
changeset 1463
67b01d295cd2
parent 1457
064e372f273d
child 1569
475eb15dfdad
permissions
-rw-r--r--

8004833: Integrate doclint support into javac
Reviewed-by: mcimadamore

duke@1 1 /*
jjh@1305 2 * Copyright (c) 1999, 2012, 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.javac.main;
duke@1 27
duke@1 28 import java.io.File;
duke@1 29 import java.io.IOException;
duke@1 30 import java.io.PrintWriter;
jjg@535 31 import java.net.URL;
jjg@535 32 import java.security.DigestInputStream;
jjg@535 33 import java.security.MessageDigest;
jjh@1187 34 import java.util.Arrays;
jjg@1055 35 import java.util.Collection;
jjg@1416 36 import java.util.Iterator;
jjg@1055 37 import java.util.LinkedHashSet;
jjg@1416 38 import java.util.ServiceLoader;
jjg@1055 39 import java.util.Set;
jjg@1416 40
jjg@1416 41 import javax.annotation.processing.Processor;
jjg@700 42 import javax.tools.JavaFileManager;
jjg@700 43 import javax.tools.JavaFileObject;
duke@1 44
jjg@1416 45 import com.sun.source.util.JavacTask;
jjg@1416 46 import com.sun.source.util.Plugin;
jjg@1463 47 import com.sun.tools.doclint.DocLint;
jjg@1463 48 import com.sun.tools.javac.api.BasicJavacTask;
duke@1 49 import com.sun.tools.javac.code.Source;
jjg@106 50 import com.sun.tools.javac.file.CacheFSInfo;
jjg@50 51 import com.sun.tools.javac.file.JavacFileManager;
duke@1 52 import com.sun.tools.javac.jvm.Target;
jjg@1416 53 import com.sun.tools.javac.processing.AnnotationProcessingError;
jjg@1416 54 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
duke@1 55 import com.sun.tools.javac.util.*;
jjg@1416 56 import com.sun.tools.javac.util.Log.PrefixKind;
jjg@1136 57 import com.sun.tools.javac.util.Log.WriterKind;
jjg@1157 58 import static com.sun.tools.javac.main.Option.*;
duke@1 59
jjg@1416 60 /** This class provides a command line interface to the javac compiler.
duke@1 61 *
jjg@581 62 * <p><b>This is NOT part of any supported API.
jjg@581 63 * If you write code that depends on this, you do so at your own risk.
duke@1 64 * This code and its internal interfaces are subject to change or
duke@1 65 * deletion without notice.</b>
duke@1 66 */
duke@1 67 public class Main {
duke@1 68
duke@1 69 /** The name of the compiler, for use in diagnostics.
duke@1 70 */
duke@1 71 String ownName;
duke@1 72
duke@1 73 /** The writer to use for diagnostic output.
duke@1 74 */
duke@1 75 PrintWriter out;
duke@1 76
jjg@1135 77 /** The log to use for diagnostic output.
jjg@1135 78 */
jjg@1135 79 Log log;
jjg@1135 80
duke@1 81 /**
jjg@946 82 * If true, certain errors will cause an exception, such as command line
jjg@946 83 * arg errors, or exceptions in user provided code.
duke@1 84 */
jjg@946 85 boolean apiMode;
jjg@946 86
duke@1 87
duke@1 88 /** Result codes.
duke@1 89 */
jjg@1097 90 public enum Result {
jjg@1097 91 OK(0), // Compilation completed with no errors.
jjg@1097 92 ERROR(1), // Completed but reported errors.
jjg@1097 93 CMDERR(2), // Bad command-line arguments
jjg@1097 94 SYSERR(3), // System error or resource exhaustion.
jjg@1097 95 ABNORMAL(4); // Compiler terminated abnormally
jjg@1097 96
jjg@1097 97 Result(int exitCode) {
jjg@1097 98 this.exitCode = exitCode;
jjg@1097 99 }
jjg@1097 100
jjg@1097 101 public boolean isOK() {
jjg@1097 102 return (exitCode == 0);
jjg@1097 103 }
jjg@1097 104
jjg@1097 105 public final int exitCode;
jjg@1097 106 }
duke@1 107
jjg@1157 108 private Option[] recognizedOptions =
jjg@1157 109 Option.getJavaCompilerOptions().toArray(new Option[0]);
duke@1 110
jjg@1157 111 private OptionHelper optionHelper = new OptionHelper() {
jjg@1157 112 @Override
jjg@1157 113 public String get(Option option) {
jjg@1157 114 return options.get(option);
duke@1 115 }
duke@1 116
jjg@1157 117 @Override
jjg@1157 118 public void put(String name, String value) {
jjg@1157 119 options.put(name, value);
jjg@1157 120 }
jjg@1157 121
jjg@1157 122 @Override
jjg@1157 123 public void remove(String name) {
jjg@1157 124 options.remove(name);
jjg@1157 125 }
jjg@1157 126
jjg@1157 127 @Override
jjg@1157 128 public Log getLog() {
jjg@1157 129 return log;
jjg@1157 130 }
jjg@1157 131
jjg@1157 132 @Override
jjg@1157 133 public String getOwnName() {
jjg@1157 134 return ownName;
jjg@1157 135 }
jjg@1157 136
jjg@1157 137 @Override
duke@1 138 public void error(String key, Object... args) {
duke@1 139 Main.this.error(key, args);
duke@1 140 }
duke@1 141
jjg@1157 142 @Override
duke@1 143 public void addFile(File f) {
jjg@1055 144 filenames.add(f);
duke@1 145 }
duke@1 146
jjg@1157 147 @Override
duke@1 148 public void addClassName(String s) {
duke@1 149 classnames.append(s);
duke@1 150 }
duke@1 151
jjg@1157 152 };
duke@1 153
duke@1 154 /**
duke@1 155 * Construct a compiler instance.
duke@1 156 */
duke@1 157 public Main(String name) {
duke@1 158 this(name, new PrintWriter(System.err, true));
duke@1 159 }
duke@1 160
duke@1 161 /**
duke@1 162 * Construct a compiler instance.
duke@1 163 */
duke@1 164 public Main(String name, PrintWriter out) {
duke@1 165 this.ownName = name;
duke@1 166 this.out = out;
duke@1 167 }
duke@1 168 /** A table of all options that's passed to the JavaCompiler constructor. */
duke@1 169 private Options options = null;
duke@1 170
duke@1 171 /** The list of source files to process
duke@1 172 */
jjg@1055 173 public Set<File> filenames = null; // XXX sb protected
duke@1 174
duke@1 175 /** List of class files names passed on the command line
duke@1 176 */
duke@1 177 public ListBuffer<String> classnames = null; // XXX sb protected
duke@1 178
duke@1 179 /** Report a usage error.
duke@1 180 */
duke@1 181 void error(String key, Object... args) {
jjg@946 182 if (apiMode) {
jjg@1136 183 String msg = log.localize(PrefixKind.JAVAC, key, args);
duke@1 184 throw new PropagatedException(new IllegalStateException(msg));
duke@1 185 }
duke@1 186 warning(key, args);
jjg@1136 187 log.printLines(PrefixKind.JAVAC, "msg.usage", ownName);
duke@1 188 }
duke@1 189
duke@1 190 /** Report a warning.
duke@1 191 */
duke@1 192 void warning(String key, Object... args) {
jjg@1136 193 log.printRawLines(ownName + ": " + log.localize(PrefixKind.JAVAC, key, args));
duke@1 194 }
duke@1 195
duke@1 196 public Option getOption(String flag) {
duke@1 197 for (Option option : recognizedOptions) {
duke@1 198 if (option.matches(flag))
duke@1 199 return option;
duke@1 200 }
duke@1 201 return null;
duke@1 202 }
duke@1 203
duke@1 204 public void setOptions(Options options) {
duke@1 205 if (options == null)
duke@1 206 throw new NullPointerException();
duke@1 207 this.options = options;
duke@1 208 }
duke@1 209
jjg@946 210 public void setAPIMode(boolean apiMode) {
jjg@946 211 this.apiMode = apiMode;
duke@1 212 }
duke@1 213
duke@1 214 /** Process command line arguments: store all command line options
duke@1 215 * in `options' table and return all source filenames.
duke@1 216 * @param flags The array of command line arguments.
duke@1 217 */
jjg@1055 218 public Collection<File> processArgs(String[] flags) { // XXX sb protected
jjh@1187 219 return processArgs(flags, null);
jjh@1187 220 }
jjh@1187 221
jjh@1187 222 public Collection<File> processArgs(String[] flags, String[] classNames) { // XXX sb protected
duke@1 223 int ac = 0;
duke@1 224 while (ac < flags.length) {
duke@1 225 String flag = flags[ac];
duke@1 226 ac++;
duke@1 227
duke@1 228 Option option = null;
duke@1 229
duke@1 230 if (flag.length() > 0) {
duke@1 231 // quick hack to speed up file processing:
duke@1 232 // if the option does not begin with '-', there is no need to check
duke@1 233 // most of the compiler options.
duke@1 234 int firstOptionToCheck = flag.charAt(0) == '-' ? 0 : recognizedOptions.length-1;
duke@1 235 for (int j=firstOptionToCheck; j<recognizedOptions.length; j++) {
duke@1 236 if (recognizedOptions[j].matches(flag)) {
duke@1 237 option = recognizedOptions[j];
duke@1 238 break;
duke@1 239 }
duke@1 240 }
duke@1 241 }
duke@1 242
duke@1 243 if (option == null) {
duke@1 244 error("err.invalid.flag", flag);
duke@1 245 return null;
duke@1 246 }
duke@1 247
duke@1 248 if (option.hasArg()) {
duke@1 249 if (ac == flags.length) {
duke@1 250 error("err.req.arg", flag);
duke@1 251 return null;
duke@1 252 }
duke@1 253 String operand = flags[ac];
duke@1 254 ac++;
jjg@1157 255 if (option.process(optionHelper, flag, operand))
duke@1 256 return null;
duke@1 257 } else {
jjg@1157 258 if (option.process(optionHelper, flag))
duke@1 259 return null;
duke@1 260 }
duke@1 261 }
duke@1 262
jjh@1187 263 if (this.classnames != null && classNames != null) {
jjh@1187 264 this.classnames.addAll(Arrays.asList(classNames));
jjh@1187 265 }
jjh@1187 266
jjg@700 267 if (!checkDirectory(D))
duke@1 268 return null;
jjg@700 269 if (!checkDirectory(S))
duke@1 270 return null;
duke@1 271
jjg@700 272 String sourceString = options.get(SOURCE);
duke@1 273 Source source = (sourceString != null)
duke@1 274 ? Source.lookup(sourceString)
duke@1 275 : Source.DEFAULT;
jjg@700 276 String targetString = options.get(TARGET);
duke@1 277 Target target = (targetString != null)
duke@1 278 ? Target.lookup(targetString)
duke@1 279 : Target.DEFAULT;
duke@1 280 // We don't check source/target consistency for CLDC, as J2ME
duke@1 281 // profiles are not aligned with J2SE targets; moreover, a
duke@1 282 // single CLDC target may have many profiles. In addition,
duke@1 283 // this is needed for the continued functioning of the JSR14
duke@1 284 // prototype.
duke@1 285 if (Character.isDigit(target.name.charAt(0))) {
duke@1 286 if (target.compareTo(source.requiredTarget()) < 0) {
duke@1 287 if (targetString != null) {
duke@1 288 if (sourceString == null) {
duke@1 289 warning("warn.target.default.source.conflict",
duke@1 290 targetString,
duke@1 291 source.requiredTarget().name);
duke@1 292 } else {
duke@1 293 warning("warn.source.target.conflict",
duke@1 294 sourceString,
duke@1 295 source.requiredTarget().name);
duke@1 296 }
duke@1 297 return null;
duke@1 298 } else {
jrose@267 299 target = source.requiredTarget();
jrose@267 300 options.put("-target", target.name);
duke@1 301 }
duke@1 302 } else {
duke@1 303 if (targetString == null && !source.allowGenerics()) {
jrose@267 304 target = Target.JDK1_4;
jrose@267 305 options.put("-target", target.name);
duke@1 306 }
duke@1 307 }
duke@1 308 }
jjg@535 309
jjg@535 310 // handle this here so it works even if no other options given
jjg@535 311 String showClass = options.get("showClass");
jjg@535 312 if (showClass != null) {
jjg@535 313 if (showClass.equals("showClass")) // no value given for option
jjg@535 314 showClass = "com.sun.tools.javac.Main";
jjg@535 315 showClass(showClass);
jjg@535 316 }
jjg@535 317
jjg@1135 318 options.notifyListeners();
jjg@1135 319
jjg@1055 320 return filenames;
duke@1 321 }
duke@1 322 // where
jjg@1157 323 private boolean checkDirectory(Option option) {
jjg@1157 324 String value = options.get(option);
duke@1 325 if (value == null)
duke@1 326 return true;
duke@1 327 File file = new File(value);
duke@1 328 if (!file.exists()) {
duke@1 329 error("err.dir.not.found", value);
duke@1 330 return false;
duke@1 331 }
duke@1 332 if (!file.isDirectory()) {
duke@1 333 error("err.file.not.directory", value);
duke@1 334 return false;
duke@1 335 }
duke@1 336 return true;
duke@1 337 }
duke@1 338
duke@1 339 /** Programmatic interface for main function.
duke@1 340 * @param args The command line parameters.
duke@1 341 */
jjg@1097 342 public Result compile(String[] args) {
duke@1 343 Context context = new Context();
duke@1 344 JavacFileManager.preRegister(context); // can't create it until Log has been set up
jjg@1097 345 Result result = compile(args, context);
duke@1 346 if (fileManager instanceof JavacFileManager) {
duke@1 347 // A fresh context was created above, so jfm must be a JavacFileManager
duke@1 348 ((JavacFileManager)fileManager).close();
duke@1 349 }
duke@1 350 return result;
duke@1 351 }
duke@1 352
jjg@1097 353 public Result compile(String[] args, Context context) {
duke@1 354 return compile(args, context, List.<JavaFileObject>nil(), null);
duke@1 355 }
duke@1 356
duke@1 357 /** Programmatic interface for main function.
duke@1 358 * @param args The command line parameters.
duke@1 359 */
jjg@1097 360 public Result compile(String[] args,
duke@1 361 Context context,
duke@1 362 List<JavaFileObject> fileObjects,
duke@1 363 Iterable<? extends Processor> processors)
duke@1 364 {
jjh@1187 365 return compile(args, null, context, fileObjects, processors);
jjh@1187 366 }
jjh@1187 367
jjh@1187 368 public Result compile(String[] args,
jjh@1187 369 String[] classNames,
jjh@1187 370 Context context,
jjh@1187 371 List<JavaFileObject> fileObjects,
jjh@1187 372 Iterable<? extends Processor> processors)
jjh@1187 373 {
jjg@1135 374 context.put(Log.outKey, out);
jjg@1135 375 log = Log.instance(context);
jjg@1135 376
duke@1 377 if (options == null)
duke@1 378 options = Options.instance(context); // creates a new one
duke@1 379
jjg@1055 380 filenames = new LinkedHashSet<File>();
duke@1 381 classnames = new ListBuffer<String>();
duke@1 382 JavaCompiler comp = null;
duke@1 383 /*
duke@1 384 * TODO: Logic below about what is an acceptable command line
duke@1 385 * should be updated to take annotation processing semantics
duke@1 386 * into account.
duke@1 387 */
duke@1 388 try {
jjh@1187 389 if (args.length == 0
jjh@1187 390 && (classNames == null || classNames.length == 0)
jjh@1187 391 && fileObjects.isEmpty()) {
jjg@1157 392 Option.HELP.process(optionHelper, "-help");
jjg@1097 393 return Result.CMDERR;
duke@1 394 }
duke@1 395
jjg@1055 396 Collection<File> files;
duke@1 397 try {
jjh@1187 398 files = processArgs(CommandLine.parse(args), classNames);
jjg@194 399 if (files == null) {
duke@1 400 // null signals an error in options, abort
jjg@1097 401 return Result.CMDERR;
jjg@194 402 } else if (files.isEmpty() && fileObjects.isEmpty() && classnames.isEmpty()) {
duke@1 403 // it is allowed to compile nothing if just asking for help or version info
jjg@700 404 if (options.isSet(HELP)
jjg@700 405 || options.isSet(X)
jjg@700 406 || options.isSet(VERSION)
jjg@700 407 || options.isSet(FULLVERSION))
jjg@1097 408 return Result.OK;
jjg@902 409 if (JavaCompiler.explicitAnnotationProcessingRequested(options)) {
jjg@902 410 error("err.no.source.files.classes");
jjg@902 411 } else {
jjg@902 412 error("err.no.source.files");
jjg@902 413 }
jjg@1097 414 return Result.CMDERR;
duke@1 415 }
duke@1 416 } catch (java.io.FileNotFoundException e) {
jjg@1136 417 warning("err.file.not.found", e.getMessage());
jjg@1097 418 return Result.SYSERR;
duke@1 419 }
duke@1 420
jjg@700 421 boolean forceStdOut = options.isSet("stdout");
duke@1 422 if (forceStdOut) {
jjg@1135 423 log.flush();
jjg@1157 424 log.setWriters(new PrintWriter(System.out, true));
duke@1 425 }
duke@1 426
jjg@106 427 // allow System property in following line as a Mustang legacy
jjg@700 428 boolean batchMode = (options.isUnset("nonBatchMode")
jjg@106 429 && System.getProperty("nonBatchMode") == null);
jjg@106 430 if (batchMode)
jjg@106 431 CacheFSInfo.preRegister(context);
jjg@106 432
jjg@1463 433 // FIXME: this code will not be invoked if using JavacTask.parse/analyze/generate
jjg@1416 434 // invoke any available plugins
jjg@1416 435 String plugins = options.get(PLUGIN);
jjg@1416 436 if (plugins != null) {
jjg@1416 437 JavacProcessingEnvironment pEnv = JavacProcessingEnvironment.instance(context);
jjg@1416 438 ClassLoader cl = pEnv.getProcessorClassLoader();
jjg@1416 439 ServiceLoader<Plugin> sl = ServiceLoader.load(Plugin.class, cl);
jjg@1416 440 Set<List<String>> pluginsToCall = new LinkedHashSet<List<String>>();
jjg@1416 441 for (String plugin: plugins.split("\\x00")) {
jjg@1416 442 pluginsToCall.add(List.from(plugin.split("\\s+")));
jjg@1416 443 }
jjg@1416 444 JavacTask task = null;
jjg@1416 445 Iterator<Plugin> iter = sl.iterator();
jjg@1416 446 while (iter.hasNext()) {
jjg@1416 447 Plugin plugin = iter.next();
jjg@1416 448 for (List<String> p: pluginsToCall) {
jjg@1416 449 if (plugin.getName().equals(p.head)) {
jjg@1416 450 pluginsToCall.remove(p);
jjg@1416 451 try {
jjg@1416 452 if (task == null)
jjg@1416 453 task = JavacTask.instance(pEnv);
jjg@1457 454 plugin.init(task, p.tail.toArray(new String[p.tail.size()]));
jjg@1416 455 } catch (Throwable ex) {
jjg@1416 456 if (apiMode)
jjg@1416 457 throw new RuntimeException(ex);
jjg@1416 458 pluginMessage(ex);
jjg@1416 459 return Result.SYSERR;
jjg@1416 460 }
jjg@1416 461
jjg@1416 462 }
jjg@1416 463 }
jjg@1416 464 }
jjg@1416 465 for (List<String> p: pluginsToCall) {
jjg@1416 466 log.printLines(PrefixKind.JAVAC, "msg.plugin.not.found", p.head);
jjg@1416 467 }
jjg@1416 468 }
jjg@1416 469
jjg@1463 470 comp = JavaCompiler.instance(context);
jjg@1463 471
jjg@1463 472 // FIXME: this code will not be invoked if using JavacTask.parse/analyze/generate
jjg@1463 473 String xdoclint = options.get(XDOCLINT);
jjg@1463 474 String xdoclintCustom = options.get(XDOCLINT_CUSTOM);
jjg@1463 475 if (xdoclint != null || xdoclintCustom != null) {
jjg@1463 476 Set<String> doclintOpts = new LinkedHashSet<String>();
jjg@1463 477 if (xdoclint != null)
jjg@1463 478 doclintOpts.add(DocLint.XMSGS_OPTION);
jjg@1463 479 if (xdoclintCustom != null) {
jjg@1463 480 for (String s: xdoclintCustom.split("\\s+")) {
jjg@1463 481 if (s.isEmpty())
jjg@1463 482 continue;
jjg@1463 483 doclintOpts.add(s.replace(XDOCLINT_CUSTOM.text, DocLint.XMSGS_CUSTOM_PREFIX));
jjg@1463 484 }
jjg@1463 485 }
jjg@1463 486 if (!(doclintOpts.size() == 1
jjg@1463 487 && doclintOpts.iterator().next().equals(DocLint.XMSGS_CUSTOM_PREFIX + "none"))) {
jjg@1463 488 JavacTask t = BasicJavacTask.instance(context);
jjg@1463 489 new DocLint().init(t, doclintOpts.toArray(new String[doclintOpts.size()]));
jjg@1463 490 comp.keepComments = true;
jjg@1463 491 }
jjg@1463 492 }
jjg@1463 493
duke@1 494 fileManager = context.get(JavaFileManager.class);
duke@1 495
jjg@194 496 if (!files.isEmpty()) {
duke@1 497 // add filenames to fileObjects
duke@1 498 comp = JavaCompiler.instance(context);
duke@1 499 List<JavaFileObject> otherFiles = List.nil();
duke@1 500 JavacFileManager dfm = (JavacFileManager)fileManager;
jjg@194 501 for (JavaFileObject fo : dfm.getJavaFileObjectsFromFiles(files))
duke@1 502 otherFiles = otherFiles.prepend(fo);
duke@1 503 for (JavaFileObject fo : otherFiles)
duke@1 504 fileObjects = fileObjects.prepend(fo);
duke@1 505 }
duke@1 506 comp.compile(fileObjects,
duke@1 507 classnames.toList(),
duke@1 508 processors);
duke@1 509
jjg@194 510 if (log.expectDiagKeys != null) {
jjg@757 511 if (log.expectDiagKeys.isEmpty()) {
jjg@1136 512 log.printRawLines("all expected diagnostics found");
jjg@1097 513 return Result.OK;
jjg@194 514 } else {
jjg@1136 515 log.printRawLines("expected diagnostic keys not found: " + log.expectDiagKeys);
jjg@1097 516 return Result.ERROR;
jjg@194 517 }
jjg@194 518 }
jjg@194 519
jjg@215 520 if (comp.errorCount() != 0)
jjg@1097 521 return Result.ERROR;
duke@1 522 } catch (IOException ex) {
duke@1 523 ioMessage(ex);
jjg@1097 524 return Result.SYSERR;
duke@1 525 } catch (OutOfMemoryError ex) {
duke@1 526 resourceMessage(ex);
jjg@1097 527 return Result.SYSERR;
duke@1 528 } catch (StackOverflowError ex) {
duke@1 529 resourceMessage(ex);
jjg@1097 530 return Result.SYSERR;
duke@1 531 } catch (FatalError ex) {
duke@1 532 feMessage(ex);
jjg@1097 533 return Result.SYSERR;
jjg@946 534 } catch (AnnotationProcessingError ex) {
jjg@946 535 if (apiMode)
jjg@946 536 throw new RuntimeException(ex.getCause());
duke@1 537 apMessage(ex);
jjg@1097 538 return Result.SYSERR;
duke@1 539 } catch (ClientCodeException ex) {
duke@1 540 // as specified by javax.tools.JavaCompiler#getTask
duke@1 541 // and javax.tools.JavaCompiler.CompilationTask#call
duke@1 542 throw new RuntimeException(ex.getCause());
duke@1 543 } catch (PropagatedException ex) {
duke@1 544 throw ex.getCause();
duke@1 545 } catch (Throwable ex) {
duke@1 546 // Nasty. If we've already reported an error, compensate
duke@1 547 // for buggy compiler error recovery by swallowing thrown
duke@1 548 // exceptions.
duke@1 549 if (comp == null || comp.errorCount() == 0 ||
jjg@700 550 options == null || options.isSet("dev"))
duke@1 551 bugMessage(ex);
jjg@1097 552 return Result.ABNORMAL;
duke@1 553 } finally {
jjg@946 554 if (comp != null) {
jjg@946 555 try {
jjg@946 556 comp.close();
jjg@946 557 } catch (ClientCodeException ex) {
jjg@946 558 throw new RuntimeException(ex.getCause());
jjg@946 559 }
jjg@946 560 }
duke@1 561 filenames = null;
duke@1 562 options = null;
duke@1 563 }
jjg@1097 564 return Result.OK;
duke@1 565 }
duke@1 566
duke@1 567 /** Print a message reporting an internal error.
duke@1 568 */
duke@1 569 void bugMessage(Throwable ex) {
jjg@1136 570 log.printLines(PrefixKind.JAVAC, "msg.bug", JavaCompiler.version());
jjg@1136 571 ex.printStackTrace(log.getWriter(WriterKind.NOTICE));
duke@1 572 }
duke@1 573
jjg@663 574 /** Print a message reporting a fatal error.
duke@1 575 */
duke@1 576 void feMessage(Throwable ex) {
jjg@1136 577 log.printRawLines(ex.getMessage());
jjg@700 578 if (ex.getCause() != null && options.isSet("dev")) {
jjg@1136 579 ex.getCause().printStackTrace(log.getWriter(WriterKind.NOTICE));
jjg@663 580 }
duke@1 581 }
duke@1 582
duke@1 583 /** Print a message reporting an input/output error.
duke@1 584 */
duke@1 585 void ioMessage(Throwable ex) {
jjg@1136 586 log.printLines(PrefixKind.JAVAC, "msg.io");
jjg@1136 587 ex.printStackTrace(log.getWriter(WriterKind.NOTICE));
duke@1 588 }
duke@1 589
duke@1 590 /** Print a message reporting an out-of-resources error.
duke@1 591 */
duke@1 592 void resourceMessage(Throwable ex) {
jjg@1136 593 log.printLines(PrefixKind.JAVAC, "msg.resource");
jjg@1136 594 ex.printStackTrace(log.getWriter(WriterKind.NOTICE));
duke@1 595 }
duke@1 596
duke@1 597 /** Print a message reporting an uncaught exception from an
duke@1 598 * annotation processor.
duke@1 599 */
duke@1 600 void apMessage(AnnotationProcessingError ex) {
jjg@1398 601 log.printLines(PrefixKind.JAVAC, "msg.proc.annotation.uncaught.exception");
jjg@1136 602 ex.getCause().printStackTrace(log.getWriter(WriterKind.NOTICE));
duke@1 603 }
duke@1 604
jjg@1416 605 /** Print a message reporting an uncaught exception from an
jjg@1416 606 * annotation processor.
jjg@1416 607 */
jjg@1416 608 void pluginMessage(Throwable ex) {
jjg@1416 609 log.printLines(PrefixKind.JAVAC, "msg.plugin.uncaught.exception");
jjg@1416 610 ex.printStackTrace(log.getWriter(WriterKind.NOTICE));
jjg@1416 611 }
jjg@1416 612
jjg@535 613 /** Display the location and checksum of a class. */
jjg@535 614 void showClass(String className) {
jjg@1136 615 PrintWriter pw = log.getWriter(WriterKind.NOTICE);
jjg@1136 616 pw.println("javac: show class: " + className);
jjg@535 617 URL url = getClass().getResource('/' + className.replace('.', '/') + ".class");
jjg@535 618 if (url == null)
jjg@1136 619 pw.println(" class not found");
jjg@535 620 else {
jjg@1136 621 pw.println(" " + url);
jjg@535 622 try {
jjg@535 623 final String algorithm = "MD5";
jjg@535 624 byte[] digest;
jjg@535 625 MessageDigest md = MessageDigest.getInstance(algorithm);
jjg@535 626 DigestInputStream in = new DigestInputStream(url.openStream(), md);
jjg@535 627 try {
jjg@535 628 byte[] buf = new byte[8192];
jjg@535 629 int n;
jjg@535 630 do { n = in.read(buf); } while (n > 0);
jjg@535 631 digest = md.digest();
jjg@535 632 } finally {
jjg@535 633 in.close();
jjg@535 634 }
jjg@535 635 StringBuilder sb = new StringBuilder();
jjg@535 636 for (byte b: digest)
jjg@535 637 sb.append(String.format("%02x", b));
jjg@1136 638 pw.println(" " + algorithm + " checksum: " + sb);
jjg@535 639 } catch (Exception e) {
jjg@1136 640 pw.println(" cannot compute digest: " + e);
jjg@535 641 }
jjg@535 642 }
jjg@535 643 }
jjg@535 644
duke@1 645 private JavaFileManager fileManager;
duke@1 646
duke@1 647 /* ************************************************************************
duke@1 648 * Internationalization
duke@1 649 *************************************************************************/
duke@1 650
jjg@1136 651 // /** Find a localized string in the resource bundle.
jjg@1136 652 // * @param key The key for the localized string.
jjg@1136 653 // */
jjg@1136 654 // public static String getLocalizedString(String key, Object... args) { // FIXME sb private
jjg@1136 655 // try {
jjg@1136 656 // if (messages == null)
jjg@1136 657 // messages = new JavacMessages(javacBundleName);
jjg@1136 658 // return messages.getLocalizedString("javac." + key, args);
jjg@1136 659 // }
jjg@1136 660 // catch (MissingResourceException e) {
jjg@1136 661 // throw new Error("Fatal Error: Resource for javac is missing", e);
jjg@1136 662 // }
jjg@1136 663 // }
jjg@1136 664 //
jjg@1136 665 // public static void useRawMessages(boolean enable) {
jjg@1136 666 // if (enable) {
jjg@1136 667 // messages = new JavacMessages(javacBundleName) {
jjg@1136 668 // @Override
jjg@1136 669 // public String getLocalizedString(String key, Object... args) {
jjg@1136 670 // return key;
jjg@1136 671 // }
jjg@1136 672 // };
jjg@1136 673 // } else {
jjg@1136 674 // messages = new JavacMessages(javacBundleName);
jjg@1136 675 // }
jjg@1136 676 // }
duke@1 677
jjg@1136 678 public static final String javacBundleName =
duke@1 679 "com.sun.tools.javac.resources.javac";
jjg@1136 680 //
jjg@1136 681 // private static JavacMessages messages;
duke@1 682 }

mercurial