1 /* 2 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.javac.api; 27 28 import java.io.InputStream; 29 import java.io.OutputStream; 30 import java.io.OutputStreamWriter; 31 import java.io.PrintWriter; 32 import java.io.Writer; 33 import java.nio.charset.Charset; 34 import java.util.Collections; 35 import java.util.EnumSet; 36 import java.util.Locale; 37 import java.util.Objects; 38 import java.util.Set; 39 40 import javax.lang.model.SourceVersion; 41 import javax.tools.*; 42 43 import com.sun.source.util.JavacTask; 44 import com.sun.tools.javac.file.JavacFileManager; 45 import com.sun.tools.javac.main.Arguments; 46 import com.sun.tools.javac.main.Option; 47 import com.sun.tools.javac.file.BaseFileManager; 48 import com.sun.tools.javac.file.CacheFSInfo; 49 import com.sun.tools.javac.jvm.Target; 50 import com.sun.tools.javac.util.ClientCodeException; 51 import com.sun.tools.javac.util.Context; 52 import com.sun.tools.javac.util.DefinedBy; 53 import com.sun.tools.javac.util.DefinedBy.Api; 54 import com.sun.tools.javac.util.List; 55 import com.sun.tools.javac.util.Log; 56 import com.sun.tools.javac.util.PropagatedException; 57 58 /** 59 * TODO: describe com.sun.tools.javac.api.Tool 60 * 61 * <p><b>This is NOT part of any supported API. 62 * If you write code that depends on this, you do so at your own 63 * risk. This code and its internal interfaces are subject to change 64 * or deletion without notice.</b></p> 65 * 66 * @author Peter von der Ah\u00e9 67 */ 68 public final class JavacTool implements JavaCompiler { 69 /** 70 * Constructor used by service provider mechanism. The recommended way to 71 * obtain an instance of this class is by using {@link #create} or the 72 * service provider mechanism. 73 * @see javax.tools.JavaCompiler 74 * @see javax.tools.ToolProvider 75 * @see #create 76 */ 77 @Deprecated 78 public JavacTool() {} 79 80 /** 81 * Static factory method for creating new instances of this tool. 82 * @return new instance of this tool 83 */ 84 public static JavacTool create() { 85 return new JavacTool(); 86 } 87 88 @Override @DefinedBy(Api.COMPILER) 89 public JavacFileManager getStandardFileManager( 90 DiagnosticListener<? super JavaFileObject> diagnosticListener, 91 Locale locale, 92 Charset charset) { 93 Context context = new Context(); 94 context.put(Locale.class, locale); 95 if (diagnosticListener != null) 96 context.put(DiagnosticListener.class, diagnosticListener); 97 PrintWriter pw = (charset == null) 98 ? new PrintWriter(System.err, true) 99 : new PrintWriter(new OutputStreamWriter(System.err, charset), true); 100 context.put(Log.errKey, pw); 101 CacheFSInfo.preRegister(context); 102 return new JavacFileManager(context, true, charset); 103 } 104 105 @Override @DefinedBy(Api.COMPILER) 106 public JavacTask getTask(Writer out, 107 JavaFileManager fileManager, 108 DiagnosticListener<? super JavaFileObject> diagnosticListener, 109 Iterable<String> options, 110 Iterable<String> classes, 111 Iterable<? extends JavaFileObject> compilationUnits) { 112 Context context = new Context(); 113 return getTask(out, fileManager, diagnosticListener, 114 options, classes, compilationUnits, 115 context); 116 } 117 118 /* Internal version of getTask, allowing context to be provided. */ 119 public JavacTask getTask(Writer out, 120 JavaFileManager fileManager, 121 DiagnosticListener<? super JavaFileObject> diagnosticListener, 122 Iterable<String> options, 123 Iterable<String> classes, 124 Iterable<? extends JavaFileObject> compilationUnits, 125 Context context) 126 { 127 try { 128 ClientCodeWrapper ccw = ClientCodeWrapper.instance(context); 129 130 if (options != null) { 131 for (String option : options) 132 Objects.requireNonNull(option); 133 } 134 135 if (classes != null) { 136 for (String cls : classes) { 137 int sep = cls.indexOf('/'); // implicit null check 138 if (sep > 0) { 139 String mod = cls.substring(0, sep); 140 if (!SourceVersion.isName(mod)) 141 throw new IllegalArgumentException("Not a valid module name: " + mod); 142 cls = cls.substring(sep + 1); 143 } 144 if (!SourceVersion.isName(cls)) 145 throw new IllegalArgumentException("Not a valid class name: " + cls); 146 } 147 } 148 149 if (compilationUnits != null) { 150 compilationUnits = ccw.wrapJavaFileObjects(compilationUnits); // implicit null check 151 for (JavaFileObject cu : compilationUnits) { 152 if (cu.getKind() != JavaFileObject.Kind.SOURCE) { 153 String kindMsg = "Compilation unit is not of SOURCE kind: " 154 + "\"" + cu.getName() + "\""; 155 throw new IllegalArgumentException(kindMsg); 156 } 157 } 158 } 159 160 if (diagnosticListener != null) 161 context.put(DiagnosticListener.class, ccw.wrap(diagnosticListener)); 162 163 if (out == null) 164 context.put(Log.errKey, new PrintWriter(System.err, true)); 165 else 166 context.put(Log.errKey, new PrintWriter(out, true)); 167 168 if (fileManager == null) { 169 fileManager = getStandardFileManager(diagnosticListener, null, null); 170 if (fileManager instanceof BaseFileManager) { 171 ((BaseFileManager) fileManager).autoClose = true; 172 } 173 } 174 fileManager = ccw.wrap(fileManager); 175 176 context.put(JavaFileManager.class, fileManager); 177 178 Arguments args = Arguments.instance(context); 179 args.init("javac", options, classes, compilationUnits); 180 181 // init multi-release jar handling 182 if (fileManager.isSupportedOption(Option.MULTIRELEASE.text) == 1) { 183 Target target = Target.instance(context); 184 List<String> list = List.of(target.multiReleaseValue()); 185 fileManager.handleOption(Option.MULTIRELEASE.text, list.iterator()); 186 } 187 188 return new JavacTaskImpl(context); 189 } catch (PropagatedException ex) { 190 throw ex.getCause(); 191 } catch (ClientCodeException ex) { 192 throw new RuntimeException(ex.getCause()); 193 } 194 } 195 196 @Override @DefinedBy(Api.COMPILER) 197 public int run(InputStream in, OutputStream out, OutputStream err, String... arguments) { 198 if (err == null) 199 err = System.err; 200 for (String argument : arguments) 201 Objects.requireNonNull(argument); 202 return com.sun.tools.javac.Main.compile(arguments, new PrintWriter(err, true)); 203 } 204 205 @Override @DefinedBy(Api.COMPILER) 206 public Set<SourceVersion> getSourceVersions() { 207 return Collections.unmodifiableSet(EnumSet.range(SourceVersion.RELEASE_3, 208 SourceVersion.latest())); 209 } 210 211 @Override @DefinedBy(Api.COMPILER) 212 public int isSupportedOption(String option) { 213 Set<Option> recognizedOptions = Option.getJavacToolOptions(); 214 for (Option o : recognizedOptions) { 215 if (o.matches(option)) 216 return o.hasArg() ? 1 : 0; 217 } 218 return -1; 219 } 220 221 }