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

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

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