1 /* 2 * Copyright (c) 2004, 2011, 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.apt.main; 27 28 import java.io.*; 29 import java.util.Map; 30 31 import javax.tools.JavaFileManager; 32 import javax.tools.JavaFileObject; 33 34 import com.sun.tools.javac.file.JavacFileManager; 35 import com.sun.tools.javac.util.*; 36 import com.sun.tools.javac.code.*; 37 import com.sun.tools.javac.jvm.*; 38 39 import com.sun.tools.javac.code.Symbol.*; 40 import com.sun.tools.javac.tree.JCTree.*; 41 42 import com.sun.tools.apt.comp.*; 43 import com.sun.tools.apt.util.Bark; 44 import com.sun.mirror.apt.AnnotationProcessorFactory; 45 46 /** 47 * <p><b>This is NOT part of any supported API. 48 * If you write code that depends on this, you do so at your own 49 * risk. This code and its internal interfaces are subject to change 50 * or deletion without notice.</b> 51 */ 52 @SuppressWarnings("deprecation") 53 public class AptJavaCompiler extends com.sun.tools.javac.main.JavaCompiler { 54 /** The context key for the compiler. */ 55 protected static final Context.Key<AptJavaCompiler> compilerKey = 56 new Context.Key<AptJavaCompiler>(); 57 58 /** Get the JavaCompiler instance for this context. */ 59 public static AptJavaCompiler instance(Context context) { 60 AptJavaCompiler instance = context.get(compilerKey); 61 if (instance == null) 62 instance = new AptJavaCompiler(context); 63 return instance; 64 } 65 66 67 java.util.Set<String> genSourceFileNames; 68 java.util.Set<String> genClassFileNames; 69 70 public java.util.Set<String> getSourceFileNames() { 71 return genSourceFileNames; 72 } 73 74 /** List of names of generated class files. 75 */ 76 public java.util.Set<String> getClassFileNames() { 77 return genClassFileNames; 78 } 79 80 java.util.Set<java.io.File> aggregateGenFiles = java.util.Collections.emptySet(); 81 82 public java.util.Set<java.io.File> getAggregateGenFiles() { 83 return aggregateGenFiles; 84 } 85 86 /** The bark to be used for error reporting. 87 */ 88 Bark bark; 89 90 /** The log to be used for error reporting. 91 */ 92 Log log; 93 94 /** The annotation framework 95 */ 96 Apt apt; 97 98 private static Context preRegister(Context context) { 99 Bark.preRegister(context); 100 101 if (context.get(JavaFileManager.class) == null) 102 JavacFileManager.preRegister(context); 103 104 return context; 105 } 106 107 /** Construct a new compiler from a shared context. 108 */ 109 public AptJavaCompiler(Context context) { 110 super(preRegister(context)); 111 112 context.put(compilerKey, this); 113 apt = Apt.instance(context); 114 115 ClassReader classReader = ClassReader.instance(context); 116 classReader.preferSource = true; 117 118 // TEMPORARY NOTE: bark==log, but while refactoring, we maintain their 119 // original identities, to remember the original intent. 120 log = Log.instance(context); 121 bark = Bark.instance(context); 122 123 Options options = Options.instance(context); 124 classOutput = options.get("-retrofit") == null; 125 nocompile = options.get("-nocompile") != null; 126 print = options.get("-print") != null; 127 classesAsDecls= options.get("-XclassesAsDecls") != null; 128 129 genSourceFileNames = new java.util.LinkedHashSet<String>(); 130 genClassFileNames = new java.util.LinkedHashSet<String>(); 131 132 // this forces a copy of the line map to be kept in the tree, 133 // for use by com.sun.mirror.util.SourcePosition. 134 lineDebugInfo = true; 135 } 136 137 /* Switches: 138 */ 139 140 /** Emit class files. This switch is always set, except for the first 141 * phase of retrofitting, where signatures are parsed. 142 */ 143 public boolean classOutput; 144 145 /** The internal printing annotation processor should be used. 146 */ 147 public boolean print; 148 149 /** Compilation should not be done after annotation processing. 150 */ 151 public boolean nocompile; 152 153 /** Are class files being treated as declarations 154 */ 155 public boolean classesAsDecls; 156 157 /** Try to open input stream with given name. 158 * Report an error if this fails. 159 * @param filename The file name of the input stream to be opened. 160 */ 161 // PROVIDED FOR EXTREME BACKWARDS COMPATIBILITY 162 // There are some very obscure errors that can arise while translating 163 // the contents of a file from bytes to characters. In Tiger, these 164 // diagnostics were ignored. This method provides compatibility with 165 // that behavior. It would be better to honor those diagnostics, in which 166 // case, this method can be deleted. 167 @Override 168 public CharSequence readSource(JavaFileObject filename) { 169 try { 170 inputFiles.add(filename); 171 boolean prev = bark.setDiagnosticsIgnored(true); 172 try { 173 return filename.getCharContent(false); 174 } 175 finally { 176 bark.setDiagnosticsIgnored(prev); 177 } 178 } catch (IOException e) { 179 bark.error(Position.NOPOS, "cant.read.file", filename); 180 return null; 181 } 182 } 183 184 /** Parse contents of input stream. 185 * @param filename The name of the file from which input stream comes. 186 * @param input The input stream to be parsed. 187 */ 188 // PROVIDED FOR BACKWARDS COMPATIBILITY 189 // In Tiger, diagnostics from the scanner and parser were ignored. 190 // This method provides compatibility with that behavior. 191 // It would be better to honor those diagnostics, in which 192 // case, this method can be deleted. 193 @Override 194 protected JCCompilationUnit parse(JavaFileObject filename, CharSequence content) { 195 boolean prev = bark.setDiagnosticsIgnored(true); 196 try { 197 return super.parse(filename, content); 198 } 199 finally { 200 bark.setDiagnosticsIgnored(prev); 201 } 202 } 203 204 @Override 205 protected boolean keepComments() { 206 return true; // make doc comments available to mirror API impl. 207 } 208 209 /** Track when the JavaCompiler has been used to compile something. */ 210 private boolean hasBeenUsed = false; 211 212 /** Main method: compile a list of files, return all compiled classes 213 * @param filenames The names of all files to be compiled. 214 */ 215 public List<ClassSymbol> compile(List<String> filenames, 216 Map<String, String> origOptions, 217 ClassLoader aptCL, 218 AnnotationProcessorFactory providedFactory, 219 java.util.Set<Class<? extends AnnotationProcessorFactory> > productiveFactories, 220 java.util.Set<java.io.File> aggregateGenFiles) 221 throws Throwable { 222 // as a JavaCompiler can only be used once, throw an exception if 223 // it has been used before. 224 assert !hasBeenUsed : "attempt to reuse JavaCompiler"; 225 hasBeenUsed = true; 226 227 this.aggregateGenFiles = aggregateGenFiles; 228 229 long msec = System.currentTimeMillis(); 230 231 ListBuffer<ClassSymbol> classes = new ListBuffer<ClassSymbol>(); 232 try { 233 JavacFileManager fm = (JavacFileManager)fileManager; 234 //parse all files 235 ListBuffer<JCCompilationUnit> trees = new ListBuffer<JCCompilationUnit>(); 236 for (List<String> l = filenames; l.nonEmpty(); l = l.tail) { 237 if (classesAsDecls) { 238 if (! l.head.endsWith(".java") ) { // process as class file 239 ClassSymbol cs = reader.enterClass(names.fromString(l.head)); 240 try { 241 cs.complete(); 242 } catch(Symbol.CompletionFailure cf) { 243 bark.aptError("CantFindClass", l); 244 continue; 245 } 246 247 classes.append(cs); // add to list of classes 248 continue; 249 } 250 } 251 JavaFileObject fo = fm.getJavaFileObjectsFromStrings(List.of(l.head)).iterator().next(); 252 trees.append(parse(fo)); 253 } 254 255 //enter symbols for all files 256 List<JCCompilationUnit> roots = trees.toList(); 257 258 if (errorCount() == 0) { 259 boolean prev = bark.setDiagnosticsIgnored(true); 260 try { 261 enter.main(roots); 262 } 263 finally { 264 bark.setDiagnosticsIgnored(prev); 265 } 266 } 267 268 if (errorCount() == 0) { 269 apt.main(roots, 270 classes, 271 origOptions, aptCL, 272 providedFactory, 273 productiveFactories); 274 genSourceFileNames.addAll(apt.getSourceFileNames()); 275 genClassFileNames.addAll(apt.getClassFileNames()); 276 } 277 278 } catch (Abort ex) { 279 } 280 281 if (verbose) 282 log.printVerbose("total", Long.toString(System.currentTimeMillis() - msec)); 283 284 chk.reportDeferredDiagnostics(); 285 286 printCount("error", errorCount()); 287 printCount("warn", warningCount()); 288 289 return classes.toList(); 290 } 291 }