415N/A/*
1259N/A * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
415N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
415N/A *
415N/A * This code is free software; you can redistribute it and/or modify it
415N/A * under the terms of the GNU General Public License version 2 only, as
553N/A * published by the Free Software Foundation. Oracle designates this
415N/A * particular file as subject to the "Classpath" exception as provided
553N/A * by Oracle in the LICENSE file that accompanied this code.
415N/A *
415N/A * This code is distributed in the hope that it will be useful, but WITHOUT
415N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
415N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
415N/A * version 2 for more details (a copy is included in the LICENSE file that
415N/A * accompanied this code).
415N/A *
415N/A * You should have received a copy of the GNU General Public License version
415N/A * 2 along with this work; if not, write to the Free Software Foundation,
415N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
415N/A *
553N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
553N/A * or visit www.oracle.com if you need additional information or have any
553N/A * questions.
415N/A */
415N/A
415N/Apackage com.sun.tools.javah;
415N/A
415N/Aimport java.io.File;
727N/Aimport java.io.FileNotFoundException;
415N/Aimport java.io.IOException;
415N/Aimport java.io.OutputStream;
415N/Aimport java.io.PrintWriter;
415N/Aimport java.io.Writer;
415N/Aimport java.text.MessageFormat;
415N/Aimport java.util.ArrayList;
415N/Aimport java.util.Arrays;
415N/Aimport java.util.Collections;
415N/Aimport java.util.HashMap;
415N/Aimport java.util.Iterator;
415N/Aimport java.util.LinkedHashSet;
415N/Aimport java.util.List;
415N/Aimport java.util.Locale;
415N/Aimport java.util.Map;
415N/Aimport java.util.MissingResourceException;
415N/Aimport java.util.ResourceBundle;
415N/Aimport java.util.Set;
415N/A
415N/Aimport javax.annotation.processing.AbstractProcessor;
415N/Aimport javax.annotation.processing.Messager;
711N/Aimport javax.annotation.processing.ProcessingEnvironment;
415N/Aimport javax.annotation.processing.RoundEnvironment;
415N/Aimport javax.annotation.processing.SupportedAnnotationTypes;
415N/A
415N/Aimport javax.lang.model.SourceVersion;
415N/Aimport javax.lang.model.element.ExecutableElement;
415N/Aimport javax.lang.model.element.TypeElement;
415N/Aimport javax.lang.model.element.VariableElement;
415N/Aimport javax.lang.model.type.ArrayType;
415N/Aimport javax.lang.model.type.DeclaredType;
415N/Aimport javax.lang.model.type.TypeMirror;
415N/Aimport javax.lang.model.type.TypeVisitor;
415N/Aimport javax.lang.model.util.ElementFilter;
574N/Aimport javax.lang.model.util.SimpleTypeVisitor7;
415N/Aimport javax.lang.model.util.Types;
415N/A
415N/Aimport javax.tools.Diagnostic;
415N/Aimport javax.tools.DiagnosticListener;
415N/Aimport javax.tools.JavaCompiler;
415N/Aimport javax.tools.JavaCompiler.CompilationTask;
415N/Aimport javax.tools.JavaFileManager;
415N/Aimport javax.tools.JavaFileObject;
415N/Aimport javax.tools.StandardJavaFileManager;
415N/Aimport javax.tools.StandardLocation;
415N/Aimport javax.tools.ToolProvider;
711N/Aimport static javax.tools.Diagnostic.Kind.*;
711N/A
711N/Aimport com.sun.tools.javac.code.Symbol.CompletionFailure;
727N/Aimport com.sun.tools.javac.main.CommandLine;
415N/A
415N/A/**
415N/A * Javah generates support files for native methods.
415N/A * Parse commandline options & Invokes javadoc to execute those commands.
415N/A *
580N/A * <p><b>This is NOT part of any supported API.
415N/A * If you write code that depends on this, you do so at your own
415N/A * risk. This code and its internal interfaces are subject to change
415N/A * or deletion without notice.</b></p>
415N/A *
415N/A * @author Sucheta Dambalkar
415N/A * @author Jonathan Gibbons
415N/A */
415N/Apublic class JavahTask implements NativeHeaderTool.NativeHeaderTask {
415N/A public class BadArgs extends Exception {
415N/A private static final long serialVersionUID = 1479361270874789045L;
415N/A BadArgs(String key, Object... args) {
415N/A super(JavahTask.this.getMessage(key, args));
415N/A this.key = key;
415N/A this.args = args;
415N/A }
415N/A
415N/A BadArgs showUsage(boolean b) {
415N/A showUsage = b;
415N/A return this;
415N/A }
415N/A
415N/A final String key;
415N/A final Object[] args;
415N/A boolean showUsage;
415N/A }
415N/A
415N/A static abstract class Option {
415N/A Option(boolean hasArg, String... aliases) {
415N/A this.hasArg = hasArg;
415N/A this.aliases = aliases;
415N/A }
415N/A
415N/A boolean isHidden() {
415N/A return false;
415N/A }
415N/A
415N/A boolean matches(String opt) {
415N/A for (String a: aliases) {
415N/A if (a.equals(opt))
415N/A return true;
415N/A }
415N/A return false;
415N/A }
415N/A
415N/A boolean ignoreRest() {
415N/A return false;
415N/A }
415N/A
415N/A abstract void process(JavahTask task, String opt, String arg) throws BadArgs;
415N/A
415N/A final boolean hasArg;
415N/A final String[] aliases;
415N/A }
415N/A
415N/A static abstract class HiddenOption extends Option {
415N/A HiddenOption(boolean hasArg, String... aliases) {
415N/A super(hasArg, aliases);
415N/A }
415N/A
415N/A @Override
415N/A boolean isHidden() {
415N/A return true;
415N/A }
415N/A }
415N/A
415N/A static Option[] recognizedOptions = {
415N/A new Option(true, "-o") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A task.ofile = new File(arg);
415N/A }
415N/A },
415N/A
415N/A new Option(true, "-d") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A task.odir = new File(arg);
415N/A }
415N/A },
415N/A
415N/A new HiddenOption(true, "-td") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A // ignored; for backwards compatibility
415N/A }
415N/A },
415N/A
415N/A new HiddenOption(false, "-stubs") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A // ignored; for backwards compatibility
415N/A }
415N/A },
415N/A
415N/A new Option(false, "-v", "-verbose") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A task.verbose = true;
415N/A }
415N/A },
415N/A
706N/A new Option(false, "-h", "-help", "--help", "-?") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A task.help = true;
415N/A }
415N/A },
415N/A
415N/A new HiddenOption(false, "-trace") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A task.trace = true;
415N/A }
415N/A },
415N/A
415N/A new Option(false, "-version") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A task.version = true;
415N/A }
415N/A },
415N/A
415N/A new HiddenOption(false, "-fullversion") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A task.fullVersion = true;
415N/A }
415N/A },
415N/A
415N/A new Option(false, "-jni") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A task.jni = true;
415N/A }
415N/A },
415N/A
415N/A new Option(false, "-force") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A task.force = true;
415N/A }
415N/A },
415N/A
415N/A new HiddenOption(false, "-Xnew") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A // we're already using the new javah
415N/A }
415N/A },
415N/A
415N/A new HiddenOption(false, "-old") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A task.old = true;
415N/A }
415N/A },
415N/A
415N/A new HiddenOption(false, "-llni", "-Xllni") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A task.llni = true;
415N/A }
415N/A },
415N/A
415N/A new HiddenOption(false, "-llnidouble") {
415N/A void process(JavahTask task, String opt, String arg) {
415N/A task.llni = true;
415N/A task.doubleAlign = true;
415N/A }
415N/A },
711N/A
711N/A new HiddenOption(false) {
711N/A boolean matches(String opt) {
711N/A return opt.startsWith("-XD");
711N/A }
711N/A void process(JavahTask task, String opt, String arg) {
711N/A task.javac_extras.add(opt);
711N/A }
711N/A },
415N/A };
415N/A
415N/A JavahTask() {
415N/A }
415N/A
415N/A JavahTask(Writer out,
415N/A JavaFileManager fileManager,
415N/A DiagnosticListener<? super JavaFileObject> diagnosticListener,
415N/A Iterable<String> options,
415N/A Iterable<String> classes) {
415N/A this();
415N/A this.log = getPrintWriterForWriter(out);
415N/A this.fileManager = fileManager;
415N/A this.diagnosticListener = diagnosticListener;
415N/A
415N/A try {
415N/A handleOptions(options, false);
415N/A } catch (BadArgs e) {
415N/A throw new IllegalArgumentException(e.getMessage());
415N/A }
415N/A
415N/A this.classes = new ArrayList<String>();
507N/A if (classes != null) {
507N/A for (String classname: classes) {
507N/A classname.getClass(); // null-check
507N/A this.classes.add(classname);
507N/A }
415N/A }
415N/A }
415N/A
415N/A public void setLocale(Locale locale) {
415N/A if (locale == null)
415N/A locale = Locale.getDefault();
415N/A task_locale = locale;
415N/A }
415N/A
415N/A public void setLog(PrintWriter log) {
415N/A this.log = log;
415N/A }
415N/A
415N/A public void setLog(OutputStream s) {
415N/A setLog(getPrintWriterForStream(s));
415N/A }
415N/A
415N/A static PrintWriter getPrintWriterForStream(OutputStream s) {
415N/A return new PrintWriter(s, true);
415N/A }
415N/A
415N/A static PrintWriter getPrintWriterForWriter(Writer w) {
415N/A if (w == null)
415N/A return getPrintWriterForStream(null);
415N/A else if (w instanceof PrintWriter)
415N/A return (PrintWriter) w;
415N/A else
415N/A return new PrintWriter(w, true);
415N/A }
415N/A
415N/A public void setDiagnosticListener(DiagnosticListener<? super JavaFileObject> dl) {
415N/A diagnosticListener = dl;
415N/A }
415N/A
415N/A public void setDiagnosticListener(OutputStream s) {
415N/A setDiagnosticListener(getDiagnosticListenerForStream(s));
415N/A }
415N/A
415N/A private DiagnosticListener<JavaFileObject> getDiagnosticListenerForStream(OutputStream s) {
415N/A return getDiagnosticListenerForWriter(getPrintWriterForStream(s));
415N/A }
415N/A
415N/A private DiagnosticListener<JavaFileObject> getDiagnosticListenerForWriter(Writer w) {
415N/A final PrintWriter pw = getPrintWriterForWriter(w);
415N/A return new DiagnosticListener<JavaFileObject> () {
415N/A public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
415N/A if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
415N/A pw.print(getMessage("err.prefix"));
415N/A pw.print(" ");
415N/A }
415N/A pw.println(diagnostic.getMessage(null));
415N/A }
415N/A };
415N/A }
415N/A
415N/A int run(String[] args) {
415N/A try {
415N/A handleOptions(args);
415N/A boolean ok = run();
415N/A return ok ? 0 : 1;
415N/A } catch (BadArgs e) {
415N/A diagnosticListener.report(createDiagnostic(e.key, e.args));
415N/A return 1;
415N/A } catch (InternalError e) {
415N/A diagnosticListener.report(createDiagnostic("err.internal.error", e.getMessage()));
415N/A return 1;
711N/A } catch (Util.Exit e) {
711N/A return e.exitValue;
415N/A } finally {
415N/A log.flush();
415N/A }
415N/A }
415N/A
415N/A public void handleOptions(String[] args) throws BadArgs {
415N/A handleOptions(Arrays.asList(args), true);
415N/A }
415N/A
415N/A private void handleOptions(Iterable<String> args, boolean allowClasses) throws BadArgs {
415N/A if (log == null) {
415N/A log = getPrintWriterForStream(System.out);
415N/A if (diagnosticListener == null)
415N/A diagnosticListener = getDiagnosticListenerForStream(System.err);
415N/A } else {
415N/A if (diagnosticListener == null)
415N/A diagnosticListener = getDiagnosticListenerForWriter(log);
415N/A }
415N/A
415N/A if (fileManager == null)
415N/A fileManager = getDefaultFileManager(diagnosticListener, log);
415N/A
727N/A Iterator<String> iter = expandAtArgs(args).iterator();
528N/A noArgs = !iter.hasNext();
415N/A
415N/A while (iter.hasNext()) {
415N/A String arg = iter.next();
415N/A if (arg.startsWith("-"))
415N/A handleOption(arg, iter);
415N/A else if (allowClasses) {
415N/A if (classes == null)
415N/A classes = new ArrayList<String>();
415N/A classes.add(arg);
415N/A while (iter.hasNext())
415N/A classes.add(iter.next());
415N/A } else
415N/A throw new BadArgs("err.unknown.option", arg).showUsage(true);
415N/A }
415N/A
415N/A if ((classes == null || classes.size() == 0) &&
507N/A !(noArgs || help || version || fullVersion)) {
415N/A throw new BadArgs("err.no.classes.specified");
415N/A }
415N/A
415N/A if (jni && llni)
415N/A throw new BadArgs("jni.llni.mixed");
415N/A
415N/A if (odir != null && ofile != null)
415N/A throw new BadArgs("dir.file.mixed");
415N/A }
415N/A
415N/A private void handleOption(String name, Iterator<String> rest) throws BadArgs {
415N/A for (Option o: recognizedOptions) {
415N/A if (o.matches(name)) {
415N/A if (o.hasArg) {
415N/A if (rest.hasNext())
415N/A o.process(this, name, rest.next());
415N/A else
415N/A throw new BadArgs("err.missing.arg", name).showUsage(true);
415N/A } else
415N/A o.process(this, name, null);
415N/A
415N/A if (o.ignoreRest()) {
415N/A while (rest.hasNext())
415N/A rest.next();
415N/A }
415N/A return;
415N/A }
415N/A }
415N/A
415N/A if (fileManager.handleOption(name, rest))
415N/A return;
415N/A
415N/A throw new BadArgs("err.unknown.option", name).showUsage(true);
415N/A }
415N/A
727N/A private Iterable<String> expandAtArgs(Iterable<String> args) throws BadArgs {
727N/A try {
727N/A List<String> l = new ArrayList<String>();
727N/A for (String arg: args) l.add(arg);
727N/A return Arrays.asList(CommandLine.parse(l.toArray(new String[l.size()])));
727N/A } catch (FileNotFoundException e) {
727N/A throw new BadArgs("at.args.file.not.found", e.getLocalizedMessage());
727N/A } catch (IOException e) {
727N/A throw new BadArgs("at.args.io.exception", e.getLocalizedMessage());
727N/A }
727N/A }
727N/A
415N/A public Boolean call() {
415N/A return run();
415N/A }
415N/A
415N/A public boolean run() throws Util.Exit {
415N/A
415N/A Util util = new Util(log, diagnosticListener);
415N/A
528N/A if (noArgs || help) {
415N/A showHelp();
528N/A return help; // treat noArgs as an error for purposes of exit code
415N/A }
415N/A
415N/A if (version || fullVersion) {
415N/A showVersion(fullVersion);
415N/A return true;
415N/A }
415N/A
415N/A util.verbose = verbose;
415N/A
415N/A Gen g;
415N/A
415N/A if (llni)
415N/A g = new LLNI(doubleAlign, util);
415N/A else {
415N/A// if (stubs)
415N/A// throw new BadArgs("jni.no.stubs");
415N/A g = new JNI(util);
415N/A }
415N/A
415N/A if (ofile != null) {
415N/A if (!(fileManager instanceof StandardJavaFileManager)) {
415N/A diagnosticListener.report(createDiagnostic("err.cant.use.option.for.fm", "-o"));
415N/A return false;
415N/A }
415N/A Iterable<? extends JavaFileObject> iter =
415N/A ((StandardJavaFileManager) fileManager).getJavaFileObjectsFromFiles(Collections.singleton(ofile));
415N/A JavaFileObject fo = iter.iterator().next();
415N/A g.setOutFile(fo);
415N/A } else {
415N/A if (odir != null) {
415N/A if (!(fileManager instanceof StandardJavaFileManager)) {
415N/A diagnosticListener.report(createDiagnostic("err.cant.use.option.for.fm", "-d"));
415N/A return false;
415N/A }
415N/A
415N/A if (!odir.exists())
415N/A if (!odir.mkdirs())
415N/A util.error("cant.create.dir", odir.toString());
415N/A try {
415N/A ((StandardJavaFileManager) fileManager).setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(odir));
415N/A } catch (IOException e) {
415N/A Object msg = e.getLocalizedMessage();
415N/A if (msg == null) {
415N/A msg = e;
415N/A }
415N/A diagnosticListener.report(createDiagnostic("err.ioerror", odir, msg));
415N/A return false;
415N/A }
415N/A }
415N/A g.setFileManager(fileManager);
415N/A }
415N/A
415N/A /*
415N/A * Force set to false will turn off smarts about checking file
415N/A * content before writing.
415N/A */
415N/A g.setForce(force);
415N/A
415N/A if (fileManager instanceof JavahFileManager)
415N/A ((JavahFileManager) fileManager).setIgnoreSymbolFile(true);
415N/A
415N/A JavaCompiler c = ToolProvider.getSystemJavaCompiler();
711N/A List<String> opts = new ArrayList<String>();
711N/A opts.add("-proc:only");
711N/A opts.addAll(javac_extras);
1259N/A CompilationTask t = c.getTask(log, fileManager, diagnosticListener, opts, classes, null);
415N/A JavahProcessor p = new JavahProcessor(g);
415N/A t.setProcessors(Collections.singleton(p));
415N/A
415N/A boolean ok = t.call();
415N/A if (p.exit != null)
415N/A throw new Util.Exit(p.exit);
415N/A return ok;
415N/A }
415N/A
415N/A private List<File> pathToFiles(String path) {
415N/A List<File> files = new ArrayList<File>();
415N/A for (String f: path.split(File.pathSeparator)) {
415N/A if (f.length() > 0)
415N/A files.add(new File(f));
415N/A }
415N/A return files;
415N/A }
415N/A
415N/A static StandardJavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
415N/A return JavahFileManager.create(dl, log);
415N/A }
415N/A
415N/A private void showHelp() {
415N/A log.println(getMessage("main.usage", progname));
415N/A for (Option o: recognizedOptions) {
415N/A if (o.isHidden())
415N/A continue;
415N/A String name = o.aliases[0].substring(1); // there must always be at least one name
415N/A log.println(getMessage("main.opt." + name));
415N/A }
415N/A String[] fmOptions = { "-classpath", "-bootclasspath" };
415N/A for (String o: fmOptions) {
415N/A if (fileManager.isSupportedOption(o) == -1)
415N/A continue;
415N/A String name = o.substring(1);
415N/A log.println(getMessage("main.opt." + name));
415N/A }
415N/A log.println(getMessage("main.usage.foot"));
415N/A }
415N/A
415N/A private void showVersion(boolean full) {
693N/A log.println(version(full));
415N/A }
415N/A
415N/A private static final String versionRBName = "com.sun.tools.javah.resources.version";
415N/A private static ResourceBundle versionRB;
415N/A
693N/A private String version(boolean full) {
693N/A String msgKey = (full ? "javah.fullVersion" : "javah.version");
693N/A String versionKey = (full ? "full" : "release");
693N/A // versionKey=product: mm.nn.oo[-milestone]
693N/A // versionKey=full: mm.mm.oo[-milestone]-build
415N/A if (versionRB == null) {
415N/A try {
415N/A versionRB = ResourceBundle.getBundle(versionRBName);
415N/A } catch (MissingResourceException e) {
415N/A return getMessage("version.resource.missing", System.getProperty("java.version"));
415N/A }
415N/A }
415N/A try {
693N/A return getMessage(msgKey, "javah", versionRB.getString(versionKey));
415N/A }
415N/A catch (MissingResourceException e) {
415N/A return getMessage("version.unknown", System.getProperty("java.version"));
415N/A }
415N/A }
415N/A
415N/A private Diagnostic<JavaFileObject> createDiagnostic(final String key, final Object... args) {
415N/A return new Diagnostic<JavaFileObject>() {
415N/A public Kind getKind() {
415N/A return Diagnostic.Kind.ERROR;
415N/A }
415N/A
415N/A public JavaFileObject getSource() {
415N/A return null;
415N/A }
415N/A
415N/A public long getPosition() {
415N/A return Diagnostic.NOPOS;
415N/A }
415N/A
415N/A public long getStartPosition() {
415N/A return Diagnostic.NOPOS;
415N/A }
415N/A
415N/A public long getEndPosition() {
415N/A return Diagnostic.NOPOS;
415N/A }
415N/A
415N/A public long getLineNumber() {
415N/A return Diagnostic.NOPOS;
415N/A }
415N/A
415N/A public long getColumnNumber() {
415N/A return Diagnostic.NOPOS;
415N/A }
415N/A
415N/A public String getCode() {
415N/A return key;
415N/A }
415N/A
415N/A public String getMessage(Locale locale) {
415N/A return JavahTask.this.getMessage(locale, key, args);
415N/A }
415N/A
415N/A };
727N/A }
415N/A
415N/A private String getMessage(String key, Object... args) {
415N/A return getMessage(task_locale, key, args);
415N/A }
415N/A
415N/A private String getMessage(Locale locale, String key, Object... args) {
415N/A if (bundles == null) {
415N/A // could make this a HashMap<Locale,SoftReference<ResourceBundle>>
415N/A // and for efficiency, keep a hard reference to the bundle for the task
415N/A // locale
415N/A bundles = new HashMap<Locale, ResourceBundle>();
415N/A }
415N/A
415N/A if (locale == null)
415N/A locale = Locale.getDefault();
415N/A
415N/A ResourceBundle b = bundles.get(locale);
415N/A if (b == null) {
415N/A try {
415N/A b = ResourceBundle.getBundle("com.sun.tools.javah.resources.l10n", locale);
415N/A bundles.put(locale, b);
415N/A } catch (MissingResourceException e) {
415N/A throw new InternalError("Cannot find javah resource bundle for locale " + locale, e);
415N/A }
415N/A }
415N/A
415N/A try {
415N/A return MessageFormat.format(b.getString(key), args);
415N/A } catch (MissingResourceException e) {
415N/A return key;
415N/A //throw new InternalError(e, key);
415N/A }
415N/A }
415N/A
415N/A File ofile;
415N/A File odir;
415N/A String bootcp;
415N/A String usercp;
415N/A List<String> classes;
415N/A boolean verbose;
528N/A boolean noArgs;
415N/A boolean help;
415N/A boolean trace;
415N/A boolean version;
415N/A boolean fullVersion;
415N/A boolean jni;
415N/A boolean llni;
415N/A boolean doubleAlign;
415N/A boolean force;
415N/A boolean old;
711N/A Set<String> javac_extras = new LinkedHashSet<String>();
415N/A
415N/A PrintWriter log;
415N/A JavaFileManager fileManager;
415N/A DiagnosticListener<? super JavaFileObject> diagnosticListener;
415N/A Locale task_locale;
415N/A Map<Locale, ResourceBundle> bundles;
415N/A
415N/A private static final String progname = "javah";
415N/A
415N/A @SupportedAnnotationTypes("*")
415N/A class JavahProcessor extends AbstractProcessor {
711N/A private Messager messager;
711N/A
415N/A JavahProcessor(Gen g) {
415N/A this.g = g;
415N/A }
415N/A
711N/A @Override
711N/A public SourceVersion getSupportedSourceVersion() {
711N/A // since this is co-bundled with javac, we can assume it supports
711N/A // the latest source version
711N/A return SourceVersion.latest();
711N/A }
711N/A
711N/A @Override
711N/A public void init(ProcessingEnvironment pEnv) {
711N/A super.init(pEnv);
711N/A messager = processingEnv.getMessager();
711N/A }
415N/A
711N/A public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
711N/A try {
711N/A Set<TypeElement> classes = getAllClasses(ElementFilter.typesIn(roundEnv.getRootElements()));
711N/A if (classes.size() > 0) {
711N/A checkMethodParameters(classes);
711N/A g.setProcessingEnvironment(processingEnv);
711N/A g.setClasses(classes);
415N/A g.run();
415N/A }
711N/A } catch (CompletionFailure cf) {
711N/A messager.printMessage(ERROR, getMessage("class.not.found", cf.sym.getQualifiedName().toString()));
711N/A } catch (ClassNotFoundException cnfe) {
711N/A messager.printMessage(ERROR, getMessage("class.not.found", cnfe.getMessage()));
711N/A } catch (IOException ioe) {
711N/A messager.printMessage(ERROR, getMessage("io.exception", ioe.getMessage()));
711N/A } catch (Util.Exit e) {
711N/A exit = e;
415N/A }
711N/A
415N/A return true;
415N/A }
415N/A
415N/A private Set<TypeElement> getAllClasses(Set<? extends TypeElement> classes) {
415N/A Set<TypeElement> allClasses = new LinkedHashSet<TypeElement>();
415N/A getAllClasses0(classes, allClasses);
415N/A return allClasses;
415N/A }
415N/A
415N/A private void getAllClasses0(Iterable<? extends TypeElement> classes, Set<TypeElement> allClasses) {
415N/A for (TypeElement c: classes) {
415N/A allClasses.add(c);
415N/A getAllClasses0(ElementFilter.typesIn(c.getEnclosedElements()), allClasses);
415N/A }
415N/A }
415N/A
415N/A // 4942232:
415N/A // check that classes exist for all the parameters of native methods
415N/A private void checkMethodParameters(Set<TypeElement> classes) {
415N/A Types types = processingEnv.getTypeUtils();
415N/A for (TypeElement te: classes) {
415N/A for (ExecutableElement ee: ElementFilter.methodsIn(te.getEnclosedElements())) {
415N/A for (VariableElement ve: ee.getParameters()) {
415N/A TypeMirror tm = ve.asType();
415N/A checkMethodParametersVisitor.visit(tm, types);
415N/A }
415N/A }
415N/A }
415N/A }
415N/A
415N/A private TypeVisitor<Void,Types> checkMethodParametersVisitor =
574N/A new SimpleTypeVisitor7<Void,Types>() {
415N/A @Override
415N/A public Void visitArray(ArrayType t, Types types) {
415N/A visit(t.getComponentType(), types);
415N/A return null;
415N/A }
415N/A @Override
415N/A public Void visitDeclared(DeclaredType t, Types types) {
415N/A t.asElement().getKind(); // ensure class exists
415N/A for (TypeMirror st: types.directSupertypes(t))
415N/A visit(st, types);
415N/A return null;
415N/A }
415N/A };
415N/A
415N/A private Gen g;
415N/A private Util.Exit exit;
415N/A }
415N/A}