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 com.sun.tools.javac.api;
027:
028: import java.io.File;
029: import java.io.InputStream;
030: import java.io.OutputStream;
031: import java.io.PrintWriter;
032: import java.io.Writer;
033: import java.util.ArrayList;
034: import java.util.Arrays;
035: import java.util.Collections;
036: import java.util.EnumSet;
037: import java.util.Iterator;
038: import java.util.List;
039: import java.util.Locale;
040: import java.util.Set;
041: import javax.lang.model.SourceVersion;
042: import javax.tools.*;
043:
044: import com.sun.source.util.JavacTask;
045: import com.sun.tools.javac.main.JavacOption.OptionKind;
046: import com.sun.tools.javac.main.JavacOption;
047: import com.sun.tools.javac.main.Main;
048: import com.sun.tools.javac.main.RecognizedOptions.GrumpyHelper;
049: import com.sun.tools.javac.main.RecognizedOptions;
050: import com.sun.tools.javac.util.Context;
051: import com.sun.tools.javac.util.JavacFileManager;
052: import com.sun.tools.javac.util.Log;
053: import com.sun.tools.javac.util.Options;
054: import com.sun.tools.javac.util.Pair;
055: import com.sun.tools.javac.util.Version;
056: import java.nio.charset.Charset;
057:
058: /**
059: * TODO: describe com.sun.tools.javac.api.Tool
060: *
061: * <p><b>This is NOT part of any API supported by Sun Microsystems.
062: * If you write code that depends on this, you do so at your own
063: * risk. This code and its internal interfaces are subject to change
064: * or deletion without notice.</b></p>
065: *
066: * @author Peter von der Ah\u00e9
067: */
068: @Version("@(#)JavacTool.java 1.19 07/05/05")
069: public final class JavacTool implements JavaCompiler {
070: private final List<Pair<String, String>> options = new ArrayList<Pair<String, String>>();
071: private final Context dummyContext = new Context();
072:
073: private final PrintWriter silent = new PrintWriter(
074: new OutputStream() {
075: public void write(int b) {
076: }
077: });
078:
079: private final Main sharedCompiler = new Main("javac", silent);
080: {
081: sharedCompiler.setOptions(Options.instance(dummyContext));
082: }
083:
084: /**
085: * Constructor used by service provider mechanism. The correct way to
086: * obtain an instance of this class is using create or the service provider
087: * mechanism.
088: * @see javax.tools.JavaCompilerTool
089: * @see javax.tools.ToolProvider
090: * @see #create
091: */
092: @Deprecated
093: public JavacTool() {
094: }
095:
096: /**
097: * Static factory method for creating new instances of this tool.
098: * @return new instance of this tool
099: */
100: public static JavacTool create() {
101: return new JavacTool();
102: }
103:
104: private String argsToString(Object... args) {
105: String newArgs = null;
106: if (args.length > 0) {
107: StringBuilder sb = new StringBuilder();
108: String separator = "";
109: for (Object arg : args) {
110: sb.append(separator).append(arg.toString());
111: separator = File.pathSeparator;
112: }
113: newArgs = sb.toString();
114: }
115: return newArgs;
116: }
117:
118: private void setOption1(String name, OptionKind kind,
119: Object... args) {
120: String arg = argsToString(args);
121: JavacOption option = sharedCompiler.getOption(name);
122: if (option == null || !match(kind, option.getKind()))
123: throw new IllegalArgumentException(name);
124: if ((args.length != 0) != option.hasArg())
125: throw new IllegalArgumentException(name);
126: if (option.hasArg()) {
127: if (option.process(null, name, arg)) // FIXME
128: throw new IllegalArgumentException(name);
129: } else {
130: if (option.process(null, name)) // FIXME
131: throw new IllegalArgumentException(name);
132: }
133: options.add(new Pair<String, String>(name, arg));
134: }
135:
136: public void setOption(String name, Object... args) {
137: setOption1(name, OptionKind.NORMAL, args);
138: }
139:
140: public void setExtendedOption(String name, Object... args) {
141: setOption1(name, OptionKind.EXTENDED, args);
142: }
143:
144: private static boolean match(OptionKind clientKind,
145: OptionKind optionKind) {
146: return (clientKind == (optionKind == OptionKind.HIDDEN ? optionKind.EXTENDED
147: : optionKind));
148: }
149:
150: public JavacFileManager getStandardFileManager(
151: DiagnosticListener<? super JavaFileObject> diagnosticListener,
152: Locale locale, Charset charset) {
153: Context context = new Context();
154: if (diagnosticListener != null)
155: context.put(DiagnosticListener.class, diagnosticListener);
156: context.put(Log.outKey, new PrintWriter(System.err, true)); // FIXME
157: return new JavacFileManager(context, true, charset);
158: }
159:
160: private boolean compilationInProgress = false;
161:
162: /**
163: * Register that a compilation is about to start.
164: */
165: void beginContext(final Context context) {
166: if (compilationInProgress)
167: throw new IllegalStateException("Compilation in progress");
168: compilationInProgress = true;
169: final JavaFileManager givenFileManager = context
170: .get(JavaFileManager.class);
171: context.put(JavaFileManager.class, (JavaFileManager) null);
172: context.put(JavaFileManager.class,
173: new Context.Factory<JavaFileManager>() {
174: public JavaFileManager make() {
175: if (givenFileManager != null) {
176: context.put(JavaFileManager.class,
177: givenFileManager);
178: return givenFileManager;
179: } else {
180: return new JavacFileManager(context, true,
181: null);
182: }
183: }
184: });
185: }
186:
187: /**
188: * Register that a compilation is completed.
189: */
190: void endContext() {
191: compilationInProgress = false;
192: }
193:
194: public JavacTask getTask(
195: Writer out,
196: JavaFileManager fileManager,
197: DiagnosticListener<? super JavaFileObject> diagnosticListener,
198: Iterable<String> options, Iterable<String> classes,
199: Iterable<? extends JavaFileObject> compilationUnits) {
200: final String kindMsg = "All compilation units must be of SOURCE kind";
201: if (options != null)
202: for (String option : options)
203: option.getClass(); // null check
204: if (classes != null) {
205: for (String cls : classes)
206: if (!SourceVersion.isName(cls)) // implicit null check
207: throw new IllegalArgumentException(
208: "Not a valid class name: " + cls);
209: }
210: if (compilationUnits != null) {
211: for (JavaFileObject cu : compilationUnits) {
212: if (cu.getKind() != JavaFileObject.Kind.SOURCE) // implicit null check
213: throw new IllegalArgumentException(kindMsg);
214: }
215: }
216:
217: Context context = new Context();
218:
219: if (diagnosticListener != null)
220: context.put(DiagnosticListener.class, diagnosticListener);
221:
222: if (out == null)
223: context.put(Log.outKey, new PrintWriter(System.err, true));
224: else
225: context.put(Log.outKey, new PrintWriter(out, true));
226:
227: if (fileManager == null)
228: fileManager = getStandardFileManager(diagnosticListener,
229: null, null);
230: context.put(JavaFileManager.class, fileManager);
231: processOptions(context, fileManager, options);
232: Main compiler = new Main("javacTask", context.get(Log.outKey));
233: return new JavacTaskImpl(this , compiler, options, context,
234: classes, compilationUnits);
235: }
236:
237: private static void processOptions(Context context,
238: JavaFileManager fileManager, Iterable<String> options) {
239: if (options == null)
240: return;
241:
242: Options optionTable = Options.instance(context);
243:
244: JavacOption[] recognizedOptions = RecognizedOptions
245: .getJavacToolOptions(new GrumpyHelper());
246: Iterator<String> flags = options.iterator();
247: while (flags.hasNext()) {
248: String flag = flags.next();
249: int j;
250: for (j = 0; j < recognizedOptions.length; j++)
251: if (recognizedOptions[j].matches(flag))
252: break;
253:
254: if (j == recognizedOptions.length) {
255: if (fileManager.handleOption(flag, flags)) {
256: continue;
257: } else {
258: String msg = Main.getLocalizedString(
259: "err.invalid.flag", flag);
260: throw new IllegalArgumentException(msg);
261: }
262: }
263:
264: JavacOption option = recognizedOptions[j];
265: if (option.hasArg()) {
266: if (!flags.hasNext()) {
267: String msg = Main.getLocalizedString("err.req.arg",
268: flag);
269: throw new IllegalArgumentException(msg);
270: }
271: String operand = flags.next();
272: if (option.process(optionTable, flag, operand))
273: // should not happen as the GrumpyHelper will throw exceptions
274: // in case of errors
275: throw new IllegalArgumentException(flag + " "
276: + operand);
277: } else {
278: if (option.process(optionTable, flag))
279: // should not happen as the GrumpyHelper will throw exceptions
280: // in case of errors
281: throw new IllegalArgumentException(flag);
282: }
283: }
284: }
285:
286: public int run(InputStream in, OutputStream out, OutputStream err,
287: String... arguments) {
288: if (err == null)
289: err = System.err;
290: for (String argument : arguments)
291: argument.getClass(); // null check
292: return com.sun.tools.javac.Main.compile(arguments,
293: new PrintWriter(err, true));
294: }
295:
296: public Set<SourceVersion> getSourceVersions() {
297: return Collections.unmodifiableSet(EnumSet.range(
298: SourceVersion.RELEASE_3, SourceVersion.latest()));
299: }
300:
301: public int isSupportedOption(String option) {
302: JavacOption[] recognizedOptions = RecognizedOptions
303: .getJavacToolOptions(new GrumpyHelper());
304: for (JavacOption o : recognizedOptions) {
305: if (o.matches(option))
306: return o.hasArg() ? 1 : 0;
307: }
308: return -1;
309: }
310:
311: }
|