src/share/classes/com/sun/tools/javah/JavahTask.java

Fri, 29 Oct 2010 13:12:38 -0700

author
jjg
date
Fri, 29 Oct 2010 13:12:38 -0700
changeset 728
895bea45a3e8
parent 712
a1d31ab7b525
child 1054
111bbf1ad913
permissions
-rw-r--r--

6994608: javah no longer accepts parameter files as input
Reviewed-by: mcimadamore

jjg@416 1 /*
jjg@694 2 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
jjg@416 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@416 4 *
jjg@416 5 * This code is free software; you can redistribute it and/or modify it
jjg@416 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
jjg@416 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
jjg@416 10 *
jjg@416 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@416 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@416 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@416 14 * version 2 for more details (a copy is included in the LICENSE file that
jjg@416 15 * accompanied this code).
jjg@416 16 *
jjg@416 17 * You should have received a copy of the GNU General Public License version
jjg@416 18 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@416 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@416 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.
jjg@416 24 */
jjg@416 25
jjg@416 26 package com.sun.tools.javah;
jjg@416 27
jjg@416 28 import java.io.File;
jjg@728 29 import java.io.FileNotFoundException;
jjg@416 30 import java.io.IOException;
jjg@416 31 import java.io.OutputStream;
jjg@416 32 import java.io.PrintWriter;
jjg@416 33 import java.io.Writer;
jjg@416 34 import java.text.MessageFormat;
jjg@416 35 import java.util.ArrayList;
jjg@416 36 import java.util.Arrays;
jjg@416 37 import java.util.Collections;
jjg@416 38 import java.util.HashMap;
jjg@416 39 import java.util.Iterator;
jjg@416 40 import java.util.LinkedHashSet;
jjg@416 41 import java.util.List;
jjg@416 42 import java.util.Locale;
jjg@416 43 import java.util.Map;
jjg@416 44 import java.util.MissingResourceException;
jjg@416 45 import java.util.ResourceBundle;
jjg@416 46 import java.util.Set;
jjg@416 47
jjg@416 48 import javax.annotation.processing.AbstractProcessor;
jjg@416 49 import javax.annotation.processing.Messager;
jjg@712 50 import javax.annotation.processing.ProcessingEnvironment;
jjg@416 51 import javax.annotation.processing.RoundEnvironment;
jjg@416 52 import javax.annotation.processing.SupportedAnnotationTypes;
jjg@416 53
jjg@416 54 import javax.lang.model.SourceVersion;
jjg@416 55 import javax.lang.model.element.ExecutableElement;
jjg@416 56 import javax.lang.model.element.TypeElement;
jjg@416 57 import javax.lang.model.element.VariableElement;
jjg@416 58 import javax.lang.model.type.ArrayType;
jjg@416 59 import javax.lang.model.type.DeclaredType;
jjg@416 60 import javax.lang.model.type.TypeMirror;
jjg@416 61 import javax.lang.model.type.TypeVisitor;
jjg@416 62 import javax.lang.model.util.ElementFilter;
darcy@575 63 import javax.lang.model.util.SimpleTypeVisitor7;
jjg@416 64 import javax.lang.model.util.Types;
jjg@416 65
jjg@416 66 import javax.tools.Diagnostic;
jjg@416 67 import javax.tools.DiagnosticListener;
jjg@416 68 import javax.tools.JavaCompiler;
jjg@416 69 import javax.tools.JavaCompiler.CompilationTask;
jjg@416 70 import javax.tools.JavaFileManager;
jjg@416 71 import javax.tools.JavaFileObject;
jjg@416 72 import javax.tools.StandardJavaFileManager;
jjg@416 73 import javax.tools.StandardLocation;
jjg@416 74 import javax.tools.ToolProvider;
jjg@712 75 import static javax.tools.Diagnostic.Kind.*;
jjg@712 76
jjg@712 77 import com.sun.tools.javac.code.Symbol.CompletionFailure;
jjg@728 78 import com.sun.tools.javac.main.CommandLine;
jjg@416 79
jjg@416 80 /**
jjg@416 81 * Javah generates support files for native methods.
jjg@416 82 * Parse commandline options & Invokes javadoc to execute those commands.
jjg@416 83 *
jjg@581 84 * <p><b>This is NOT part of any supported API.
jjg@416 85 * If you write code that depends on this, you do so at your own
jjg@416 86 * risk. This code and its internal interfaces are subject to change
jjg@416 87 * or deletion without notice.</b></p>
jjg@416 88 *
jjg@416 89 * @author Sucheta Dambalkar
jjg@416 90 * @author Jonathan Gibbons
jjg@416 91 */
jjg@416 92 public class JavahTask implements NativeHeaderTool.NativeHeaderTask {
jjg@416 93 public class BadArgs extends Exception {
jjg@416 94 private static final long serialVersionUID = 1479361270874789045L;
jjg@416 95 BadArgs(String key, Object... args) {
jjg@416 96 super(JavahTask.this.getMessage(key, args));
jjg@416 97 this.key = key;
jjg@416 98 this.args = args;
jjg@416 99 }
jjg@416 100
jjg@416 101 BadArgs showUsage(boolean b) {
jjg@416 102 showUsage = b;
jjg@416 103 return this;
jjg@416 104 }
jjg@416 105
jjg@416 106 final String key;
jjg@416 107 final Object[] args;
jjg@416 108 boolean showUsage;
jjg@416 109 }
jjg@416 110
jjg@416 111 static abstract class Option {
jjg@416 112 Option(boolean hasArg, String... aliases) {
jjg@416 113 this.hasArg = hasArg;
jjg@416 114 this.aliases = aliases;
jjg@416 115 }
jjg@416 116
jjg@416 117 boolean isHidden() {
jjg@416 118 return false;
jjg@416 119 }
jjg@416 120
jjg@416 121 boolean matches(String opt) {
jjg@416 122 for (String a: aliases) {
jjg@416 123 if (a.equals(opt))
jjg@416 124 return true;
jjg@416 125 }
jjg@416 126 return false;
jjg@416 127 }
jjg@416 128
jjg@416 129 boolean ignoreRest() {
jjg@416 130 return false;
jjg@416 131 }
jjg@416 132
jjg@416 133 abstract void process(JavahTask task, String opt, String arg) throws BadArgs;
jjg@416 134
jjg@416 135 final boolean hasArg;
jjg@416 136 final String[] aliases;
jjg@416 137 }
jjg@416 138
jjg@416 139 static abstract class HiddenOption extends Option {
jjg@416 140 HiddenOption(boolean hasArg, String... aliases) {
jjg@416 141 super(hasArg, aliases);
jjg@416 142 }
jjg@416 143
jjg@416 144 @Override
jjg@416 145 boolean isHidden() {
jjg@416 146 return true;
jjg@416 147 }
jjg@416 148 }
jjg@416 149
jjg@416 150 static Option[] recognizedOptions = {
jjg@416 151 new Option(true, "-o") {
jjg@416 152 void process(JavahTask task, String opt, String arg) {
jjg@416 153 task.ofile = new File(arg);
jjg@416 154 }
jjg@416 155 },
jjg@416 156
jjg@416 157 new Option(true, "-d") {
jjg@416 158 void process(JavahTask task, String opt, String arg) {
jjg@416 159 task.odir = new File(arg);
jjg@416 160 }
jjg@416 161 },
jjg@416 162
jjg@416 163 new HiddenOption(true, "-td") {
jjg@416 164 void process(JavahTask task, String opt, String arg) {
jjg@416 165 // ignored; for backwards compatibility
jjg@416 166 }
jjg@416 167 },
jjg@416 168
jjg@416 169 new HiddenOption(false, "-stubs") {
jjg@416 170 void process(JavahTask task, String opt, String arg) {
jjg@416 171 // ignored; for backwards compatibility
jjg@416 172 }
jjg@416 173 },
jjg@416 174
jjg@416 175 new Option(false, "-v", "-verbose") {
jjg@416 176 void process(JavahTask task, String opt, String arg) {
jjg@416 177 task.verbose = true;
jjg@416 178 }
jjg@416 179 },
jjg@416 180
jjg@707 181 new Option(false, "-h", "-help", "--help", "-?") {
jjg@416 182 void process(JavahTask task, String opt, String arg) {
jjg@416 183 task.help = true;
jjg@416 184 }
jjg@416 185 },
jjg@416 186
jjg@416 187 new HiddenOption(false, "-trace") {
jjg@416 188 void process(JavahTask task, String opt, String arg) {
jjg@416 189 task.trace = true;
jjg@416 190 }
jjg@416 191 },
jjg@416 192
jjg@416 193 new Option(false, "-version") {
jjg@416 194 void process(JavahTask task, String opt, String arg) {
jjg@416 195 task.version = true;
jjg@416 196 }
jjg@416 197 },
jjg@416 198
jjg@416 199 new HiddenOption(false, "-fullversion") {
jjg@416 200 void process(JavahTask task, String opt, String arg) {
jjg@416 201 task.fullVersion = true;
jjg@416 202 }
jjg@416 203 },
jjg@416 204
jjg@416 205 new Option(false, "-jni") {
jjg@416 206 void process(JavahTask task, String opt, String arg) {
jjg@416 207 task.jni = true;
jjg@416 208 }
jjg@416 209 },
jjg@416 210
jjg@416 211 new Option(false, "-force") {
jjg@416 212 void process(JavahTask task, String opt, String arg) {
jjg@416 213 task.force = true;
jjg@416 214 }
jjg@416 215 },
jjg@416 216
jjg@416 217 new HiddenOption(false, "-Xnew") {
jjg@416 218 void process(JavahTask task, String opt, String arg) {
jjg@416 219 // we're already using the new javah
jjg@416 220 }
jjg@416 221 },
jjg@416 222
jjg@416 223 new HiddenOption(false, "-old") {
jjg@416 224 void process(JavahTask task, String opt, String arg) {
jjg@416 225 task.old = true;
jjg@416 226 }
jjg@416 227 },
jjg@416 228
jjg@416 229 new HiddenOption(false, "-llni", "-Xllni") {
jjg@416 230 void process(JavahTask task, String opt, String arg) {
jjg@416 231 task.llni = true;
jjg@416 232 }
jjg@416 233 },
jjg@416 234
jjg@416 235 new HiddenOption(false, "-llnidouble") {
jjg@416 236 void process(JavahTask task, String opt, String arg) {
jjg@416 237 task.llni = true;
jjg@416 238 task.doubleAlign = true;
jjg@416 239 }
jjg@416 240 },
jjg@712 241
jjg@712 242 new HiddenOption(false) {
jjg@712 243 boolean matches(String opt) {
jjg@712 244 return opt.startsWith("-XD");
jjg@712 245 }
jjg@712 246 void process(JavahTask task, String opt, String arg) {
jjg@712 247 task.javac_extras.add(opt);
jjg@712 248 }
jjg@712 249 },
jjg@416 250 };
jjg@416 251
jjg@416 252 JavahTask() {
jjg@416 253 }
jjg@416 254
jjg@416 255 JavahTask(Writer out,
jjg@416 256 JavaFileManager fileManager,
jjg@416 257 DiagnosticListener<? super JavaFileObject> diagnosticListener,
jjg@416 258 Iterable<String> options,
jjg@416 259 Iterable<String> classes) {
jjg@416 260 this();
jjg@416 261 this.log = getPrintWriterForWriter(out);
jjg@416 262 this.fileManager = fileManager;
jjg@416 263 this.diagnosticListener = diagnosticListener;
jjg@416 264
jjg@416 265 try {
jjg@416 266 handleOptions(options, false);
jjg@416 267 } catch (BadArgs e) {
jjg@416 268 throw new IllegalArgumentException(e.getMessage());
jjg@416 269 }
jjg@416 270
jjg@416 271 this.classes = new ArrayList<String>();
jjg@508 272 if (classes != null) {
jjg@508 273 for (String classname: classes) {
jjg@508 274 classname.getClass(); // null-check
jjg@508 275 this.classes.add(classname);
jjg@508 276 }
jjg@416 277 }
jjg@416 278 }
jjg@416 279
jjg@416 280 public void setLocale(Locale locale) {
jjg@416 281 if (locale == null)
jjg@416 282 locale = Locale.getDefault();
jjg@416 283 task_locale = locale;
jjg@416 284 }
jjg@416 285
jjg@416 286 public void setLog(PrintWriter log) {
jjg@416 287 this.log = log;
jjg@416 288 }
jjg@416 289
jjg@416 290 public void setLog(OutputStream s) {
jjg@416 291 setLog(getPrintWriterForStream(s));
jjg@416 292 }
jjg@416 293
jjg@416 294 static PrintWriter getPrintWriterForStream(OutputStream s) {
jjg@416 295 return new PrintWriter(s, true);
jjg@416 296 }
jjg@416 297
jjg@416 298 static PrintWriter getPrintWriterForWriter(Writer w) {
jjg@416 299 if (w == null)
jjg@416 300 return getPrintWriterForStream(null);
jjg@416 301 else if (w instanceof PrintWriter)
jjg@416 302 return (PrintWriter) w;
jjg@416 303 else
jjg@416 304 return new PrintWriter(w, true);
jjg@416 305 }
jjg@416 306
jjg@416 307 public void setDiagnosticListener(DiagnosticListener<? super JavaFileObject> dl) {
jjg@416 308 diagnosticListener = dl;
jjg@416 309 }
jjg@416 310
jjg@416 311 public void setDiagnosticListener(OutputStream s) {
jjg@416 312 setDiagnosticListener(getDiagnosticListenerForStream(s));
jjg@416 313 }
jjg@416 314
jjg@416 315 private DiagnosticListener<JavaFileObject> getDiagnosticListenerForStream(OutputStream s) {
jjg@416 316 return getDiagnosticListenerForWriter(getPrintWriterForStream(s));
jjg@416 317 }
jjg@416 318
jjg@416 319 private DiagnosticListener<JavaFileObject> getDiagnosticListenerForWriter(Writer w) {
jjg@416 320 final PrintWriter pw = getPrintWriterForWriter(w);
jjg@416 321 return new DiagnosticListener<JavaFileObject> () {
jjg@416 322 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
jjg@416 323 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
jjg@416 324 pw.print(getMessage("err.prefix"));
jjg@416 325 pw.print(" ");
jjg@416 326 }
jjg@416 327 pw.println(diagnostic.getMessage(null));
jjg@416 328 }
jjg@416 329 };
jjg@416 330 }
jjg@416 331
jjg@416 332 int run(String[] args) {
jjg@416 333 try {
jjg@416 334 handleOptions(args);
jjg@416 335 boolean ok = run();
jjg@416 336 return ok ? 0 : 1;
jjg@416 337 } catch (BadArgs e) {
jjg@416 338 diagnosticListener.report(createDiagnostic(e.key, e.args));
jjg@416 339 return 1;
jjg@416 340 } catch (InternalError e) {
jjg@416 341 diagnosticListener.report(createDiagnostic("err.internal.error", e.getMessage()));
jjg@416 342 return 1;
jjg@712 343 } catch (Util.Exit e) {
jjg@712 344 return e.exitValue;
jjg@416 345 } finally {
jjg@416 346 log.flush();
jjg@416 347 }
jjg@416 348 }
jjg@416 349
jjg@416 350 public void handleOptions(String[] args) throws BadArgs {
jjg@416 351 handleOptions(Arrays.asList(args), true);
jjg@416 352 }
jjg@416 353
jjg@416 354 private void handleOptions(Iterable<String> args, boolean allowClasses) throws BadArgs {
jjg@416 355 if (log == null) {
jjg@416 356 log = getPrintWriterForStream(System.out);
jjg@416 357 if (diagnosticListener == null)
jjg@416 358 diagnosticListener = getDiagnosticListenerForStream(System.err);
jjg@416 359 } else {
jjg@416 360 if (diagnosticListener == null)
jjg@416 361 diagnosticListener = getDiagnosticListenerForWriter(log);
jjg@416 362 }
jjg@416 363
jjg@416 364 if (fileManager == null)
jjg@416 365 fileManager = getDefaultFileManager(diagnosticListener, log);
jjg@416 366
jjg@728 367 Iterator<String> iter = expandAtArgs(args).iterator();
jjg@529 368 noArgs = !iter.hasNext();
jjg@416 369
jjg@416 370 while (iter.hasNext()) {
jjg@416 371 String arg = iter.next();
jjg@416 372 if (arg.startsWith("-"))
jjg@416 373 handleOption(arg, iter);
jjg@416 374 else if (allowClasses) {
jjg@416 375 if (classes == null)
jjg@416 376 classes = new ArrayList<String>();
jjg@416 377 classes.add(arg);
jjg@416 378 while (iter.hasNext())
jjg@416 379 classes.add(iter.next());
jjg@416 380 } else
jjg@416 381 throw new BadArgs("err.unknown.option", arg).showUsage(true);
jjg@416 382 }
jjg@416 383
jjg@416 384 if ((classes == null || classes.size() == 0) &&
jjg@508 385 !(noArgs || help || version || fullVersion)) {
jjg@416 386 throw new BadArgs("err.no.classes.specified");
jjg@416 387 }
jjg@416 388
jjg@416 389 if (jni && llni)
jjg@416 390 throw new BadArgs("jni.llni.mixed");
jjg@416 391
jjg@416 392 if (odir != null && ofile != null)
jjg@416 393 throw new BadArgs("dir.file.mixed");
jjg@416 394 }
jjg@416 395
jjg@416 396 private void handleOption(String name, Iterator<String> rest) throws BadArgs {
jjg@416 397 for (Option o: recognizedOptions) {
jjg@416 398 if (o.matches(name)) {
jjg@416 399 if (o.hasArg) {
jjg@416 400 if (rest.hasNext())
jjg@416 401 o.process(this, name, rest.next());
jjg@416 402 else
jjg@416 403 throw new BadArgs("err.missing.arg", name).showUsage(true);
jjg@416 404 } else
jjg@416 405 o.process(this, name, null);
jjg@416 406
jjg@416 407 if (o.ignoreRest()) {
jjg@416 408 while (rest.hasNext())
jjg@416 409 rest.next();
jjg@416 410 }
jjg@416 411 return;
jjg@416 412 }
jjg@416 413 }
jjg@416 414
jjg@416 415 if (fileManager.handleOption(name, rest))
jjg@416 416 return;
jjg@416 417
jjg@416 418 throw new BadArgs("err.unknown.option", name).showUsage(true);
jjg@416 419 }
jjg@416 420
jjg@728 421 private Iterable<String> expandAtArgs(Iterable<String> args) throws BadArgs {
jjg@728 422 try {
jjg@728 423 List<String> l = new ArrayList<String>();
jjg@728 424 for (String arg: args) l.add(arg);
jjg@728 425 return Arrays.asList(CommandLine.parse(l.toArray(new String[l.size()])));
jjg@728 426 } catch (FileNotFoundException e) {
jjg@728 427 throw new BadArgs("at.args.file.not.found", e.getLocalizedMessage());
jjg@728 428 } catch (IOException e) {
jjg@728 429 throw new BadArgs("at.args.io.exception", e.getLocalizedMessage());
jjg@728 430 }
jjg@728 431 }
jjg@728 432
jjg@416 433 public Boolean call() {
jjg@416 434 return run();
jjg@416 435 }
jjg@416 436
jjg@416 437 public boolean run() throws Util.Exit {
jjg@416 438
jjg@416 439 Util util = new Util(log, diagnosticListener);
jjg@416 440
jjg@529 441 if (noArgs || help) {
jjg@416 442 showHelp();
jjg@529 443 return help; // treat noArgs as an error for purposes of exit code
jjg@416 444 }
jjg@416 445
jjg@416 446 if (version || fullVersion) {
jjg@416 447 showVersion(fullVersion);
jjg@416 448 return true;
jjg@416 449 }
jjg@416 450
jjg@416 451 util.verbose = verbose;
jjg@416 452
jjg@416 453 Gen g;
jjg@416 454
jjg@416 455 if (llni)
jjg@416 456 g = new LLNI(doubleAlign, util);
jjg@416 457 else {
jjg@416 458 // if (stubs)
jjg@416 459 // throw new BadArgs("jni.no.stubs");
jjg@416 460 g = new JNI(util);
jjg@416 461 }
jjg@416 462
jjg@416 463 if (ofile != null) {
jjg@416 464 if (!(fileManager instanceof StandardJavaFileManager)) {
jjg@416 465 diagnosticListener.report(createDiagnostic("err.cant.use.option.for.fm", "-o"));
jjg@416 466 return false;
jjg@416 467 }
jjg@416 468 Iterable<? extends JavaFileObject> iter =
jjg@416 469 ((StandardJavaFileManager) fileManager).getJavaFileObjectsFromFiles(Collections.singleton(ofile));
jjg@416 470 JavaFileObject fo = iter.iterator().next();
jjg@416 471 g.setOutFile(fo);
jjg@416 472 } else {
jjg@416 473 if (odir != null) {
jjg@416 474 if (!(fileManager instanceof StandardJavaFileManager)) {
jjg@416 475 diagnosticListener.report(createDiagnostic("err.cant.use.option.for.fm", "-d"));
jjg@416 476 return false;
jjg@416 477 }
jjg@416 478
jjg@416 479 if (!odir.exists())
jjg@416 480 if (!odir.mkdirs())
jjg@416 481 util.error("cant.create.dir", odir.toString());
jjg@416 482 try {
jjg@416 483 ((StandardJavaFileManager) fileManager).setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(odir));
jjg@416 484 } catch (IOException e) {
jjg@416 485 Object msg = e.getLocalizedMessage();
jjg@416 486 if (msg == null) {
jjg@416 487 msg = e;
jjg@416 488 }
jjg@416 489 diagnosticListener.report(createDiagnostic("err.ioerror", odir, msg));
jjg@416 490 return false;
jjg@416 491 }
jjg@416 492 }
jjg@416 493 g.setFileManager(fileManager);
jjg@416 494 }
jjg@416 495
jjg@416 496 /*
jjg@416 497 * Force set to false will turn off smarts about checking file
jjg@416 498 * content before writing.
jjg@416 499 */
jjg@416 500 g.setForce(force);
jjg@416 501
jjg@416 502 if (fileManager instanceof JavahFileManager)
jjg@416 503 ((JavahFileManager) fileManager).setIgnoreSymbolFile(true);
jjg@416 504
jjg@416 505 JavaCompiler c = ToolProvider.getSystemJavaCompiler();
jjg@712 506 List<String> opts = new ArrayList<String>();
jjg@712 507 opts.add("-proc:only");
jjg@712 508 opts.addAll(javac_extras);
jjg@416 509 CompilationTask t = c.getTask(log, fileManager, diagnosticListener, opts, internalize(classes), null);
jjg@416 510 JavahProcessor p = new JavahProcessor(g);
jjg@416 511 t.setProcessors(Collections.singleton(p));
jjg@416 512
jjg@416 513 boolean ok = t.call();
jjg@416 514 if (p.exit != null)
jjg@416 515 throw new Util.Exit(p.exit);
jjg@416 516 return ok;
jjg@416 517 }
jjg@416 518
jjg@416 519 private List<String> internalize(List<String> classes) {
jjg@416 520 List<String> l = new ArrayList<String>();
jjg@416 521 for (String c: classes) {
jjg@416 522 l.add(c.replace('$', '.'));
jjg@416 523 }
jjg@416 524 return l;
jjg@416 525 }
jjg@416 526
jjg@416 527 private List<File> pathToFiles(String path) {
jjg@416 528 List<File> files = new ArrayList<File>();
jjg@416 529 for (String f: path.split(File.pathSeparator)) {
jjg@416 530 if (f.length() > 0)
jjg@416 531 files.add(new File(f));
jjg@416 532 }
jjg@416 533 return files;
jjg@416 534 }
jjg@416 535
jjg@416 536 static StandardJavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
jjg@416 537 return JavahFileManager.create(dl, log);
jjg@416 538 }
jjg@416 539
jjg@416 540 private void showHelp() {
jjg@416 541 log.println(getMessage("main.usage", progname));
jjg@416 542 for (Option o: recognizedOptions) {
jjg@416 543 if (o.isHidden())
jjg@416 544 continue;
jjg@416 545 String name = o.aliases[0].substring(1); // there must always be at least one name
jjg@416 546 log.println(getMessage("main.opt." + name));
jjg@416 547 }
jjg@416 548 String[] fmOptions = { "-classpath", "-bootclasspath" };
jjg@416 549 for (String o: fmOptions) {
jjg@416 550 if (fileManager.isSupportedOption(o) == -1)
jjg@416 551 continue;
jjg@416 552 String name = o.substring(1);
jjg@416 553 log.println(getMessage("main.opt." + name));
jjg@416 554 }
jjg@416 555 log.println(getMessage("main.usage.foot"));
jjg@416 556 }
jjg@416 557
jjg@416 558 private void showVersion(boolean full) {
jjg@694 559 log.println(version(full));
jjg@416 560 }
jjg@416 561
jjg@416 562 private static final String versionRBName = "com.sun.tools.javah.resources.version";
jjg@416 563 private static ResourceBundle versionRB;
jjg@416 564
jjg@694 565 private String version(boolean full) {
jjg@694 566 String msgKey = (full ? "javah.fullVersion" : "javah.version");
jjg@694 567 String versionKey = (full ? "full" : "release");
jjg@694 568 // versionKey=product: mm.nn.oo[-milestone]
jjg@694 569 // versionKey=full: mm.mm.oo[-milestone]-build
jjg@416 570 if (versionRB == null) {
jjg@416 571 try {
jjg@416 572 versionRB = ResourceBundle.getBundle(versionRBName);
jjg@416 573 } catch (MissingResourceException e) {
jjg@416 574 return getMessage("version.resource.missing", System.getProperty("java.version"));
jjg@416 575 }
jjg@416 576 }
jjg@416 577 try {
jjg@694 578 return getMessage(msgKey, "javah", versionRB.getString(versionKey));
jjg@416 579 }
jjg@416 580 catch (MissingResourceException e) {
jjg@416 581 return getMessage("version.unknown", System.getProperty("java.version"));
jjg@416 582 }
jjg@416 583 }
jjg@416 584
jjg@416 585 private Diagnostic<JavaFileObject> createDiagnostic(final String key, final Object... args) {
jjg@416 586 return new Diagnostic<JavaFileObject>() {
jjg@416 587 public Kind getKind() {
jjg@416 588 return Diagnostic.Kind.ERROR;
jjg@416 589 }
jjg@416 590
jjg@416 591 public JavaFileObject getSource() {
jjg@416 592 return null;
jjg@416 593 }
jjg@416 594
jjg@416 595 public long getPosition() {
jjg@416 596 return Diagnostic.NOPOS;
jjg@416 597 }
jjg@416 598
jjg@416 599 public long getStartPosition() {
jjg@416 600 return Diagnostic.NOPOS;
jjg@416 601 }
jjg@416 602
jjg@416 603 public long getEndPosition() {
jjg@416 604 return Diagnostic.NOPOS;
jjg@416 605 }
jjg@416 606
jjg@416 607 public long getLineNumber() {
jjg@416 608 return Diagnostic.NOPOS;
jjg@416 609 }
jjg@416 610
jjg@416 611 public long getColumnNumber() {
jjg@416 612 return Diagnostic.NOPOS;
jjg@416 613 }
jjg@416 614
jjg@416 615 public String getCode() {
jjg@416 616 return key;
jjg@416 617 }
jjg@416 618
jjg@416 619 public String getMessage(Locale locale) {
jjg@416 620 return JavahTask.this.getMessage(locale, key, args);
jjg@416 621 }
jjg@416 622
jjg@416 623 };
jjg@728 624 }
jjg@416 625
jjg@416 626 private String getMessage(String key, Object... args) {
jjg@416 627 return getMessage(task_locale, key, args);
jjg@416 628 }
jjg@416 629
jjg@416 630 private String getMessage(Locale locale, String key, Object... args) {
jjg@416 631 if (bundles == null) {
jjg@416 632 // could make this a HashMap<Locale,SoftReference<ResourceBundle>>
jjg@416 633 // and for efficiency, keep a hard reference to the bundle for the task
jjg@416 634 // locale
jjg@416 635 bundles = new HashMap<Locale, ResourceBundle>();
jjg@416 636 }
jjg@416 637
jjg@416 638 if (locale == null)
jjg@416 639 locale = Locale.getDefault();
jjg@416 640
jjg@416 641 ResourceBundle b = bundles.get(locale);
jjg@416 642 if (b == null) {
jjg@416 643 try {
jjg@416 644 b = ResourceBundle.getBundle("com.sun.tools.javah.resources.l10n", locale);
jjg@416 645 bundles.put(locale, b);
jjg@416 646 } catch (MissingResourceException e) {
jjg@416 647 throw new InternalError("Cannot find javah resource bundle for locale " + locale, e);
jjg@416 648 }
jjg@416 649 }
jjg@416 650
jjg@416 651 try {
jjg@416 652 return MessageFormat.format(b.getString(key), args);
jjg@416 653 } catch (MissingResourceException e) {
jjg@416 654 return key;
jjg@416 655 //throw new InternalError(e, key);
jjg@416 656 }
jjg@416 657 }
jjg@416 658
jjg@416 659 File ofile;
jjg@416 660 File odir;
jjg@416 661 String bootcp;
jjg@416 662 String usercp;
jjg@416 663 List<String> classes;
jjg@416 664 boolean verbose;
jjg@529 665 boolean noArgs;
jjg@416 666 boolean help;
jjg@416 667 boolean trace;
jjg@416 668 boolean version;
jjg@416 669 boolean fullVersion;
jjg@416 670 boolean jni;
jjg@416 671 boolean llni;
jjg@416 672 boolean doubleAlign;
jjg@416 673 boolean force;
jjg@416 674 boolean old;
jjg@712 675 Set<String> javac_extras = new LinkedHashSet<String>();
jjg@416 676
jjg@416 677 PrintWriter log;
jjg@416 678 JavaFileManager fileManager;
jjg@416 679 DiagnosticListener<? super JavaFileObject> diagnosticListener;
jjg@416 680 Locale task_locale;
jjg@416 681 Map<Locale, ResourceBundle> bundles;
jjg@416 682
jjg@416 683 private static final String progname = "javah";
jjg@416 684
jjg@416 685 @SupportedAnnotationTypes("*")
jjg@416 686 class JavahProcessor extends AbstractProcessor {
jjg@712 687 private Messager messager;
jjg@712 688
jjg@416 689 JavahProcessor(Gen g) {
jjg@416 690 this.g = g;
jjg@416 691 }
jjg@416 692
jjg@712 693 @Override
jjg@712 694 public SourceVersion getSupportedSourceVersion() {
jjg@712 695 // since this is co-bundled with javac, we can assume it supports
jjg@712 696 // the latest source version
jjg@712 697 return SourceVersion.latest();
jjg@712 698 }
jjg@712 699
jjg@712 700 @Override
jjg@712 701 public void init(ProcessingEnvironment pEnv) {
jjg@712 702 super.init(pEnv);
jjg@712 703 messager = processingEnv.getMessager();
jjg@712 704 }
jjg@712 705
jjg@416 706 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
jjg@712 707 try {
jjg@712 708 Set<TypeElement> classes = getAllClasses(ElementFilter.typesIn(roundEnv.getRootElements()));
jjg@712 709 if (classes.size() > 0) {
jjg@712 710 checkMethodParameters(classes);
jjg@712 711 g.setProcessingEnvironment(processingEnv);
jjg@712 712 g.setClasses(classes);
jjg@712 713 g.run();
jjg@712 714 }
jjg@712 715 } catch (CompletionFailure cf) {
jjg@712 716 messager.printMessage(ERROR, getMessage("class.not.found", cf.sym.getQualifiedName().toString()));
jjg@712 717 } catch (ClassNotFoundException cnfe) {
jjg@712 718 messager.printMessage(ERROR, getMessage("class.not.found", cnfe.getMessage()));
jjg@712 719 } catch (IOException ioe) {
jjg@712 720 messager.printMessage(ERROR, getMessage("io.exception", ioe.getMessage()));
jjg@712 721 } catch (Util.Exit e) {
jjg@712 722 exit = e;
jjg@712 723 }
jjg@416 724
jjg@416 725 return true;
jjg@416 726 }
jjg@416 727
jjg@416 728 private Set<TypeElement> getAllClasses(Set<? extends TypeElement> classes) {
jjg@416 729 Set<TypeElement> allClasses = new LinkedHashSet<TypeElement>();
jjg@416 730 getAllClasses0(classes, allClasses);
jjg@416 731 return allClasses;
jjg@416 732 }
jjg@416 733
jjg@416 734 private void getAllClasses0(Iterable<? extends TypeElement> classes, Set<TypeElement> allClasses) {
jjg@416 735 for (TypeElement c: classes) {
jjg@416 736 allClasses.add(c);
jjg@416 737 getAllClasses0(ElementFilter.typesIn(c.getEnclosedElements()), allClasses);
jjg@416 738 }
jjg@416 739 }
jjg@416 740
jjg@416 741 // 4942232:
jjg@416 742 // check that classes exist for all the parameters of native methods
jjg@416 743 private void checkMethodParameters(Set<TypeElement> classes) {
jjg@416 744 Types types = processingEnv.getTypeUtils();
jjg@416 745 for (TypeElement te: classes) {
jjg@416 746 for (ExecutableElement ee: ElementFilter.methodsIn(te.getEnclosedElements())) {
jjg@416 747 for (VariableElement ve: ee.getParameters()) {
jjg@416 748 TypeMirror tm = ve.asType();
jjg@416 749 checkMethodParametersVisitor.visit(tm, types);
jjg@416 750 }
jjg@416 751 }
jjg@416 752 }
jjg@416 753 }
jjg@416 754
jjg@416 755 private TypeVisitor<Void,Types> checkMethodParametersVisitor =
darcy@575 756 new SimpleTypeVisitor7<Void,Types>() {
jjg@416 757 @Override
jjg@416 758 public Void visitArray(ArrayType t, Types types) {
jjg@416 759 visit(t.getComponentType(), types);
jjg@416 760 return null;
jjg@416 761 }
jjg@416 762 @Override
jjg@416 763 public Void visitDeclared(DeclaredType t, Types types) {
jjg@416 764 t.asElement().getKind(); // ensure class exists
jjg@416 765 for (TypeMirror st: types.directSupertypes(t))
jjg@416 766 visit(st, types);
jjg@416 767 return null;
jjg@416 768 }
jjg@416 769 };
jjg@416 770
jjg@416 771 private Gen g;
jjg@416 772 private Util.Exit exit;
jjg@416 773 }
jjg@416 774 }

mercurial