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.processing;
27
28 import java.io.Closeable;
29 import java.io.File;
30 import java.io.PrintWriter;
31 import java.io.StringWriter;
32 import java.net.MalformedURLException;
33 import java.net.URL;
34 import java.util.*;
35 import java.util.regex.*;
36
37 import javax.annotation.processing.*;
38 import javax.lang.model.SourceVersion;
39 import javax.lang.model.element.*;
40 import javax.lang.model.util.*;
41 import javax.tools.JavaFileManager;
42 import javax.tools.JavaFileObject;
43 import javax.tools.StandardJavaFileManager;
44 import static javax.tools.StandardLocation.*;
45
46 import com.sun.source.util.TaskEvent;
47 import com.sun.tools.javac.api.MultiTaskListener;
48 import com.sun.tools.javac.code.*;
49 import com.sun.tools.javac.code.Symbol.*;
50 import com.sun.tools.javac.code.Type.ClassType;
51 import com.sun.tools.javac.code.Types;
52 import com.sun.tools.javac.comp.AttrContext;
53 import com.sun.tools.javac.comp.Check;
54 import com.sun.tools.javac.comp.Enter;
55 import com.sun.tools.javac.comp.Env;
56 import com.sun.tools.javac.file.JavacFileManager;
57 import com.sun.tools.javac.main.JavaCompiler;
58 import com.sun.tools.javac.model.JavacElements;
59 import com.sun.tools.javac.model.JavacTypes;
60 import com.sun.tools.javac.tree.*;
61 import com.sun.tools.javac.tree.JCTree.*;
62 import com.sun.tools.javac.util.Abort;
63 import com.sun.tools.javac.util.Assert;
64 import com.sun.tools.javac.util.ClientCodeException;
65 import com.sun.tools.javac.util.Context;
66 import com.sun.tools.javac.util.Convert;
67 import com.sun.tools.javac.util.DefinedBy;
68 import com.sun.tools.javac.util.DefinedBy.Api;
69 import com.sun.tools.javac.util.JCDiagnostic;
70 import com.sun.tools.javac.util.JavacMessages;
71 import com.sun.tools.javac.util.List;
72 import com.sun.tools.javac.util.Log;
73 import com.sun.tools.javac.util.MatchingUtils;
74 import com.sun.tools.javac.util.Name;
75 import com.sun.tools.javac.util.Names;
76 import com.sun.tools.javac.util.Options;
77 import com.sun.tools.javac.util.ServiceLoader;
78 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
79 import static com.sun.tools.javac.code.Kinds.Kind.*;
80 import static com.sun.tools.javac.main.Option.*;
81 import static com.sun.tools.javac.comp.CompileStates.CompileState;
82 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
83
84 /**
85 * Objects of this class hold and manage the state needed to support
86 * annotation processing.
87 *
88 * <p><b>This is NOT part of any supported API.
265 * If the "-processor" option is used, search the appropriate
266 * path for the named class. Otherwise, use a service
267 * provider mechanism to create the processor iterator.
268 */
269 if (processorNames != null) {
270 processorIterator = new NameProcessIterator(processorNames, processorClassLoader, log);
271 } else {
272 processorIterator = new ServiceIterator(processorClassLoader, log);
273 }
274 } else {
275 /*
276 * A security exception will occur if we can't create a classloader.
277 * Ignore the exception if, with hindsight, we didn't need it anyway
278 * (i.e. no processor was specified either explicitly, or implicitly,
279 * in service configuration file.) Otherwise, we cannot continue.
280 */
281 processorIterator = handleServiceLoaderUnavailability("proc.cant.create.loader",
282 processorClassLoaderException);
283 }
284 }
285 discoveredProcs = new DiscoveredProcessors(processorIterator);
286 }
287
288 /**
289 * Returns an empty processor iterator if no processors are on the
290 * relevant path, otherwise if processors are present, logs an
291 * error. Called when a service loader is unavailable for some
292 * reason, either because a service loader class cannot be found
293 * or because a security policy prevents class loaders from being
294 * created.
295 *
296 * @param key The resource key to use to log an error message
297 * @param e If non-null, pass this exception to Abort
298 */
299 private Iterator<Processor> handleServiceLoaderUnavailability(String key, Exception e) {
300 JavaFileManager fileManager = context.get(JavaFileManager.class);
301
302 if (fileManager instanceof JavacFileManager) {
303 StandardJavaFileManager standardFileManager = (JavacFileManager) fileManager;
304 Iterable<? extends File> workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
305 ? standardFileManager.getLocation(ANNOTATION_PROCESSOR_PATH)
464 Set<String> keySet = options.keySet();
465 Map<String, String> tempOptions = new LinkedHashMap<>();
466
467 for(String key : keySet) {
468 if (key.startsWith("-A") && key.length() > 2) {
469 int sepIndex = key.indexOf('=');
470 String candidateKey = null;
471 String candidateValue = null;
472
473 if (sepIndex == -1)
474 candidateKey = key.substring(2);
475 else if (sepIndex >= 3) {
476 candidateKey = key.substring(2, sepIndex);
477 candidateValue = (sepIndex < key.length()-1)?
478 key.substring(sepIndex+1) : null;
479 }
480 tempOptions.put(candidateKey, candidateValue);
481 }
482 }
483
484 return Collections.unmodifiableMap(tempOptions);
485 }
486
487 private Set<String> initUnmatchedProcessorOptions() {
488 Set<String> unmatchedProcessorOptions = new HashSet<>();
489 unmatchedProcessorOptions.addAll(processorOptions.keySet());
490 return unmatchedProcessorOptions;
491 }
492
493 /**
494 * State about how a processor has been used by the tool. If a
495 * processor has been used on a prior round, its process method is
496 * called on all subsequent rounds, perhaps with an empty set of
497 * annotations to process. The {@code annotationSupported} method
498 * caches the supported annotation information from the first (and
499 * only) getSupportedAnnotationTypes call to the processor.
500 */
501 static class ProcessorState {
502 public Processor processor;
503 public boolean contributed;
|
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.processing;
27
28 import java.io.Closeable;
29 import java.io.File;
30 import java.io.PrintWriter;
31 import java.io.StringWriter;
32 import java.net.MalformedURLException;
33 import java.net.URL;
34 import java.util.*;
35 import java.util.regex.*;
36 import java.util.stream.Collectors;
37
38 import javax.annotation.processing.*;
39 import javax.lang.model.SourceVersion;
40 import javax.lang.model.element.*;
41 import javax.lang.model.util.*;
42 import javax.tools.JavaFileManager;
43 import javax.tools.JavaFileObject;
44 import javax.tools.StandardJavaFileManager;
45 import static javax.tools.StandardLocation.*;
46
47 import com.sun.source.util.TaskEvent;
48 import com.sun.tools.javac.api.MultiTaskListener;
49 import com.sun.tools.javac.code.*;
50 import com.sun.tools.javac.code.Symbol.*;
51 import com.sun.tools.javac.code.Type.ClassType;
52 import com.sun.tools.javac.code.Types;
53 import com.sun.tools.javac.comp.AttrContext;
54 import com.sun.tools.javac.comp.Check;
55 import com.sun.tools.javac.comp.Enter;
56 import com.sun.tools.javac.comp.Env;
57 import com.sun.tools.javac.file.JavacFileManager;
58 import com.sun.tools.javac.main.JavaCompiler;
59 import com.sun.tools.javac.model.JavacElements;
60 import com.sun.tools.javac.model.JavacTypes;
61 import com.sun.tools.javac.platform.PlatformProvider;
62 import com.sun.tools.javac.platform.PlatformProvider.PluginInfo;
63 import com.sun.tools.javac.tree.*;
64 import com.sun.tools.javac.tree.JCTree.*;
65 import com.sun.tools.javac.util.Abort;
66 import com.sun.tools.javac.util.Assert;
67 import com.sun.tools.javac.util.ClientCodeException;
68 import com.sun.tools.javac.util.Context;
69 import com.sun.tools.javac.util.Convert;
70 import com.sun.tools.javac.util.DefinedBy;
71 import com.sun.tools.javac.util.DefinedBy.Api;
72 import com.sun.tools.javac.util.Iterators;
73 import com.sun.tools.javac.util.JCDiagnostic;
74 import com.sun.tools.javac.util.JavacMessages;
75 import com.sun.tools.javac.util.List;
76 import com.sun.tools.javac.util.Log;
77 import com.sun.tools.javac.util.MatchingUtils;
78 import com.sun.tools.javac.util.Name;
79 import com.sun.tools.javac.util.Names;
80 import com.sun.tools.javac.util.Options;
81 import com.sun.tools.javac.util.ServiceLoader;
82 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
83 import static com.sun.tools.javac.code.Kinds.Kind.*;
84 import static com.sun.tools.javac.main.Option.*;
85 import static com.sun.tools.javac.comp.CompileStates.CompileState;
86 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
87
88 /**
89 * Objects of this class hold and manage the state needed to support
90 * annotation processing.
91 *
92 * <p><b>This is NOT part of any supported API.
269 * If the "-processor" option is used, search the appropriate
270 * path for the named class. Otherwise, use a service
271 * provider mechanism to create the processor iterator.
272 */
273 if (processorNames != null) {
274 processorIterator = new NameProcessIterator(processorNames, processorClassLoader, log);
275 } else {
276 processorIterator = new ServiceIterator(processorClassLoader, log);
277 }
278 } else {
279 /*
280 * A security exception will occur if we can't create a classloader.
281 * Ignore the exception if, with hindsight, we didn't need it anyway
282 * (i.e. no processor was specified either explicitly, or implicitly,
283 * in service configuration file.) Otherwise, we cannot continue.
284 */
285 processorIterator = handleServiceLoaderUnavailability("proc.cant.create.loader",
286 processorClassLoaderException);
287 }
288 }
289 PlatformProvider platformProvider = context.get(PlatformProvider.class);
290 java.util.List<Processor> platformProcessors = Collections.emptyList();
291 if (platformProvider != null) {
292 platformProcessors = platformProvider.getAnnotationProcessors()
293 .stream()
294 .map(ap -> ap.getPlugin())
295 .collect(Collectors.toList());
296 }
297 List<Iterator<? extends Processor>> iterators = List.of(processorIterator,
298 platformProcessors.iterator());
299 Iterator<? extends Processor> compoundIterator =
300 Iterators.createCompoundIterator(iterators, i -> i);
301 discoveredProcs = new DiscoveredProcessors(compoundIterator);
302 }
303
304 /**
305 * Returns an empty processor iterator if no processors are on the
306 * relevant path, otherwise if processors are present, logs an
307 * error. Called when a service loader is unavailable for some
308 * reason, either because a service loader class cannot be found
309 * or because a security policy prevents class loaders from being
310 * created.
311 *
312 * @param key The resource key to use to log an error message
313 * @param e If non-null, pass this exception to Abort
314 */
315 private Iterator<Processor> handleServiceLoaderUnavailability(String key, Exception e) {
316 JavaFileManager fileManager = context.get(JavaFileManager.class);
317
318 if (fileManager instanceof JavacFileManager) {
319 StandardJavaFileManager standardFileManager = (JavacFileManager) fileManager;
320 Iterable<? extends File> workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
321 ? standardFileManager.getLocation(ANNOTATION_PROCESSOR_PATH)
480 Set<String> keySet = options.keySet();
481 Map<String, String> tempOptions = new LinkedHashMap<>();
482
483 for(String key : keySet) {
484 if (key.startsWith("-A") && key.length() > 2) {
485 int sepIndex = key.indexOf('=');
486 String candidateKey = null;
487 String candidateValue = null;
488
489 if (sepIndex == -1)
490 candidateKey = key.substring(2);
491 else if (sepIndex >= 3) {
492 candidateKey = key.substring(2, sepIndex);
493 candidateValue = (sepIndex < key.length()-1)?
494 key.substring(sepIndex+1) : null;
495 }
496 tempOptions.put(candidateKey, candidateValue);
497 }
498 }
499
500 PlatformProvider platformProvider = context.get(PlatformProvider.class);
501
502 if (platformProvider != null) {
503 for (PluginInfo<Processor> ap : platformProvider.getAnnotationProcessors()) {
504 tempOptions.putAll(ap.getOptions());
505 }
506 }
507
508 return Collections.unmodifiableMap(tempOptions);
509 }
510
511 private Set<String> initUnmatchedProcessorOptions() {
512 Set<String> unmatchedProcessorOptions = new HashSet<>();
513 unmatchedProcessorOptions.addAll(processorOptions.keySet());
514 return unmatchedProcessorOptions;
515 }
516
517 /**
518 * State about how a processor has been used by the tool. If a
519 * processor has been used on a prior round, its process method is
520 * called on all subsequent rounds, perhaps with an empty set of
521 * annotations to process. The {@code annotationSupported} method
522 * caches the supported annotation information from the first (and
523 * only) getSupportedAnnotationTypes call to the processor.
524 */
525 static class ProcessorState {
526 public Processor processor;
527 public boolean contributed;
|