001    /*
002     * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package javax.tools;
027    
028    import java.io.File;
029    import java.io.InputStream;
030    import java.io.Writer;
031    import java.nio.charset.Charset;
032    import java.util.List;
033    import java.util.Locale;
034    import java.util.concurrent.Callable;
035    import javax.annotation.processing.Processor;
036    
037    /**
038     * Interface to invoke Java™ programming language compilers from
039     * programs.
040     *
041     * <p>The compiler might generate diagnostics during compilation (for
042     * example, error messages).  If a diagnostic listener is provided,
043     * the diagnostics will be supplied to the listener.  If no listener
044     * is provided, the diagnostics will be formatted in an unspecified
045     * format and written to the default output, which is {@code
046     * System.err} unless otherwise specified.  Even if a diagnostic
047     * listener is supplied, some diagnostics might not fit in a {@code
048     * Diagnostic} and will be written to the default output.
049     *
050     * <p>A compiler tool has an associated standard file manager, which
051     * is the file manager that is native to the tool (or built-in).  The
052     * standard file manager can be obtained by calling {@linkplain
053     * #getStandardFileManager getStandardFileManager}.
054     *
055     * <p>A compiler tool must function with any file manager as long as
056     * any additional requirements as detailed in the methods below are
057     * met.  If no file manager is provided, the compiler tool will use a
058     * standard file manager such as the one returned by {@linkplain
059     * #getStandardFileManager getStandardFileManager}.
060     *
061     * <p>An instance implementing this interface must conform to the Java
062     * Language Specification and generate class files conforming to the
063     * Java Virtual Machine specification.  The versions of these
064     * specifications are defined in the {@linkplain Tool} interface.
065     *
066     * Additionally, an instance of this interface supporting {@link
067     * javax.lang.model.SourceVersion#RELEASE_6 SourceVersion.RELEASE_6}
068     * or higher must also support {@linkplain javax.annotation.processing
069     * annotation processing}.
070     *
071     * <p>The compiler relies on two services: {@linkplain
072     * DiagnosticListener diagnostic listener} and {@linkplain
073     * JavaFileManager file manager}.  Although most classes and
074     * interfaces in this package defines an API for compilers (and
075     * tools in general) the interfaces {@linkplain DiagnosticListener},
076     * {@linkplain JavaFileManager}, {@linkplain FileObject}, and
077     * {@linkplain JavaFileObject} are not intended to be used in
078     * applications.  Instead these interfaces are intended to be
079     * implemented and used to provide customized services for a
080     * compiler and thus defines an SPI for compilers.
081     *
082     * <p>There are a number of classes and interfaces in this package
083     * which are designed to ease the implementation of the SPI to
084     * customize the behavior of a compiler:
085     *
086     * <dl>
087     *   <dt>{@link StandardJavaFileManager}</dt>
088     *   <dd>
089     *
090     *     Every compiler which implements this interface provides a
091     *     standard file manager for operating on regular {@linkplain
092     *     java.io.File files}.  The StandardJavaFileManager interface
093     *     defines additional methods for creating file objects from
094     *     regular files.
095     *
096     *     <p>The standard file manager serves two purposes:
097     *
098     *     <ul>
099     *       <li>basic building block for customizing how a compiler reads
100     *       and writes files</li>
101     *       <li>sharing between multiple compilation tasks</li>
102     *     </ul>
103     *
104     *     <p>Reusing a file manager can potentially reduce overhead of
105     *     scanning the file system and reading jar files.  Although there
106     *     might be no reduction in overhead, a standard file manager must
107     *     work with multiple sequential compilations making the following
108     *     example a recommended coding pattern:
109     *
110     *     <pre>
111     *       Files[] files1 = ... ; // input for first compilation task
112     *       Files[] files2 = ... ; // input for second compilation task
113     *
114     *       JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
115     *       StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
116     *
117     *       {@code Iterable<? extends JavaFileObject>} compilationUnits1 =
118     *           fileManager.getJavaFileObjectsFromFiles({@linkplain java.util.Arrays#asList Arrays.asList}(files1));
119     *       compiler.getTask(null, fileManager, null, null, null, compilationUnits1).call();
120     *
121     *       {@code Iterable<? extends JavaFileObject>} compilationUnits2 =
122     *           fileManager.getJavaFileObjects(files2); // use alternative method
123     *       // reuse the same file manager to allow caching of jar files
124     *       compiler.getTask(null, fileManager, null, null, null, compilationUnits2).call();
125     *
126     *       fileManager.close();</pre>
127     *
128     *   </dd>
129     *
130     *   <dt>{@link DiagnosticCollector}</dt>
131     *   <dd>
132     *     Used to collect diagnostics in a list, for example:
133     *     <pre>
134     *       {@code Iterable<? extends JavaFileObject>} compilationUnits = ...;
135     *       JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
136     *       {@code DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();}
137     *       StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
138     *       compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits).call();
139     *
140     *       for (Diagnostic diagnostic : diagnostics.getDiagnostics())
141     *           System.out.format("Error on line %d in %d%n",
142     *                             diagnostic.getLineNumber()
143     *                             diagnostic.getSource().toUri());
144     *
145     *       fileManager.close();</pre>
146     *   </dd>
147     *
148     *   <dt>
149     *     {@link ForwardingJavaFileManager}, {@link ForwardingFileObject}, and
150     *     {@link ForwardingJavaFileObject}
151     *   </dt>
152     *   <dd>
153     *
154     *     Subclassing is not available for overriding the behavior of a
155     *     standard file manager as it is created by calling a method on a
156     *     compiler, not by invoking a constructor.  Instead forwarding
157     *     (or delegation) should be used.  These classes makes it easy to
158     *     forward most calls to a given file manager or file object while
159     *     allowing customizing behavior.  For example, consider how to
160     *     log all calls to {@linkplain JavaFileManager#flush}:
161     *
162     *     <pre>
163     *       final {@linkplain java.util.logging.Logger Logger} logger = ...;
164     *       {@code Iterable<? extends JavaFileObject>} compilationUnits = ...;
165     *       JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
166     *       StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, null, null);
167     *       JavaFileManager fileManager = new ForwardingJavaFileManager(stdFileManager) {
168     *           public void flush() {
169     *               logger.entering(StandardJavaFileManager.class.getName(), "flush");
170     *               super.flush();
171     *               logger.exiting(StandardJavaFileManager.class.getName(), "flush");
172     *           }
173     *       };
174     *       compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();</pre>
175     *   </dd>
176     *
177     *   <dt>{@link SimpleJavaFileObject}</dt>
178     *   <dd>
179     *
180     *     This class provides a basic file object implementation which
181     *     can be used as building block for creating file objects.  For
182     *     example, here is how to define a file object which represent
183     *     source code stored in a string:
184     *
185     *     <pre>
186     *       /**
187     *        * A file object used to represent source coming from a string.
188     *        {@code *}/
189     *       public class JavaSourceFromString extends SimpleJavaFileObject {
190     *           /**
191     *            * The source code of this "file".
192     *            {@code *}/
193     *           final String code;
194     *
195     *           /**
196     *            * Constructs a new JavaSourceFromString.
197     *            * {@code @}param name the name of the compilation unit represented by this file object
198     *            * {@code @}param code the source code for the compilation unit represented by this file object
199     *            {@code *}/
200     *           JavaSourceFromString(String name, String code) {
201     *               super({@linkplain java.net.URI#create URI.create}("string:///" + name.replace('.','/') + Kind.SOURCE.extension),
202     *                     Kind.SOURCE);
203     *               this.code = code;
204     *           }
205     *
206     *           {@code @}Override
207     *           public CharSequence getCharContent(boolean ignoreEncodingErrors) {
208     *               return code;
209     *           }
210     *       }</pre>
211     *   </dd>
212     * </dl>
213     *
214     * @author Peter von der Ah&eacute;
215     * @author Jonathan Gibbons
216     * @see DiagnosticListener
217     * @see Diagnostic
218     * @see JavaFileManager
219     * @since 1.6
220     */
221    public interface JavaCompiler extends Tool, OptionChecker {
222    
223        /**
224         * Creates a future for a compilation task with the given
225         * components and arguments.  The compilation might not have
226         * completed as described in the CompilationTask interface.
227         *
228         * <p>If a file manager is provided, it must be able to handle all
229         * locations defined in {@link StandardLocation}.
230         *
231         * @param out a Writer for additional output from the compiler;
232         * use {@code System.err} if {@code null}
233         * @param fileManager a file manager; if {@code null} use the
234         * compiler's standard filemanager
235         * @param diagnosticListener a diagnostic listener; if {@code
236         * null} use the compiler's default method for reporting
237         * diagnostics
238         * @param options compiler options, {@code null} means no options
239         * @param classes class names (for annotation processing), {@code
240         * null} means no class names
241         * @param compilationUnits the compilation units to compile, {@code
242         * null} means no compilation units
243         * @return an object representing the compilation
244         * @throws RuntimeException if an unrecoverable error
245         * occurred in a user supplied component.  The
246         * {@linkplain Throwable#getCause() cause} will be the error in
247         * user code.
248         * @throws IllegalArgumentException if any of the given
249         * compilation units are of other kind than
250         * {@linkplain JavaFileObject.Kind#SOURCE source}
251         */
252        CompilationTask getTask(Writer out,
253                                JavaFileManager fileManager,
254                                DiagnosticListener<? super JavaFileObject> diagnosticListener,
255                                Iterable<String> options,
256                                Iterable<String> classes,
257                                Iterable<? extends JavaFileObject> compilationUnits);
258    
259        /**
260         * Gets a new instance of the standard file manager implementation
261         * for this tool.  The file manager will use the given diagnostic
262         * listener for producing any non-fatal diagnostics.  Fatal errors
263         * will be signalled with the appropriate exceptions.
264         *
265         * <p>The standard file manager will be automatically reopened if
266         * it is accessed after calls to {@code flush} or {@code close}.
267         * The standard file manager must be usable with other tools.
268         *
269         * @param diagnosticListener a diagnostic listener for non-fatal
270         * diagnostics; if {@code null} use the compiler's default method
271         * for reporting diagnostics
272         * @param locale the locale to apply when formatting diagnostics;
273         * {@code null} means the {@linkplain Locale#getDefault() default locale}.
274         * @param charset the character set used for decoding bytes; if
275         * {@code null} use the platform default
276         * @return the standard file manager
277         */
278        StandardJavaFileManager getStandardFileManager(
279            DiagnosticListener<? super JavaFileObject> diagnosticListener,
280            Locale locale,
281            Charset charset);
282    
283        /**
284         * Interface representing a future for a compilation task.  The
285         * compilation task has not yet started.  To start the task, call
286         * the {@linkplain #call call} method.
287         *
288         * <p>Before calling the call method, additional aspects of the
289         * task can be configured, for example, by calling the
290         * {@linkplain #setProcessors setProcessors} method.
291         */
292        interface CompilationTask extends Callable<Boolean> {
293    
294            /**
295             * Sets processors (for annotation processing).  This will
296             * bypass the normal discovery mechanism.
297             *
298             * @param processors processors (for annotation processing)
299             * @throws IllegalStateException if the task has started
300             */
301            void setProcessors(Iterable<? extends Processor> processors);
302    
303            /**
304             * Set the locale to be applied when formatting diagnostics and
305             * other localized data.
306             *
307             * @param locale the locale to apply; {@code null} means apply no
308             * locale
309             * @throws IllegalStateException if the task has started
310             */
311            void setLocale(Locale locale);
312    
313            /**
314             * Performs this compilation task.  The compilation may only
315             * be performed once.  Subsequent calls to this method throw
316             * IllegalStateException.
317             *
318             * @return true if and only all the files compiled without errors;
319             * false otherwise
320             *
321             * @throws RuntimeException if an unrecoverable error occurred
322             * in a user-supplied component.  The
323             * {@linkplain Throwable#getCause() cause} will be the error
324             * in user code.
325             * @throws IllegalStateException if called more than once
326             */
327            Boolean call();
328        }
329    }