aoqi@0: /* aoqi@0: * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.tools.javah; aoqi@0: aoqi@0: import java.io.File; aoqi@0: import java.io.FileNotFoundException; aoqi@0: import java.io.IOException; aoqi@0: import java.io.OutputStream; aoqi@0: import java.io.PrintWriter; aoqi@0: import java.io.Writer; aoqi@0: import java.text.MessageFormat; aoqi@0: import java.util.ArrayList; aoqi@0: import java.util.Arrays; aoqi@0: import java.util.Collections; aoqi@0: import java.util.HashMap; aoqi@0: import java.util.Iterator; aoqi@0: import java.util.LinkedHashSet; aoqi@0: import java.util.List; aoqi@0: import java.util.Locale; aoqi@0: import java.util.Map; aoqi@0: import java.util.MissingResourceException; aoqi@0: import java.util.ResourceBundle; aoqi@0: import java.util.Set; aoqi@0: aoqi@0: import javax.annotation.processing.AbstractProcessor; aoqi@0: import javax.annotation.processing.Messager; aoqi@0: import javax.annotation.processing.ProcessingEnvironment; aoqi@0: import javax.annotation.processing.RoundEnvironment; aoqi@0: import javax.annotation.processing.SupportedAnnotationTypes; aoqi@0: aoqi@0: import javax.lang.model.SourceVersion; aoqi@0: import javax.lang.model.element.ExecutableElement; aoqi@0: import javax.lang.model.element.TypeElement; aoqi@0: import javax.lang.model.element.VariableElement; aoqi@0: import javax.lang.model.type.ArrayType; aoqi@0: import javax.lang.model.type.DeclaredType; aoqi@0: import javax.lang.model.type.TypeMirror; aoqi@0: import javax.lang.model.type.TypeVisitor; aoqi@0: import javax.lang.model.util.ElementFilter; aoqi@0: import javax.lang.model.util.SimpleTypeVisitor8; aoqi@0: import javax.lang.model.util.Types; aoqi@0: aoqi@0: import javax.tools.Diagnostic; aoqi@0: import javax.tools.DiagnosticListener; aoqi@0: import javax.tools.JavaCompiler; aoqi@0: import javax.tools.JavaCompiler.CompilationTask; aoqi@0: import javax.tools.JavaFileManager; aoqi@0: import javax.tools.JavaFileObject; aoqi@0: import javax.tools.StandardJavaFileManager; aoqi@0: import javax.tools.StandardLocation; aoqi@0: import javax.tools.ToolProvider; aoqi@0: import static javax.tools.Diagnostic.Kind.*; aoqi@0: aoqi@0: import com.sun.tools.javac.code.Symbol.CompletionFailure; aoqi@0: import com.sun.tools.javac.main.CommandLine; aoqi@0: aoqi@0: /** aoqi@0: * Javah generates support files for native methods. aoqi@0: * Parse commandline options and invokes javadoc to execute those commands. aoqi@0: * aoqi@0: *

This is NOT part of any supported API. aoqi@0: * If you write code that depends on this, you do so at your own aoqi@0: * risk. This code and its internal interfaces are subject to change aoqi@0: * or deletion without notice.

aoqi@0: * aoqi@0: * @author Sucheta Dambalkar aoqi@0: * @author Jonathan Gibbons aoqi@0: */ aoqi@0: public class JavahTask implements NativeHeaderTool.NativeHeaderTask { aoqi@0: public class BadArgs extends Exception { aoqi@0: private static final long serialVersionUID = 1479361270874789045L; aoqi@0: BadArgs(String key, Object... args) { aoqi@0: super(JavahTask.this.getMessage(key, args)); aoqi@0: this.key = key; aoqi@0: this.args = args; aoqi@0: } aoqi@0: aoqi@0: BadArgs showUsage(boolean b) { aoqi@0: showUsage = b; aoqi@0: return this; aoqi@0: } aoqi@0: aoqi@0: final String key; aoqi@0: final Object[] args; aoqi@0: boolean showUsage; aoqi@0: } aoqi@0: aoqi@0: static abstract class Option { aoqi@0: Option(boolean hasArg, String... aliases) { aoqi@0: this.hasArg = hasArg; aoqi@0: this.aliases = aliases; aoqi@0: } aoqi@0: aoqi@0: boolean isHidden() { aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: boolean matches(String opt) { aoqi@0: for (String a: aliases) { aoqi@0: if (a.equals(opt)) aoqi@0: return true; aoqi@0: } aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: boolean ignoreRest() { aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: abstract void process(JavahTask task, String opt, String arg) throws BadArgs; aoqi@0: aoqi@0: final boolean hasArg; aoqi@0: final String[] aliases; aoqi@0: } aoqi@0: aoqi@0: static abstract class HiddenOption extends Option { aoqi@0: HiddenOption(boolean hasArg, String... aliases) { aoqi@0: super(hasArg, aliases); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: boolean isHidden() { aoqi@0: return true; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: static final Option[] recognizedOptions = { aoqi@0: new Option(true, "-o") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: task.ofile = new File(arg); aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new Option(true, "-d") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: task.odir = new File(arg); aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new HiddenOption(true, "-td") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: // ignored; for backwards compatibility aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new HiddenOption(false, "-stubs") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: // ignored; for backwards compatibility aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new Option(false, "-v", "-verbose") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: task.verbose = true; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new Option(false, "-h", "-help", "--help", "-?") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: task.help = true; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new HiddenOption(false, "-trace") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: task.trace = true; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new Option(false, "-version") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: task.version = true; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new HiddenOption(false, "-fullversion") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: task.fullVersion = true; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new Option(false, "-jni") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: task.jni = true; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new Option(false, "-force") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: task.force = true; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new HiddenOption(false, "-Xnew") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: // we're already using the new javah aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new HiddenOption(false, "-llni", "-Xllni") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: task.llni = true; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new HiddenOption(false, "-llnidouble") { aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: task.llni = true; aoqi@0: task.doubleAlign = true; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: new HiddenOption(false) { aoqi@0: boolean matches(String opt) { aoqi@0: return opt.startsWith("-XD"); aoqi@0: } aoqi@0: void process(JavahTask task, String opt, String arg) { aoqi@0: task.javac_extras.add(opt); aoqi@0: } aoqi@0: }, aoqi@0: }; aoqi@0: aoqi@0: JavahTask() { aoqi@0: } aoqi@0: aoqi@0: JavahTask(Writer out, aoqi@0: JavaFileManager fileManager, aoqi@0: DiagnosticListener diagnosticListener, aoqi@0: Iterable options, aoqi@0: Iterable classes) { aoqi@0: this(); aoqi@0: this.log = getPrintWriterForWriter(out); aoqi@0: this.fileManager = fileManager; aoqi@0: this.diagnosticListener = diagnosticListener; aoqi@0: aoqi@0: try { aoqi@0: handleOptions(options, false); aoqi@0: } catch (BadArgs e) { aoqi@0: throw new IllegalArgumentException(e.getMessage()); aoqi@0: } aoqi@0: aoqi@0: this.classes = new ArrayList(); aoqi@0: if (classes != null) { aoqi@0: for (String classname: classes) { aoqi@0: classname.getClass(); // null-check aoqi@0: this.classes.add(classname); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public void setLocale(Locale locale) { aoqi@0: if (locale == null) aoqi@0: locale = Locale.getDefault(); aoqi@0: task_locale = locale; aoqi@0: } aoqi@0: aoqi@0: public void setLog(PrintWriter log) { aoqi@0: this.log = log; aoqi@0: } aoqi@0: aoqi@0: public void setLog(OutputStream s) { aoqi@0: setLog(getPrintWriterForStream(s)); aoqi@0: } aoqi@0: aoqi@0: static PrintWriter getPrintWriterForStream(OutputStream s) { aoqi@0: return new PrintWriter(s, true); aoqi@0: } aoqi@0: aoqi@0: static PrintWriter getPrintWriterForWriter(Writer w) { aoqi@0: if (w == null) aoqi@0: return getPrintWriterForStream(null); aoqi@0: else if (w instanceof PrintWriter) aoqi@0: return (PrintWriter) w; aoqi@0: else aoqi@0: return new PrintWriter(w, true); aoqi@0: } aoqi@0: aoqi@0: public void setDiagnosticListener(DiagnosticListener dl) { aoqi@0: diagnosticListener = dl; aoqi@0: } aoqi@0: aoqi@0: public void setDiagnosticListener(OutputStream s) { aoqi@0: setDiagnosticListener(getDiagnosticListenerForStream(s)); aoqi@0: } aoqi@0: aoqi@0: private DiagnosticListener getDiagnosticListenerForStream(OutputStream s) { aoqi@0: return getDiagnosticListenerForWriter(getPrintWriterForStream(s)); aoqi@0: } aoqi@0: aoqi@0: private DiagnosticListener getDiagnosticListenerForWriter(Writer w) { aoqi@0: final PrintWriter pw = getPrintWriterForWriter(w); aoqi@0: return new DiagnosticListener () { aoqi@0: public void report(Diagnostic diagnostic) { aoqi@0: if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { aoqi@0: pw.print(getMessage("err.prefix")); aoqi@0: pw.print(" "); aoqi@0: } aoqi@0: pw.println(diagnostic.getMessage(null)); aoqi@0: } aoqi@0: }; aoqi@0: } aoqi@0: aoqi@0: int run(String[] args) { aoqi@0: try { aoqi@0: handleOptions(args); aoqi@0: boolean ok = run(); aoqi@0: return ok ? 0 : 1; aoqi@0: } catch (BadArgs e) { aoqi@0: diagnosticListener.report(createDiagnostic(e.key, e.args)); aoqi@0: return 1; aoqi@0: } catch (InternalError e) { aoqi@0: diagnosticListener.report(createDiagnostic("err.internal.error", e.getMessage())); aoqi@0: return 1; aoqi@0: } catch (Util.Exit e) { aoqi@0: return e.exitValue; aoqi@0: } finally { aoqi@0: log.flush(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public void handleOptions(String[] args) throws BadArgs { aoqi@0: handleOptions(Arrays.asList(args), true); aoqi@0: } aoqi@0: aoqi@0: private void handleOptions(Iterable args, boolean allowClasses) throws BadArgs { aoqi@0: if (log == null) { aoqi@0: log = getPrintWriterForStream(System.out); aoqi@0: if (diagnosticListener == null) aoqi@0: diagnosticListener = getDiagnosticListenerForStream(System.err); aoqi@0: } else { aoqi@0: if (diagnosticListener == null) aoqi@0: diagnosticListener = getDiagnosticListenerForWriter(log); aoqi@0: } aoqi@0: aoqi@0: if (fileManager == null) aoqi@0: fileManager = getDefaultFileManager(diagnosticListener, log); aoqi@0: aoqi@0: Iterator iter = expandAtArgs(args).iterator(); aoqi@0: noArgs = !iter.hasNext(); aoqi@0: aoqi@0: while (iter.hasNext()) { aoqi@0: String arg = iter.next(); aoqi@0: if (arg.startsWith("-")) aoqi@0: handleOption(arg, iter); aoqi@0: else if (allowClasses) { aoqi@0: if (classes == null) aoqi@0: classes = new ArrayList(); aoqi@0: classes.add(arg); aoqi@0: while (iter.hasNext()) aoqi@0: classes.add(iter.next()); aoqi@0: } else aoqi@0: throw new BadArgs("err.unknown.option", arg).showUsage(true); aoqi@0: } aoqi@0: aoqi@0: if ((classes == null || classes.size() == 0) && aoqi@0: !(noArgs || help || version || fullVersion)) { aoqi@0: throw new BadArgs("err.no.classes.specified"); aoqi@0: } aoqi@0: aoqi@0: if (jni && llni) aoqi@0: throw new BadArgs("jni.llni.mixed"); aoqi@0: aoqi@0: if (odir != null && ofile != null) aoqi@0: throw new BadArgs("dir.file.mixed"); aoqi@0: } aoqi@0: aoqi@0: private void handleOption(String name, Iterator rest) throws BadArgs { aoqi@0: for (Option o: recognizedOptions) { aoqi@0: if (o.matches(name)) { aoqi@0: if (o.hasArg) { aoqi@0: if (rest.hasNext()) aoqi@0: o.process(this, name, rest.next()); aoqi@0: else aoqi@0: throw new BadArgs("err.missing.arg", name).showUsage(true); aoqi@0: } else aoqi@0: o.process(this, name, null); aoqi@0: aoqi@0: if (o.ignoreRest()) { aoqi@0: while (rest.hasNext()) aoqi@0: rest.next(); aoqi@0: } aoqi@0: return; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (fileManager.handleOption(name, rest)) aoqi@0: return; aoqi@0: aoqi@0: throw new BadArgs("err.unknown.option", name).showUsage(true); aoqi@0: } aoqi@0: aoqi@0: private Iterable expandAtArgs(Iterable args) throws BadArgs { aoqi@0: try { aoqi@0: List l = new ArrayList(); aoqi@0: for (String arg: args) l.add(arg); aoqi@0: return Arrays.asList(CommandLine.parse(l.toArray(new String[l.size()]))); aoqi@0: } catch (FileNotFoundException e) { aoqi@0: throw new BadArgs("at.args.file.not.found", e.getLocalizedMessage()); aoqi@0: } catch (IOException e) { aoqi@0: throw new BadArgs("at.args.io.exception", e.getLocalizedMessage()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public Boolean call() { aoqi@0: return run(); aoqi@0: } aoqi@0: aoqi@0: public boolean run() throws Util.Exit { aoqi@0: aoqi@0: Util util = new Util(log, diagnosticListener); aoqi@0: aoqi@0: if (noArgs || help) { aoqi@0: showHelp(); aoqi@0: return help; // treat noArgs as an error for purposes of exit code aoqi@0: } aoqi@0: aoqi@0: if (version || fullVersion) { aoqi@0: showVersion(fullVersion); aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: util.verbose = verbose; aoqi@0: aoqi@0: Gen g; aoqi@0: aoqi@0: if (llni) aoqi@0: g = new LLNI(doubleAlign, util); aoqi@0: else { aoqi@0: // if (stubs) aoqi@0: // throw new BadArgs("jni.no.stubs"); aoqi@0: g = new JNI(util); aoqi@0: } aoqi@0: aoqi@0: if (ofile != null) { aoqi@0: if (!(fileManager instanceof StandardJavaFileManager)) { aoqi@0: diagnosticListener.report(createDiagnostic("err.cant.use.option.for.fm", "-o")); aoqi@0: return false; aoqi@0: } aoqi@0: Iterable iter = aoqi@0: ((StandardJavaFileManager) fileManager).getJavaFileObjectsFromFiles(Collections.singleton(ofile)); aoqi@0: JavaFileObject fo = iter.iterator().next(); aoqi@0: g.setOutFile(fo); aoqi@0: } else { aoqi@0: if (odir != null) { aoqi@0: if (!(fileManager instanceof StandardJavaFileManager)) { aoqi@0: diagnosticListener.report(createDiagnostic("err.cant.use.option.for.fm", "-d")); aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: if (!odir.exists()) aoqi@0: if (!odir.mkdirs()) aoqi@0: util.error("cant.create.dir", odir.toString()); aoqi@0: try { aoqi@0: ((StandardJavaFileManager) fileManager).setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(odir)); aoqi@0: } catch (IOException e) { aoqi@0: Object msg = e.getLocalizedMessage(); aoqi@0: if (msg == null) { aoqi@0: msg = e; aoqi@0: } aoqi@0: diagnosticListener.report(createDiagnostic("err.ioerror", odir, msg)); aoqi@0: return false; aoqi@0: } aoqi@0: } aoqi@0: g.setFileManager(fileManager); aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Force set to false will turn off smarts about checking file aoqi@0: * content before writing. aoqi@0: */ aoqi@0: g.setForce(force); aoqi@0: aoqi@0: if (fileManager instanceof JavahFileManager) aoqi@0: ((JavahFileManager) fileManager).setSymbolFileEnabled(false); aoqi@0: aoqi@0: JavaCompiler c = ToolProvider.getSystemJavaCompiler(); aoqi@0: List opts = new ArrayList(); aoqi@0: opts.add("-proc:only"); aoqi@0: opts.addAll(javac_extras); aoqi@0: CompilationTask t = c.getTask(log, fileManager, diagnosticListener, opts, classes, null); aoqi@0: JavahProcessor p = new JavahProcessor(g); aoqi@0: t.setProcessors(Collections.singleton(p)); aoqi@0: aoqi@0: boolean ok = t.call(); aoqi@0: if (p.exit != null) aoqi@0: throw new Util.Exit(p.exit); aoqi@0: return ok; aoqi@0: } aoqi@0: aoqi@0: private List pathToFiles(String path) { aoqi@0: List files = new ArrayList(); aoqi@0: for (String f: path.split(File.pathSeparator)) { aoqi@0: if (f.length() > 0) aoqi@0: files.add(new File(f)); aoqi@0: } aoqi@0: return files; aoqi@0: } aoqi@0: aoqi@0: static StandardJavaFileManager getDefaultFileManager(final DiagnosticListener dl, PrintWriter log) { aoqi@0: return JavahFileManager.create(dl, log); aoqi@0: } aoqi@0: aoqi@0: private void showHelp() { aoqi@0: log.println(getMessage("main.usage", progname)); aoqi@0: for (Option o: recognizedOptions) { aoqi@0: if (o.isHidden()) aoqi@0: continue; aoqi@0: String name = o.aliases[0].substring(1); // there must always be at least one name aoqi@0: log.println(getMessage("main.opt." + name)); aoqi@0: } aoqi@0: String[] fmOptions = { "-classpath", "-cp", "-bootclasspath" }; aoqi@0: for (String o: fmOptions) { aoqi@0: if (fileManager.isSupportedOption(o) == -1) aoqi@0: continue; aoqi@0: String name = o.substring(1); aoqi@0: log.println(getMessage("main.opt." + name)); aoqi@0: } aoqi@0: log.println(getMessage("main.usage.foot")); aoqi@0: } aoqi@0: aoqi@0: private void showVersion(boolean full) { aoqi@0: log.println(version(full)); aoqi@0: } aoqi@0: aoqi@0: private static final String versionRBName = "com.sun.tools.javah.resources.version"; aoqi@0: private static ResourceBundle versionRB; aoqi@0: aoqi@0: private String version(boolean full) { aoqi@0: String msgKey = (full ? "javah.fullVersion" : "javah.version"); aoqi@0: String versionKey = (full ? "full" : "release"); aoqi@0: // versionKey=product: mm.nn.oo[-milestone] aoqi@0: // versionKey=full: mm.mm.oo[-milestone]-build aoqi@0: if (versionRB == null) { aoqi@0: try { aoqi@0: versionRB = ResourceBundle.getBundle(versionRBName); aoqi@0: } catch (MissingResourceException e) { aoqi@0: return getMessage("version.resource.missing", System.getProperty("java.version")); aoqi@0: } aoqi@0: } aoqi@0: try { aoqi@0: return getMessage(msgKey, "javah", versionRB.getString(versionKey)); aoqi@0: } aoqi@0: catch (MissingResourceException e) { aoqi@0: return getMessage("version.unknown", System.getProperty("java.version")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private Diagnostic createDiagnostic(final String key, final Object... args) { aoqi@0: return new Diagnostic() { aoqi@0: public Kind getKind() { aoqi@0: return Diagnostic.Kind.ERROR; aoqi@0: } aoqi@0: aoqi@0: public JavaFileObject getSource() { aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: public long getPosition() { aoqi@0: return Diagnostic.NOPOS; aoqi@0: } aoqi@0: aoqi@0: public long getStartPosition() { aoqi@0: return Diagnostic.NOPOS; aoqi@0: } aoqi@0: aoqi@0: public long getEndPosition() { aoqi@0: return Diagnostic.NOPOS; aoqi@0: } aoqi@0: aoqi@0: public long getLineNumber() { aoqi@0: return Diagnostic.NOPOS; aoqi@0: } aoqi@0: aoqi@0: public long getColumnNumber() { aoqi@0: return Diagnostic.NOPOS; aoqi@0: } aoqi@0: aoqi@0: public String getCode() { aoqi@0: return key; aoqi@0: } aoqi@0: aoqi@0: public String getMessage(Locale locale) { aoqi@0: return JavahTask.this.getMessage(locale, key, args); aoqi@0: } aoqi@0: aoqi@0: }; aoqi@0: } aoqi@0: aoqi@0: private String getMessage(String key, Object... args) { aoqi@0: return getMessage(task_locale, key, args); aoqi@0: } aoqi@0: aoqi@0: private String getMessage(Locale locale, String key, Object... args) { aoqi@0: if (bundles == null) { aoqi@0: // could make this a HashMap> aoqi@0: // and for efficiency, keep a hard reference to the bundle for the task aoqi@0: // locale aoqi@0: bundles = new HashMap(); aoqi@0: } aoqi@0: aoqi@0: if (locale == null) aoqi@0: locale = Locale.getDefault(); aoqi@0: aoqi@0: ResourceBundle b = bundles.get(locale); aoqi@0: if (b == null) { aoqi@0: try { aoqi@0: b = ResourceBundle.getBundle("com.sun.tools.javah.resources.l10n", locale); aoqi@0: bundles.put(locale, b); aoqi@0: } catch (MissingResourceException e) { aoqi@0: throw new InternalError("Cannot find javah resource bundle for locale " + locale, e); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: try { aoqi@0: return MessageFormat.format(b.getString(key), args); aoqi@0: } catch (MissingResourceException e) { aoqi@0: return key; aoqi@0: //throw new InternalError(e, key); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: File ofile; aoqi@0: File odir; aoqi@0: String bootcp; aoqi@0: String usercp; aoqi@0: List classes; aoqi@0: boolean verbose; aoqi@0: boolean noArgs; aoqi@0: boolean help; aoqi@0: boolean trace; aoqi@0: boolean version; aoqi@0: boolean fullVersion; aoqi@0: boolean jni; aoqi@0: boolean llni; aoqi@0: boolean doubleAlign; aoqi@0: boolean force; aoqi@0: Set javac_extras = new LinkedHashSet(); aoqi@0: aoqi@0: PrintWriter log; aoqi@0: JavaFileManager fileManager; aoqi@0: DiagnosticListener diagnosticListener; aoqi@0: Locale task_locale; aoqi@0: Map bundles; aoqi@0: aoqi@0: private static final String progname = "javah"; aoqi@0: aoqi@0: @SupportedAnnotationTypes("*") aoqi@0: class JavahProcessor extends AbstractProcessor { aoqi@0: private Messager messager; aoqi@0: aoqi@0: JavahProcessor(Gen g) { aoqi@0: this.g = g; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public SourceVersion getSupportedSourceVersion() { aoqi@0: // since this is co-bundled with javac, we can assume it supports aoqi@0: // the latest source version aoqi@0: return SourceVersion.latest(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void init(ProcessingEnvironment pEnv) { aoqi@0: super.init(pEnv); aoqi@0: messager = processingEnv.getMessager(); aoqi@0: } aoqi@0: aoqi@0: public boolean process(Set annotations, RoundEnvironment roundEnv) { aoqi@0: try { aoqi@0: Set classes = getAllClasses(ElementFilter.typesIn(roundEnv.getRootElements())); aoqi@0: if (classes.size() > 0) { aoqi@0: checkMethodParameters(classes); aoqi@0: g.setProcessingEnvironment(processingEnv); aoqi@0: g.setClasses(classes); aoqi@0: g.run(); aoqi@0: } aoqi@0: } catch (CompletionFailure cf) { aoqi@0: messager.printMessage(ERROR, getMessage("class.not.found", cf.sym.getQualifiedName().toString())); aoqi@0: } catch (ClassNotFoundException cnfe) { aoqi@0: messager.printMessage(ERROR, getMessage("class.not.found", cnfe.getMessage())); aoqi@0: } catch (IOException ioe) { aoqi@0: messager.printMessage(ERROR, getMessage("io.exception", ioe.getMessage())); aoqi@0: } catch (Util.Exit e) { aoqi@0: exit = e; aoqi@0: } aoqi@0: aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: private Set getAllClasses(Set classes) { aoqi@0: Set allClasses = new LinkedHashSet(); aoqi@0: getAllClasses0(classes, allClasses); aoqi@0: return allClasses; aoqi@0: } aoqi@0: aoqi@0: private void getAllClasses0(Iterable classes, Set allClasses) { aoqi@0: for (TypeElement c: classes) { aoqi@0: allClasses.add(c); aoqi@0: getAllClasses0(ElementFilter.typesIn(c.getEnclosedElements()), allClasses); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // 4942232: aoqi@0: // check that classes exist for all the parameters of native methods aoqi@0: private void checkMethodParameters(Set classes) { aoqi@0: Types types = processingEnv.getTypeUtils(); aoqi@0: for (TypeElement te: classes) { aoqi@0: for (ExecutableElement ee: ElementFilter.methodsIn(te.getEnclosedElements())) { aoqi@0: for (VariableElement ve: ee.getParameters()) { aoqi@0: TypeMirror tm = ve.asType(); aoqi@0: checkMethodParametersVisitor.visit(tm, types); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private TypeVisitor checkMethodParametersVisitor = aoqi@0: new SimpleTypeVisitor8() { aoqi@0: @Override aoqi@0: public Void visitArray(ArrayType t, Types types) { aoqi@0: visit(t.getComponentType(), types); aoqi@0: return null; aoqi@0: } aoqi@0: @Override aoqi@0: public Void visitDeclared(DeclaredType t, Types types) { aoqi@0: t.asElement().getKind(); // ensure class exists aoqi@0: for (TypeMirror st: types.directSupertypes(t)) aoqi@0: visit(st, types); aoqi@0: return null; aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: private Gen g; aoqi@0: private Util.Exit exit; aoqi@0: } aoqi@0: }