1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/main/Main.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,699 @@ 1.4 +/* 1.5 + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.javac.main; 1.30 + 1.31 +import java.io.File; 1.32 +import java.io.IOException; 1.33 +import java.io.PrintWriter; 1.34 +import java.net.URL; 1.35 +import java.security.DigestInputStream; 1.36 +import java.security.MessageDigest; 1.37 +import java.util.Arrays; 1.38 +import java.util.Collection; 1.39 +import java.util.Iterator; 1.40 +import java.util.LinkedHashSet; 1.41 +import java.util.Set; 1.42 + 1.43 +import javax.annotation.processing.Processor; 1.44 +import javax.tools.JavaFileManager; 1.45 +import javax.tools.JavaFileObject; 1.46 + 1.47 +import com.sun.source.util.JavacTask; 1.48 +import com.sun.source.util.Plugin; 1.49 +import com.sun.tools.doclint.DocLint; 1.50 +import com.sun.tools.javac.api.BasicJavacTask; 1.51 +import com.sun.tools.javac.code.Source; 1.52 +import com.sun.tools.javac.file.CacheFSInfo; 1.53 +import com.sun.tools.javac.file.JavacFileManager; 1.54 +import com.sun.tools.javac.jvm.Profile; 1.55 +import com.sun.tools.javac.jvm.Target; 1.56 +import com.sun.tools.javac.processing.AnnotationProcessingError; 1.57 +import com.sun.tools.javac.processing.JavacProcessingEnvironment; 1.58 +import com.sun.tools.javac.util.*; 1.59 +import com.sun.tools.javac.util.Log.PrefixKind; 1.60 +import com.sun.tools.javac.util.Log.WriterKind; 1.61 +import com.sun.tools.javac.util.ServiceLoader; 1.62 +import static com.sun.tools.javac.main.Option.*; 1.63 + 1.64 +/** This class provides a command line interface to the javac compiler. 1.65 + * 1.66 + * <p><b>This is NOT part of any supported API. 1.67 + * If you write code that depends on this, you do so at your own risk. 1.68 + * This code and its internal interfaces are subject to change or 1.69 + * deletion without notice.</b> 1.70 + */ 1.71 +public class Main { 1.72 + 1.73 + /** The name of the compiler, for use in diagnostics. 1.74 + */ 1.75 + String ownName; 1.76 + 1.77 + /** The writer to use for diagnostic output. 1.78 + */ 1.79 + PrintWriter out; 1.80 + 1.81 + /** The log to use for diagnostic output. 1.82 + */ 1.83 + public Log log; 1.84 + 1.85 + /** 1.86 + * If true, certain errors will cause an exception, such as command line 1.87 + * arg errors, or exceptions in user provided code. 1.88 + */ 1.89 + boolean apiMode; 1.90 + 1.91 + 1.92 + /** Result codes. 1.93 + */ 1.94 + public enum Result { 1.95 + OK(0), // Compilation completed with no errors. 1.96 + ERROR(1), // Completed but reported errors. 1.97 + CMDERR(2), // Bad command-line arguments 1.98 + SYSERR(3), // System error or resource exhaustion. 1.99 + ABNORMAL(4); // Compiler terminated abnormally 1.100 + 1.101 + Result(int exitCode) { 1.102 + this.exitCode = exitCode; 1.103 + } 1.104 + 1.105 + public boolean isOK() { 1.106 + return (exitCode == 0); 1.107 + } 1.108 + 1.109 + public final int exitCode; 1.110 + } 1.111 + 1.112 + private Option[] recognizedOptions = 1.113 + Option.getJavaCompilerOptions().toArray(new Option[0]); 1.114 + 1.115 + private OptionHelper optionHelper = new OptionHelper() { 1.116 + @Override 1.117 + public String get(Option option) { 1.118 + return options.get(option); 1.119 + } 1.120 + 1.121 + @Override 1.122 + public void put(String name, String value) { 1.123 + options.put(name, value); 1.124 + } 1.125 + 1.126 + @Override 1.127 + public void remove(String name) { 1.128 + options.remove(name); 1.129 + } 1.130 + 1.131 + @Override 1.132 + public Log getLog() { 1.133 + return log; 1.134 + } 1.135 + 1.136 + @Override 1.137 + public String getOwnName() { 1.138 + return ownName; 1.139 + } 1.140 + 1.141 + @Override 1.142 + public void error(String key, Object... args) { 1.143 + Main.this.error(key, args); 1.144 + } 1.145 + 1.146 + @Override 1.147 + public void addFile(File f) { 1.148 + filenames.add(f); 1.149 + } 1.150 + 1.151 + @Override 1.152 + public void addClassName(String s) { 1.153 + classnames.append(s); 1.154 + } 1.155 + 1.156 + }; 1.157 + 1.158 + /** 1.159 + * Construct a compiler instance. 1.160 + */ 1.161 + public Main(String name) { 1.162 + this(name, new PrintWriter(System.err, true)); 1.163 + } 1.164 + 1.165 + /** 1.166 + * Construct a compiler instance. 1.167 + */ 1.168 + public Main(String name, PrintWriter out) { 1.169 + this.ownName = name; 1.170 + this.out = out; 1.171 + } 1.172 + 1.173 + /** A table of all options that's passed to the JavaCompiler constructor. */ 1.174 + private Options options = null; 1.175 + 1.176 + /** The list of source files to process 1.177 + */ 1.178 + public Set<File> filenames = null; // XXX sb protected 1.179 + 1.180 + /** List of class files names passed on the command line 1.181 + */ 1.182 + public ListBuffer<String> classnames = null; // XXX sb protected 1.183 + 1.184 + /** Report a usage error. 1.185 + */ 1.186 + void error(String key, Object... args) { 1.187 + if (apiMode) { 1.188 + String msg = log.localize(PrefixKind.JAVAC, key, args); 1.189 + throw new PropagatedException(new IllegalStateException(msg)); 1.190 + } 1.191 + warning(key, args); 1.192 + log.printLines(PrefixKind.JAVAC, "msg.usage", ownName); 1.193 + } 1.194 + 1.195 + /** Report a warning. 1.196 + */ 1.197 + void warning(String key, Object... args) { 1.198 + log.printRawLines(ownName + ": " + log.localize(PrefixKind.JAVAC, key, args)); 1.199 + } 1.200 + 1.201 + public Option getOption(String flag) { 1.202 + for (Option option : recognizedOptions) { 1.203 + if (option.matches(flag)) 1.204 + return option; 1.205 + } 1.206 + return null; 1.207 + } 1.208 + 1.209 + public void setOptions(Options options) { 1.210 + if (options == null) 1.211 + throw new NullPointerException(); 1.212 + this.options = options; 1.213 + } 1.214 + 1.215 + public void setAPIMode(boolean apiMode) { 1.216 + this.apiMode = apiMode; 1.217 + } 1.218 + 1.219 + /** Process command line arguments: store all command line options 1.220 + * in `options' table and return all source filenames. 1.221 + * @param flags The array of command line arguments. 1.222 + */ 1.223 + public Collection<File> processArgs(String[] flags) { // XXX sb protected 1.224 + return processArgs(flags, null); 1.225 + } 1.226 + 1.227 + public Collection<File> processArgs(String[] flags, String[] classNames) { // XXX sb protected 1.228 + int ac = 0; 1.229 + while (ac < flags.length) { 1.230 + String flag = flags[ac]; 1.231 + ac++; 1.232 + 1.233 + Option option = null; 1.234 + 1.235 + if (flag.length() > 0) { 1.236 + // quick hack to speed up file processing: 1.237 + // if the option does not begin with '-', there is no need to check 1.238 + // most of the compiler options. 1.239 + int firstOptionToCheck = flag.charAt(0) == '-' ? 0 : recognizedOptions.length-1; 1.240 + for (int j=firstOptionToCheck; j<recognizedOptions.length; j++) { 1.241 + if (recognizedOptions[j].matches(flag)) { 1.242 + option = recognizedOptions[j]; 1.243 + break; 1.244 + } 1.245 + } 1.246 + } 1.247 + 1.248 + if (option == null) { 1.249 + error("err.invalid.flag", flag); 1.250 + return null; 1.251 + } 1.252 + 1.253 + if (option.hasArg()) { 1.254 + if (ac == flags.length) { 1.255 + error("err.req.arg", flag); 1.256 + return null; 1.257 + } 1.258 + String operand = flags[ac]; 1.259 + ac++; 1.260 + if (option.process(optionHelper, flag, operand)) 1.261 + return null; 1.262 + } else { 1.263 + if (option.process(optionHelper, flag)) 1.264 + return null; 1.265 + } 1.266 + } 1.267 + 1.268 + if (options.get(PROFILE) != null && options.get(BOOTCLASSPATH) != null) { 1.269 + error("err.profile.bootclasspath.conflict"); 1.270 + return null; 1.271 + } 1.272 + 1.273 + if (this.classnames != null && classNames != null) { 1.274 + this.classnames.addAll(Arrays.asList(classNames)); 1.275 + } 1.276 + 1.277 + if (!checkDirectory(D)) 1.278 + return null; 1.279 + if (!checkDirectory(S)) 1.280 + return null; 1.281 + 1.282 + String sourceString = options.get(SOURCE); 1.283 + Source source = (sourceString != null) 1.284 + ? Source.lookup(sourceString) 1.285 + : Source.DEFAULT; 1.286 + String targetString = options.get(TARGET); 1.287 + Target target = (targetString != null) 1.288 + ? Target.lookup(targetString) 1.289 + : Target.DEFAULT; 1.290 + // We don't check source/target consistency for CLDC, as J2ME 1.291 + // profiles are not aligned with J2SE targets; moreover, a 1.292 + // single CLDC target may have many profiles. In addition, 1.293 + // this is needed for the continued functioning of the JSR14 1.294 + // prototype. 1.295 + if (Character.isDigit(target.name.charAt(0))) { 1.296 + if (target.compareTo(source.requiredTarget()) < 0) { 1.297 + if (targetString != null) { 1.298 + if (sourceString == null) { 1.299 + warning("warn.target.default.source.conflict", 1.300 + targetString, 1.301 + source.requiredTarget().name); 1.302 + } else { 1.303 + warning("warn.source.target.conflict", 1.304 + sourceString, 1.305 + source.requiredTarget().name); 1.306 + } 1.307 + return null; 1.308 + } else { 1.309 + target = source.requiredTarget(); 1.310 + options.put("-target", target.name); 1.311 + } 1.312 + } else { 1.313 + if (targetString == null && !source.allowGenerics()) { 1.314 + target = Target.JDK1_4; 1.315 + options.put("-target", target.name); 1.316 + } 1.317 + } 1.318 + } 1.319 + 1.320 + String profileString = options.get(PROFILE); 1.321 + if (profileString != null) { 1.322 + Profile profile = Profile.lookup(profileString); 1.323 + if (!profile.isValid(target)) { 1.324 + warning("warn.profile.target.conflict", profileString, target.name); 1.325 + return null; 1.326 + } 1.327 + } 1.328 + 1.329 + // handle this here so it works even if no other options given 1.330 + String showClass = options.get("showClass"); 1.331 + if (showClass != null) { 1.332 + if (showClass.equals("showClass")) // no value given for option 1.333 + showClass = "com.sun.tools.javac.Main"; 1.334 + showClass(showClass); 1.335 + } 1.336 + 1.337 + options.notifyListeners(); 1.338 + 1.339 + return filenames; 1.340 + } 1.341 + // where 1.342 + private boolean checkDirectory(Option option) { 1.343 + String value = options.get(option); 1.344 + if (value == null) 1.345 + return true; 1.346 + File file = new File(value); 1.347 + if (!file.exists()) { 1.348 + error("err.dir.not.found", value); 1.349 + return false; 1.350 + } 1.351 + if (!file.isDirectory()) { 1.352 + error("err.file.not.directory", value); 1.353 + return false; 1.354 + } 1.355 + return true; 1.356 + } 1.357 + 1.358 + /** Programmatic interface for main function. 1.359 + * @param args The command line parameters. 1.360 + */ 1.361 + public Result compile(String[] args) { 1.362 + Context context = new Context(); 1.363 + JavacFileManager.preRegister(context); // can't create it until Log has been set up 1.364 + Result result = compile(args, context); 1.365 + if (fileManager instanceof JavacFileManager) { 1.366 + // A fresh context was created above, so jfm must be a JavacFileManager 1.367 + ((JavacFileManager)fileManager).close(); 1.368 + } 1.369 + return result; 1.370 + } 1.371 + 1.372 + public Result compile(String[] args, Context context) { 1.373 + return compile(args, context, List.<JavaFileObject>nil(), null); 1.374 + } 1.375 + 1.376 + /** Programmatic interface for main function. 1.377 + * @param args The command line parameters. 1.378 + */ 1.379 + public Result compile(String[] args, 1.380 + Context context, 1.381 + List<JavaFileObject> fileObjects, 1.382 + Iterable<? extends Processor> processors) 1.383 + { 1.384 + return compile(args, null, context, fileObjects, processors); 1.385 + } 1.386 + 1.387 + public Result compile(String[] args, 1.388 + String[] classNames, 1.389 + Context context, 1.390 + List<JavaFileObject> fileObjects, 1.391 + Iterable<? extends Processor> processors) 1.392 + { 1.393 + context.put(Log.outKey, out); 1.394 + log = Log.instance(context); 1.395 + 1.396 + if (options == null) 1.397 + options = Options.instance(context); // creates a new one 1.398 + 1.399 + filenames = new LinkedHashSet<File>(); 1.400 + classnames = new ListBuffer<String>(); 1.401 + JavaCompiler comp = null; 1.402 + /* 1.403 + * TODO: Logic below about what is an acceptable command line 1.404 + * should be updated to take annotation processing semantics 1.405 + * into account. 1.406 + */ 1.407 + try { 1.408 + if (args.length == 0 1.409 + && (classNames == null || classNames.length == 0) 1.410 + && fileObjects.isEmpty()) { 1.411 + Option.HELP.process(optionHelper, "-help"); 1.412 + return Result.CMDERR; 1.413 + } 1.414 + 1.415 + Collection<File> files; 1.416 + try { 1.417 + files = processArgs(CommandLine.parse(args), classNames); 1.418 + if (files == null) { 1.419 + // null signals an error in options, abort 1.420 + return Result.CMDERR; 1.421 + } else if (files.isEmpty() && fileObjects.isEmpty() && classnames.isEmpty()) { 1.422 + // it is allowed to compile nothing if just asking for help or version info 1.423 + if (options.isSet(HELP) 1.424 + || options.isSet(X) 1.425 + || options.isSet(VERSION) 1.426 + || options.isSet(FULLVERSION)) 1.427 + return Result.OK; 1.428 + if (JavaCompiler.explicitAnnotationProcessingRequested(options)) { 1.429 + error("err.no.source.files.classes"); 1.430 + } else { 1.431 + error("err.no.source.files"); 1.432 + } 1.433 + return Result.CMDERR; 1.434 + } 1.435 + } catch (java.io.FileNotFoundException e) { 1.436 + warning("err.file.not.found", e.getMessage()); 1.437 + return Result.SYSERR; 1.438 + } 1.439 + 1.440 + boolean forceStdOut = options.isSet("stdout"); 1.441 + if (forceStdOut) { 1.442 + log.flush(); 1.443 + log.setWriters(new PrintWriter(System.out, true)); 1.444 + } 1.445 + 1.446 + // allow System property in following line as a Mustang legacy 1.447 + boolean batchMode = (options.isUnset("nonBatchMode") 1.448 + && System.getProperty("nonBatchMode") == null); 1.449 + if (batchMode) 1.450 + CacheFSInfo.preRegister(context); 1.451 + 1.452 + // FIXME: this code will not be invoked if using JavacTask.parse/analyze/generate 1.453 + // invoke any available plugins 1.454 + String plugins = options.get(PLUGIN); 1.455 + if (plugins != null) { 1.456 + JavacProcessingEnvironment pEnv = JavacProcessingEnvironment.instance(context); 1.457 + ClassLoader cl = pEnv.getProcessorClassLoader(); 1.458 + ServiceLoader<Plugin> sl = ServiceLoader.load(Plugin.class, cl); 1.459 + Set<List<String>> pluginsToCall = new LinkedHashSet<List<String>>(); 1.460 + for (String plugin: plugins.split("\\x00")) { 1.461 + pluginsToCall.add(List.from(plugin.split("\\s+"))); 1.462 + } 1.463 + JavacTask task = null; 1.464 + Iterator<Plugin> iter = sl.iterator(); 1.465 + while (iter.hasNext()) { 1.466 + Plugin plugin = iter.next(); 1.467 + for (List<String> p: pluginsToCall) { 1.468 + if (plugin.getName().equals(p.head)) { 1.469 + pluginsToCall.remove(p); 1.470 + try { 1.471 + if (task == null) 1.472 + task = JavacTask.instance(pEnv); 1.473 + plugin.init(task, p.tail.toArray(new String[p.tail.size()])); 1.474 + } catch (Throwable ex) { 1.475 + if (apiMode) 1.476 + throw new RuntimeException(ex); 1.477 + pluginMessage(ex); 1.478 + return Result.SYSERR; 1.479 + } 1.480 + } 1.481 + } 1.482 + } 1.483 + for (List<String> p: pluginsToCall) { 1.484 + log.printLines(PrefixKind.JAVAC, "msg.plugin.not.found", p.head); 1.485 + } 1.486 + } 1.487 + 1.488 + comp = JavaCompiler.instance(context); 1.489 + 1.490 + // FIXME: this code will not be invoked if using JavacTask.parse/analyze/generate 1.491 + String xdoclint = options.get(XDOCLINT); 1.492 + String xdoclintCustom = options.get(XDOCLINT_CUSTOM); 1.493 + if (xdoclint != null || xdoclintCustom != null) { 1.494 + Set<String> doclintOpts = new LinkedHashSet<String>(); 1.495 + if (xdoclint != null) 1.496 + doclintOpts.add(DocLint.XMSGS_OPTION); 1.497 + if (xdoclintCustom != null) { 1.498 + for (String s: xdoclintCustom.split("\\s+")) { 1.499 + if (s.isEmpty()) 1.500 + continue; 1.501 + doclintOpts.add(s.replace(XDOCLINT_CUSTOM.text, DocLint.XMSGS_CUSTOM_PREFIX)); 1.502 + } 1.503 + } 1.504 + if (!(doclintOpts.size() == 1 1.505 + && doclintOpts.iterator().next().equals(DocLint.XMSGS_CUSTOM_PREFIX + "none"))) { 1.506 + JavacTask t = BasicJavacTask.instance(context); 1.507 + // standard doclet normally generates H1, H2 1.508 + doclintOpts.add(DocLint.XIMPLICIT_HEADERS + "2"); 1.509 + new DocLint().init(t, doclintOpts.toArray(new String[doclintOpts.size()])); 1.510 + comp.keepComments = true; 1.511 + } 1.512 + } 1.513 + 1.514 + fileManager = context.get(JavaFileManager.class); 1.515 + 1.516 + if (!files.isEmpty()) { 1.517 + // add filenames to fileObjects 1.518 + comp = JavaCompiler.instance(context); 1.519 + List<JavaFileObject> otherFiles = List.nil(); 1.520 + JavacFileManager dfm = (JavacFileManager)fileManager; 1.521 + for (JavaFileObject fo : dfm.getJavaFileObjectsFromFiles(files)) 1.522 + otherFiles = otherFiles.prepend(fo); 1.523 + for (JavaFileObject fo : otherFiles) 1.524 + fileObjects = fileObjects.prepend(fo); 1.525 + } 1.526 + comp.compile(fileObjects, 1.527 + classnames.toList(), 1.528 + processors); 1.529 + 1.530 + if (log.expectDiagKeys != null) { 1.531 + if (log.expectDiagKeys.isEmpty()) { 1.532 + log.printRawLines("all expected diagnostics found"); 1.533 + return Result.OK; 1.534 + } else { 1.535 + log.printRawLines("expected diagnostic keys not found: " + log.expectDiagKeys); 1.536 + return Result.ERROR; 1.537 + } 1.538 + } 1.539 + 1.540 + if (comp.errorCount() != 0) 1.541 + return Result.ERROR; 1.542 + } catch (IOException ex) { 1.543 + ioMessage(ex); 1.544 + return Result.SYSERR; 1.545 + } catch (OutOfMemoryError ex) { 1.546 + resourceMessage(ex); 1.547 + return Result.SYSERR; 1.548 + } catch (StackOverflowError ex) { 1.549 + resourceMessage(ex); 1.550 + return Result.SYSERR; 1.551 + } catch (FatalError ex) { 1.552 + feMessage(ex); 1.553 + return Result.SYSERR; 1.554 + } catch (AnnotationProcessingError ex) { 1.555 + if (apiMode) 1.556 + throw new RuntimeException(ex.getCause()); 1.557 + apMessage(ex); 1.558 + return Result.SYSERR; 1.559 + } catch (ClientCodeException ex) { 1.560 + // as specified by javax.tools.JavaCompiler#getTask 1.561 + // and javax.tools.JavaCompiler.CompilationTask#call 1.562 + throw new RuntimeException(ex.getCause()); 1.563 + } catch (PropagatedException ex) { 1.564 + throw ex.getCause(); 1.565 + } catch (Throwable ex) { 1.566 + // Nasty. If we've already reported an error, compensate 1.567 + // for buggy compiler error recovery by swallowing thrown 1.568 + // exceptions. 1.569 + if (comp == null || comp.errorCount() == 0 || 1.570 + options == null || options.isSet("dev")) 1.571 + bugMessage(ex); 1.572 + return Result.ABNORMAL; 1.573 + } finally { 1.574 + if (comp != null) { 1.575 + try { 1.576 + comp.close(); 1.577 + } catch (ClientCodeException ex) { 1.578 + throw new RuntimeException(ex.getCause()); 1.579 + } 1.580 + } 1.581 + filenames = null; 1.582 + options = null; 1.583 + } 1.584 + return Result.OK; 1.585 + } 1.586 + 1.587 + /** Print a message reporting an internal error. 1.588 + */ 1.589 + void bugMessage(Throwable ex) { 1.590 + log.printLines(PrefixKind.JAVAC, "msg.bug", JavaCompiler.version()); 1.591 + ex.printStackTrace(log.getWriter(WriterKind.NOTICE)); 1.592 + } 1.593 + 1.594 + /** Print a message reporting a fatal error. 1.595 + */ 1.596 + void feMessage(Throwable ex) { 1.597 + log.printRawLines(ex.getMessage()); 1.598 + if (ex.getCause() != null && options.isSet("dev")) { 1.599 + ex.getCause().printStackTrace(log.getWriter(WriterKind.NOTICE)); 1.600 + } 1.601 + } 1.602 + 1.603 + /** Print a message reporting an input/output error. 1.604 + */ 1.605 + void ioMessage(Throwable ex) { 1.606 + log.printLines(PrefixKind.JAVAC, "msg.io"); 1.607 + ex.printStackTrace(log.getWriter(WriterKind.NOTICE)); 1.608 + } 1.609 + 1.610 + /** Print a message reporting an out-of-resources error. 1.611 + */ 1.612 + void resourceMessage(Throwable ex) { 1.613 + log.printLines(PrefixKind.JAVAC, "msg.resource"); 1.614 + ex.printStackTrace(log.getWriter(WriterKind.NOTICE)); 1.615 + } 1.616 + 1.617 + /** Print a message reporting an uncaught exception from an 1.618 + * annotation processor. 1.619 + */ 1.620 + void apMessage(AnnotationProcessingError ex) { 1.621 + log.printLines(PrefixKind.JAVAC, "msg.proc.annotation.uncaught.exception"); 1.622 + ex.getCause().printStackTrace(log.getWriter(WriterKind.NOTICE)); 1.623 + } 1.624 + 1.625 + /** Print a message reporting an uncaught exception from an 1.626 + * annotation processor. 1.627 + */ 1.628 + void pluginMessage(Throwable ex) { 1.629 + log.printLines(PrefixKind.JAVAC, "msg.plugin.uncaught.exception"); 1.630 + ex.printStackTrace(log.getWriter(WriterKind.NOTICE)); 1.631 + } 1.632 + 1.633 + /** Display the location and checksum of a class. */ 1.634 + void showClass(String className) { 1.635 + PrintWriter pw = log.getWriter(WriterKind.NOTICE); 1.636 + pw.println("javac: show class: " + className); 1.637 + URL url = getClass().getResource('/' + className.replace('.', '/') + ".class"); 1.638 + if (url == null) 1.639 + pw.println(" class not found"); 1.640 + else { 1.641 + pw.println(" " + url); 1.642 + try { 1.643 + final String algorithm = "MD5"; 1.644 + byte[] digest; 1.645 + MessageDigest md = MessageDigest.getInstance(algorithm); 1.646 + DigestInputStream in = new DigestInputStream(url.openStream(), md); 1.647 + try { 1.648 + byte[] buf = new byte[8192]; 1.649 + int n; 1.650 + do { n = in.read(buf); } while (n > 0); 1.651 + digest = md.digest(); 1.652 + } finally { 1.653 + in.close(); 1.654 + } 1.655 + StringBuilder sb = new StringBuilder(); 1.656 + for (byte b: digest) 1.657 + sb.append(String.format("%02x", b)); 1.658 + pw.println(" " + algorithm + " checksum: " + sb); 1.659 + } catch (Exception e) { 1.660 + pw.println(" cannot compute digest: " + e); 1.661 + } 1.662 + } 1.663 + } 1.664 + 1.665 + private JavaFileManager fileManager; 1.666 + 1.667 + /* ************************************************************************ 1.668 + * Internationalization 1.669 + *************************************************************************/ 1.670 + 1.671 +// /** Find a localized string in the resource bundle. 1.672 +// * @param key The key for the localized string. 1.673 +// */ 1.674 +// public static String getLocalizedString(String key, Object... args) { // FIXME sb private 1.675 +// try { 1.676 +// if (messages == null) 1.677 +// messages = new JavacMessages(javacBundleName); 1.678 +// return messages.getLocalizedString("javac." + key, args); 1.679 +// } 1.680 +// catch (MissingResourceException e) { 1.681 +// throw new Error("Fatal Error: Resource for javac is missing", e); 1.682 +// } 1.683 +// } 1.684 +// 1.685 +// public static void useRawMessages(boolean enable) { 1.686 +// if (enable) { 1.687 +// messages = new JavacMessages(javacBundleName) { 1.688 +// @Override 1.689 +// public String getLocalizedString(String key, Object... args) { 1.690 +// return key; 1.691 +// } 1.692 +// }; 1.693 +// } else { 1.694 +// messages = new JavacMessages(javacBundleName); 1.695 +// } 1.696 +// } 1.697 + 1.698 + public static final String javacBundleName = 1.699 + "com.sun.tools.javac.resources.javac"; 1.700 +// 1.701 +// private static JavacMessages messages; 1.702 +}