45 import javax.tools.JavaFileObject;
46 import javax.tools.JavaFileObject.Kind;
47 import javax.tools.StandardJavaFileManager;
48
49 import static javax.tools.StandardLocation.*;
50
51 import com.sun.source.util.TaskEvent;
52 import com.sun.tools.javac.api.MultiTaskListener;
53 import com.sun.tools.javac.code.*;
54 import com.sun.tools.javac.code.Scope.WriteableScope;
55 import com.sun.tools.javac.code.Symbol.*;
56 import com.sun.tools.javac.code.Type.ClassType;
57 import com.sun.tools.javac.code.Types;
58 import com.sun.tools.javac.comp.AttrContext;
59 import com.sun.tools.javac.comp.Check;
60 import com.sun.tools.javac.comp.Enter;
61 import com.sun.tools.javac.comp.Env;
62 import com.sun.tools.javac.comp.Modules;
63 import com.sun.tools.javac.file.JavacFileManager;
64 import com.sun.tools.javac.main.JavaCompiler;
65 import com.sun.tools.javac.model.JavacElements;
66 import com.sun.tools.javac.model.JavacTypes;
67 import com.sun.tools.javac.platform.PlatformDescription;
68 import com.sun.tools.javac.platform.PlatformDescription.PluginInfo;
69 import com.sun.tools.javac.resources.CompilerProperties.Errors;
70 import com.sun.tools.javac.tree.*;
71 import com.sun.tools.javac.tree.JCTree.*;
72 import com.sun.tools.javac.util.Abort;
73 import com.sun.tools.javac.util.Assert;
74 import com.sun.tools.javac.util.ClientCodeException;
75 import com.sun.tools.javac.util.Context;
76 import com.sun.tools.javac.util.Convert;
77 import com.sun.tools.javac.util.DefinedBy;
78 import com.sun.tools.javac.util.DefinedBy.Api;
79 import com.sun.tools.javac.util.Iterators;
80 import com.sun.tools.javac.util.JCDiagnostic;
81 import com.sun.tools.javac.util.JavacMessages;
82 import com.sun.tools.javac.util.List;
83 import com.sun.tools.javac.util.Log;
84 import com.sun.tools.javac.util.MatchingUtils;
85 import com.sun.tools.javac.util.ModuleHelper;
86 import com.sun.tools.javac.util.Name;
87 import com.sun.tools.javac.util.Names;
88 import com.sun.tools.javac.util.Options;
89
90 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
91 import static com.sun.tools.javac.code.Kinds.Kind.*;
92 import static com.sun.tools.javac.main.Option.*;
93 import static com.sun.tools.javac.comp.CompileStates.CompileState;
94 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
95
96 /**
97 * Objects of this class hold and manage the state needed to support
98 * annotation processing.
99 *
100 * <p><b>This is NOT part of any supported API.
101 * If you write code that depends on this, you do so at your own risk.
102 * This code and its internal interfaces are subject to change or
103 * deletion without notice.</b>
104 */
105 public class JavacProcessingEnvironment implements ProcessingEnvironment, Closeable {
106 private final Options options;
107
108 private final boolean printProcessorInfo;
109 private final boolean printRounds;
110 private final boolean verbose;
111 private final boolean lint;
112 private final boolean fatalErrors;
179 private final Check chk;
180 private final ModuleSymbol defaultModule;
181
182 private final Context context;
183
184 /** Get the JavacProcessingEnvironment instance for this context. */
185 public static JavacProcessingEnvironment instance(Context context) {
186 JavacProcessingEnvironment instance = context.get(JavacProcessingEnvironment.class);
187 if (instance == null)
188 instance = new JavacProcessingEnvironment(context);
189 return instance;
190 }
191
192 protected JavacProcessingEnvironment(Context context) {
193 this.context = context;
194 context.put(JavacProcessingEnvironment.class, this);
195 log = Log.instance(context);
196 source = Source.instance(context);
197 diags = JCDiagnostic.Factory.instance(context);
198 options = Options.instance(context);
199 printProcessorInfo = options.isSet(XPRINTPROCESSORINFO);
200 printRounds = options.isSet(XPRINTROUNDS);
201 verbose = options.isSet(VERBOSE);
202 lint = Lint.instance(context).isEnabled(PROCESSING);
203 compiler = JavaCompiler.instance(context);
204 if (options.isSet(PROC, "only") || options.isSet(XPRINT)) {
205 compiler.shouldStopPolicyIfNoError = CompileState.PROCESS;
206 }
207 fatalErrors = options.isSet("fatalEnterError");
208 showResolveErrors = options.isSet("showResolveErrors");
209 werror = options.isSet(WERROR);
210 fileManager = context.get(JavaFileManager.class);
211 platformAnnotations = initPlatformAnnotations();
212
213 // Initialize services before any processors are initialized
214 // in case processors use them.
215 filer = new JavacFiler(context);
216 messager = new JavacMessager(context, this);
217 elementUtils = JavacElements.instance(context);
218 typeUtils = JavacTypes.instance(context);
219 modules = Modules.instance(context);
220 types = Types.instance(context);
221 processorOptions = initProcessorOptions();
222 unmatchedProcessorOptions = initUnmatchedProcessorOptions();
223 messages = JavacMessages.instance(context);
224 taskListener = MultiTaskListener.instance(context);
225 symtab = Symtab.instance(context);
226 names = Names.instance(context);
227 enter = Enter.instance(context);
228 initialCompleter = ClassFinder.instance(context).getCompleter();
229 chk = Check.instance(context);
262 } else {
263 // If processorpath is not explicitly set, use the classpath.
264 processorClassLoader = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
265 ? fileManager.getClassLoader(ANNOTATION_PROCESSOR_PATH)
266 : fileManager.getClassLoader(CLASS_PATH);
267
268 moduleHelper.addExports(processorClassLoader);
269
270 if (processorClassLoader != null && processorClassLoader instanceof Closeable) {
271 compiler.closeables = compiler.closeables.prepend((Closeable) processorClassLoader);
272 }
273 }
274 } catch (SecurityException e) {
275 processorLoaderException = e;
276 }
277 }
278
279 private void initProcessorIterator(Iterable<? extends Processor> processors) {
280 Iterator<? extends Processor> processorIterator;
281
282 if (options.isSet(XPRINT)) {
283 try {
284 processorIterator = List.of(new PrintingProcessor()).iterator();
285 } catch (Throwable t) {
286 AssertionError assertError =
287 new AssertionError("Problem instantiating PrintingProcessor.");
288 assertError.initCause(t);
289 throw assertError;
290 }
291 } else if (processors != null) {
292 processorIterator = processors.iterator();
293 } else {
294 if (processorLoaderException == null) {
295 /*
296 * If the "-processor" option is used, search the appropriate
297 * path for the named class. Otherwise, use a service
298 * provider mechanism to create the processor iterator.
299 */
300 String processorNames = options.get(PROCESSOR);
301 if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
302 processorIterator = (processorNames == null) ?
303 new ServiceIterator(serviceLoader, log) :
304 new NameServiceIterator(serviceLoader, log, processorNames);
305 } else if (processorNames != null) {
306 processorIterator = new NameProcessIterator(processorNames, processorClassLoader, log);
307 } else {
308 processorIterator = new ServiceIterator(processorClassLoader, log);
309 }
310 } else {
311 /*
312 * A security exception will occur if we can't create a classloader.
313 * Ignore the exception if, with hindsight, we didn't need it anyway
314 * (i.e. no processor was specified either explicitly, or implicitly,
315 * in service configuration file.) Otherwise, we cannot continue.
316 */
317 processorIterator = handleServiceLoaderUnavailability("proc.cant.create.loader",
318 processorLoaderException);
319 }
320 }
346 }
347
348 /**
349 * Returns an empty processor iterator if no processors are on the
350 * relevant path, otherwise if processors are present, logs an
351 * error. Called when a service loader is unavailable for some
352 * reason, either because a service loader class cannot be found
353 * or because a security policy prevents class loaders from being
354 * created.
355 *
356 * @param key The resource key to use to log an error message
357 * @param e If non-null, pass this exception to Abort
358 */
359 private Iterator<Processor> handleServiceLoaderUnavailability(String key, Exception e) {
360 if (fileManager instanceof JavacFileManager) {
361 StandardJavaFileManager standardFileManager = (JavacFileManager) fileManager;
362 Iterable<? extends Path> workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
363 ? standardFileManager.getLocationAsPaths(ANNOTATION_PROCESSOR_PATH)
364 : standardFileManager.getLocationAsPaths(CLASS_PATH);
365
366 if (needClassLoader(options.get(PROCESSOR), workingPath) )
367 handleException(key, e);
368
369 } else {
370 handleException(key, e);
371 }
372
373 java.util.List<Processor> pl = Collections.emptyList();
374 return pl.iterator();
375 }
376
377 /**
378 * Handle a security exception thrown during initializing the
379 * Processor iterator.
380 */
381 private void handleException(String key, Exception e) {
382 if (e != null) {
383 log.error(key, e.getLocalizedMessage());
384 throw new Abort(e);
385 } else {
386 log.error(key);
|
45 import javax.tools.JavaFileObject;
46 import javax.tools.JavaFileObject.Kind;
47 import javax.tools.StandardJavaFileManager;
48
49 import static javax.tools.StandardLocation.*;
50
51 import com.sun.source.util.TaskEvent;
52 import com.sun.tools.javac.api.MultiTaskListener;
53 import com.sun.tools.javac.code.*;
54 import com.sun.tools.javac.code.Scope.WriteableScope;
55 import com.sun.tools.javac.code.Symbol.*;
56 import com.sun.tools.javac.code.Type.ClassType;
57 import com.sun.tools.javac.code.Types;
58 import com.sun.tools.javac.comp.AttrContext;
59 import com.sun.tools.javac.comp.Check;
60 import com.sun.tools.javac.comp.Enter;
61 import com.sun.tools.javac.comp.Env;
62 import com.sun.tools.javac.comp.Modules;
63 import com.sun.tools.javac.file.JavacFileManager;
64 import com.sun.tools.javac.main.JavaCompiler;
65 import com.sun.tools.javac.main.Option;
66 import com.sun.tools.javac.model.JavacElements;
67 import com.sun.tools.javac.model.JavacTypes;
68 import com.sun.tools.javac.platform.PlatformDescription;
69 import com.sun.tools.javac.platform.PlatformDescription.PluginInfo;
70 import com.sun.tools.javac.resources.CompilerProperties.Errors;
71 import com.sun.tools.javac.tree.*;
72 import com.sun.tools.javac.tree.JCTree.*;
73 import com.sun.tools.javac.util.Abort;
74 import com.sun.tools.javac.util.Assert;
75 import com.sun.tools.javac.util.ClientCodeException;
76 import com.sun.tools.javac.util.Context;
77 import com.sun.tools.javac.util.Convert;
78 import com.sun.tools.javac.util.DefinedBy;
79 import com.sun.tools.javac.util.DefinedBy.Api;
80 import com.sun.tools.javac.util.Iterators;
81 import com.sun.tools.javac.util.JCDiagnostic;
82 import com.sun.tools.javac.util.JavacMessages;
83 import com.sun.tools.javac.util.List;
84 import com.sun.tools.javac.util.Log;
85 import com.sun.tools.javac.util.MatchingUtils;
86 import com.sun.tools.javac.util.ModuleHelper;
87 import com.sun.tools.javac.util.Name;
88 import com.sun.tools.javac.util.Names;
89 import com.sun.tools.javac.util.Options;
90
91 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
92 import static com.sun.tools.javac.code.Kinds.Kind.*;
93 import static com.sun.tools.javac.comp.CompileStates.CompileState;
94 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
95
96 /**
97 * Objects of this class hold and manage the state needed to support
98 * annotation processing.
99 *
100 * <p><b>This is NOT part of any supported API.
101 * If you write code that depends on this, you do so at your own risk.
102 * This code and its internal interfaces are subject to change or
103 * deletion without notice.</b>
104 */
105 public class JavacProcessingEnvironment implements ProcessingEnvironment, Closeable {
106 private final Options options;
107
108 private final boolean printProcessorInfo;
109 private final boolean printRounds;
110 private final boolean verbose;
111 private final boolean lint;
112 private final boolean fatalErrors;
179 private final Check chk;
180 private final ModuleSymbol defaultModule;
181
182 private final Context context;
183
184 /** Get the JavacProcessingEnvironment instance for this context. */
185 public static JavacProcessingEnvironment instance(Context context) {
186 JavacProcessingEnvironment instance = context.get(JavacProcessingEnvironment.class);
187 if (instance == null)
188 instance = new JavacProcessingEnvironment(context);
189 return instance;
190 }
191
192 protected JavacProcessingEnvironment(Context context) {
193 this.context = context;
194 context.put(JavacProcessingEnvironment.class, this);
195 log = Log.instance(context);
196 source = Source.instance(context);
197 diags = JCDiagnostic.Factory.instance(context);
198 options = Options.instance(context);
199 printProcessorInfo = options.isSet(Option.XPRINTPROCESSORINFO);
200 printRounds = options.isSet(Option.XPRINTROUNDS);
201 verbose = options.isSet(Option.VERBOSE);
202 lint = Lint.instance(context).isEnabled(PROCESSING);
203 compiler = JavaCompiler.instance(context);
204 if (options.isSet(Option.PROC, "only") || options.isSet(Option.XPRINT)) {
205 compiler.shouldStopPolicyIfNoError = CompileState.PROCESS;
206 }
207 fatalErrors = options.isSet("fatalEnterError");
208 showResolveErrors = options.isSet("showResolveErrors");
209 werror = options.isSet(Option.WERROR);
210 fileManager = context.get(JavaFileManager.class);
211 platformAnnotations = initPlatformAnnotations();
212
213 // Initialize services before any processors are initialized
214 // in case processors use them.
215 filer = new JavacFiler(context);
216 messager = new JavacMessager(context, this);
217 elementUtils = JavacElements.instance(context);
218 typeUtils = JavacTypes.instance(context);
219 modules = Modules.instance(context);
220 types = Types.instance(context);
221 processorOptions = initProcessorOptions();
222 unmatchedProcessorOptions = initUnmatchedProcessorOptions();
223 messages = JavacMessages.instance(context);
224 taskListener = MultiTaskListener.instance(context);
225 symtab = Symtab.instance(context);
226 names = Names.instance(context);
227 enter = Enter.instance(context);
228 initialCompleter = ClassFinder.instance(context).getCompleter();
229 chk = Check.instance(context);
262 } else {
263 // If processorpath is not explicitly set, use the classpath.
264 processorClassLoader = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
265 ? fileManager.getClassLoader(ANNOTATION_PROCESSOR_PATH)
266 : fileManager.getClassLoader(CLASS_PATH);
267
268 moduleHelper.addExports(processorClassLoader);
269
270 if (processorClassLoader != null && processorClassLoader instanceof Closeable) {
271 compiler.closeables = compiler.closeables.prepend((Closeable) processorClassLoader);
272 }
273 }
274 } catch (SecurityException e) {
275 processorLoaderException = e;
276 }
277 }
278
279 private void initProcessorIterator(Iterable<? extends Processor> processors) {
280 Iterator<? extends Processor> processorIterator;
281
282 if (options.isSet(Option.XPRINT)) {
283 try {
284 processorIterator = List.of(new PrintingProcessor()).iterator();
285 } catch (Throwable t) {
286 AssertionError assertError =
287 new AssertionError("Problem instantiating PrintingProcessor.");
288 assertError.initCause(t);
289 throw assertError;
290 }
291 } else if (processors != null) {
292 processorIterator = processors.iterator();
293 } else {
294 if (processorLoaderException == null) {
295 /*
296 * If the "-processor" option is used, search the appropriate
297 * path for the named class. Otherwise, use a service
298 * provider mechanism to create the processor iterator.
299 */
300 String processorNames = options.get(Option.PROCESSOR);
301 if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
302 processorIterator = (processorNames == null) ?
303 new ServiceIterator(serviceLoader, log) :
304 new NameServiceIterator(serviceLoader, log, processorNames);
305 } else if (processorNames != null) {
306 processorIterator = new NameProcessIterator(processorNames, processorClassLoader, log);
307 } else {
308 processorIterator = new ServiceIterator(processorClassLoader, log);
309 }
310 } else {
311 /*
312 * A security exception will occur if we can't create a classloader.
313 * Ignore the exception if, with hindsight, we didn't need it anyway
314 * (i.e. no processor was specified either explicitly, or implicitly,
315 * in service configuration file.) Otherwise, we cannot continue.
316 */
317 processorIterator = handleServiceLoaderUnavailability("proc.cant.create.loader",
318 processorLoaderException);
319 }
320 }
346 }
347
348 /**
349 * Returns an empty processor iterator if no processors are on the
350 * relevant path, otherwise if processors are present, logs an
351 * error. Called when a service loader is unavailable for some
352 * reason, either because a service loader class cannot be found
353 * or because a security policy prevents class loaders from being
354 * created.
355 *
356 * @param key The resource key to use to log an error message
357 * @param e If non-null, pass this exception to Abort
358 */
359 private Iterator<Processor> handleServiceLoaderUnavailability(String key, Exception e) {
360 if (fileManager instanceof JavacFileManager) {
361 StandardJavaFileManager standardFileManager = (JavacFileManager) fileManager;
362 Iterable<? extends Path> workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
363 ? standardFileManager.getLocationAsPaths(ANNOTATION_PROCESSOR_PATH)
364 : standardFileManager.getLocationAsPaths(CLASS_PATH);
365
366 if (needClassLoader(options.get(Option.PROCESSOR), workingPath) )
367 handleException(key, e);
368
369 } else {
370 handleException(key, e);
371 }
372
373 java.util.List<Processor> pl = Collections.emptyList();
374 return pl.iterator();
375 }
376
377 /**
378 * Handle a security exception thrown during initializing the
379 * Processor iterator.
380 */
381 private void handleException(String key, Exception e) {
382 if (e != null) {
383 log.error(key, e.getLocalizedMessage());
384 throw new Abort(e);
385 } else {
386 log.error(key);
|