JavacTool.java revision 3809:27be91e4393b
121308Sache/* 221308Sache * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. 321308Sache * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 421308Sache * 521308Sache * This code is free software; you can redistribute it and/or modify it 621308Sache * under the terms of the GNU General Public License version 2 only, as 721308Sache * published by the Free Software Foundation. Oracle designates this 821308Sache * particular file as subject to the "Classpath" exception as provided 921308Sache * by Oracle in the LICENSE file that accompanied this code. 1058310Sache * 1121308Sache * This code is distributed in the hope that it will be useful, but WITHOUT 1221308Sache * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1321308Sache * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1421308Sache * version 2 for more details (a copy is included in the LICENSE file that 1521308Sache * accompanied this code). 1621308Sache * 1721308Sache * You should have received a copy of the GNU General Public License version 1821308Sache * 2 along with this work; if not, write to the Free Software Foundation, 1921308Sache * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2058310Sache * 2121308Sache * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2221308Sache * or visit www.oracle.com if you need additional information or have any 2321308Sache * questions. 2421308Sache */ 2521308Sache 2621308Sachepackage com.sun.tools.javac.api; 2721308Sache 2821308Sacheimport java.io.InputStream; 2921308Sacheimport java.io.OutputStream; 3021308Sacheimport java.io.OutputStreamWriter; 3121308Sacheimport java.io.PrintWriter; 3221308Sacheimport java.io.Writer; 3321308Sacheimport java.nio.charset.Charset; 3421308Sacheimport java.util.Collections; 3521308Sacheimport java.util.EnumSet; 3621308Sacheimport java.util.Locale; 3721308Sacheimport java.util.Objects; 3821308Sacheimport java.util.Set; 3921308Sache 4021308Sacheimport javax.lang.model.SourceVersion; 4121308Sacheimport javax.tools.*; 4221308Sache 4321308Sacheimport com.sun.source.util.JavacTask; 4421308Sacheimport com.sun.tools.javac.file.JavacFileManager; 4521308Sacheimport com.sun.tools.javac.main.Arguments; 4621308Sacheimport com.sun.tools.javac.main.Option; 4721308Sacheimport com.sun.tools.javac.file.BaseFileManager; 4821308Sacheimport com.sun.tools.javac.file.CacheFSInfo; 4921308Sacheimport com.sun.tools.javac.jvm.Target; 5021308Sacheimport com.sun.tools.javac.util.ClientCodeException; 5121308Sacheimport com.sun.tools.javac.util.Context; 5221308Sacheimport com.sun.tools.javac.util.DefinedBy; 5321308Sacheimport com.sun.tools.javac.util.DefinedBy.Api; 5421308Sacheimport com.sun.tools.javac.util.List; 5521308Sacheimport com.sun.tools.javac.util.Log; 5621308Sacheimport com.sun.tools.javac.util.PropagatedException; 5721308Sache 5821308Sache/** 5921308Sache * TODO: describe com.sun.tools.javac.api.Tool 6021308Sache * 6121308Sache * <p><b>This is NOT part of any supported API. 6221308Sache * If you write code that depends on this, you do so at your own 6321308Sache * risk. This code and its internal interfaces are subject to change 6421308Sache * or deletion without notice.</b></p> 6521308Sache * 6621308Sache * @author Peter von der Ah\u00e9 6721308Sache */ 6821308Sachepublic final class JavacTool implements JavaCompiler { 6921308Sache /** 7021308Sache * Constructor used by service provider mechanism. The recommended way to 7121308Sache * obtain an instance of this class is by using {@link #create} or the 7221308Sache * service provider mechanism. 7321308Sache * @see javax.tools.JavaCompiler 7421308Sache * @see javax.tools.ToolProvider 7521308Sache * @see #create 7621308Sache */ 7721308Sache @Deprecated 7821308Sache public JavacTool() {} 7921308Sache 8021308Sache // @Override // can't add @Override until bootstrap JDK provides Tool.name() 8121308Sache @DefinedBy(Api.COMPILER) 8221308Sache public String name() { 8321308Sache return "javac"; 8421308Sache } 8521308Sache 8621308Sache /** 8721308Sache * Static factory method for creating new instances of this tool. 8821308Sache * @return new instance of this tool 8921308Sache */ 9021308Sache public static JavacTool create() { 9121308Sache return new JavacTool(); 9221308Sache } 9321308Sache 9421308Sache @Override @DefinedBy(Api.COMPILER) 9521308Sache public JavacFileManager getStandardFileManager( 9621308Sache DiagnosticListener<? super JavaFileObject> diagnosticListener, 9721308Sache Locale locale, 9821308Sache Charset charset) { 9921308Sache Context context = new Context(); 10021308Sache context.put(Locale.class, locale); 10121308Sache if (diagnosticListener != null) 10221308Sache context.put(DiagnosticListener.class, diagnosticListener); 10321308Sache PrintWriter pw = (charset == null) 10421308Sache ? new PrintWriter(System.err, true) 10521308Sache : new PrintWriter(new OutputStreamWriter(System.err, charset), true); 10621308Sache context.put(Log.errKey, pw); 10721308Sache CacheFSInfo.preRegister(context); 10821308Sache return new JavacFileManager(context, true, charset); 10921308Sache } 11021308Sache 11121308Sache @Override @DefinedBy(Api.COMPILER) 11221308Sache public JavacTask getTask(Writer out, 11321308Sache JavaFileManager fileManager, 11421308Sache DiagnosticListener<? super JavaFileObject> diagnosticListener, 11521308Sache Iterable<String> options, 11621308Sache Iterable<String> classes, 11721308Sache Iterable<? extends JavaFileObject> compilationUnits) { 11821308Sache Context context = new Context(); 11921308Sache return getTask(out, fileManager, diagnosticListener, 12021308Sache options, classes, compilationUnits, 12121308Sache context); 12221308Sache } 12321308Sache 12421308Sache /* Internal version of getTask, allowing context to be provided. */ 12521308Sache public JavacTask getTask(Writer out, 12621308Sache JavaFileManager fileManager, 12721308Sache DiagnosticListener<? super JavaFileObject> diagnosticListener, 12821308Sache Iterable<String> options, 12921308Sache Iterable<String> classes, 13021308Sache Iterable<? extends JavaFileObject> compilationUnits, 13121308Sache Context context) 13221308Sache { 13321308Sache try { 13421308Sache ClientCodeWrapper ccw = ClientCodeWrapper.instance(context); 13521308Sache 13621308Sache if (options != null) { 13721308Sache for (String option : options) 13821308Sache Objects.requireNonNull(option); 13921308Sache } 14021308Sache 14121308Sache if (classes != null) { 14221308Sache for (String cls : classes) { 143 int sep = cls.indexOf('/'); // implicit null check 144 if (sep > 0) { 145 String mod = cls.substring(0, sep); 146 if (!SourceVersion.isName(mod)) 147 throw new IllegalArgumentException("Not a valid module name: " + mod); 148 cls = cls.substring(sep + 1); 149 } 150 if (!SourceVersion.isName(cls)) 151 throw new IllegalArgumentException("Not a valid class name: " + cls); 152 } 153 } 154 155 if (compilationUnits != null) { 156 compilationUnits = ccw.wrapJavaFileObjects(compilationUnits); // implicit null check 157 for (JavaFileObject cu : compilationUnits) { 158 if (cu.getKind() != JavaFileObject.Kind.SOURCE) { 159 String kindMsg = "Compilation unit is not of SOURCE kind: " 160 + "\"" + cu.getName() + "\""; 161 throw new IllegalArgumentException(kindMsg); 162 } 163 } 164 } 165 166 if (diagnosticListener != null) 167 context.put(DiagnosticListener.class, ccw.wrap(diagnosticListener)); 168 169 if (out == null) 170 context.put(Log.errKey, new PrintWriter(System.err, true)); 171 else 172 context.put(Log.errKey, new PrintWriter(out, true)); 173 174 if (fileManager == null) { 175 fileManager = getStandardFileManager(diagnosticListener, null, null); 176 if (fileManager instanceof BaseFileManager) { 177 ((BaseFileManager) fileManager).autoClose = true; 178 } 179 } 180 fileManager = ccw.wrap(fileManager); 181 182 context.put(JavaFileManager.class, fileManager); 183 184 Arguments args = Arguments.instance(context); 185 args.init("javac", options, classes, compilationUnits); 186 187 // init multi-release jar handling 188 if (fileManager.isSupportedOption(Option.MULTIRELEASE.primaryName) == 1) { 189 Target target = Target.instance(context); 190 List<String> list = List.of(target.multiReleaseValue()); 191 fileManager.handleOption(Option.MULTIRELEASE.primaryName, list.iterator()); 192 } 193 194 return new JavacTaskImpl(context); 195 } catch (PropagatedException ex) { 196 throw ex.getCause(); 197 } catch (ClientCodeException ex) { 198 throw new RuntimeException(ex.getCause()); 199 } 200 } 201 202 @Override @DefinedBy(Api.COMPILER) 203 public int run(InputStream in, OutputStream out, OutputStream err, String... arguments) { 204 if (err == null) 205 err = System.err; 206 for (String argument : arguments) 207 Objects.requireNonNull(argument); 208 return com.sun.tools.javac.Main.compile(arguments, new PrintWriter(err, true)); 209 } 210 211 @Override @DefinedBy(Api.COMPILER) 212 public Set<SourceVersion> getSourceVersions() { 213 return Collections.unmodifiableSet(EnumSet.range(SourceVersion.RELEASE_3, 214 SourceVersion.latest())); 215 } 216 217 @Override @DefinedBy(Api.COMPILER) 218 public int isSupportedOption(String option) { 219 Set<Option> recognizedOptions = Option.getJavacToolOptions(); 220 for (Option o : recognizedOptions) { 221 if (o.matches(option)) { 222 return o.hasArg() ? 1 : 0; 223 } 224 } 225 return -1; 226 } 227 228} 229