|
| 1 | +package online.sharedtype.exec.common; |
| 2 | + |
| 3 | +import javax.annotation.processing.Processor; |
| 4 | +import javax.tools.JavaCompiler; |
| 5 | +import javax.tools.JavaFileObject; |
| 6 | +import javax.tools.StandardJavaFileManager; |
| 7 | +import javax.tools.StandardLocation; |
| 8 | +import javax.tools.ToolProvider; |
| 9 | +import java.io.File; |
| 10 | +import java.io.IOException; |
| 11 | +import java.nio.charset.Charset; |
| 12 | +import java.nio.file.FileVisitOption; |
| 13 | +import java.nio.file.Files; |
| 14 | +import java.nio.file.Path; |
| 15 | +import java.util.Collections; |
| 16 | +import java.util.EnumSet; |
| 17 | +import java.util.List; |
| 18 | + |
| 19 | +/** |
| 20 | + * Generic annotation processor executor. This module does not depend on sharedtype-ap. |
| 21 | + * @see SharedTypeApCompilerOptions |
| 22 | + * @author Cause Chung |
| 23 | + */ |
| 24 | +public final class AnnotationProcessorExecutor { |
| 25 | + private static final String JAVA8_VERSION = "1.8"; |
| 26 | + private final Processor processor; |
| 27 | + private final Logger log; |
| 28 | + private final DependencyResolver dependencyResolver; |
| 29 | + |
| 30 | + public AnnotationProcessorExecutor(Processor processor, Logger log, DependencyResolver dependencyResolver) { |
| 31 | + this.processor = processor; |
| 32 | + this.log = log; |
| 33 | + this.dependencyResolver = dependencyResolver; |
| 34 | + } |
| 35 | + |
| 36 | + public void execute(Path projectBaseDir, |
| 37 | + Path outputDir, |
| 38 | + Iterable<Path> compileSourceRoots, |
| 39 | + String sourceEncoding, |
| 40 | + Iterable<String> compilerOptions) throws Exception { |
| 41 | + SimpleDiagnosticListener diagnosticListener = new SimpleDiagnosticListener(log, projectBaseDir); |
| 42 | + JavaCompiler compiler = getJavaCompiler(); |
| 43 | + |
| 44 | + StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, getCharset(sourceEncoding)); |
| 45 | + try (SimpleLoggerWriter logger = new SimpleLoggerWriter(log)) { |
| 46 | + if (Files.notExists(outputDir)) { |
| 47 | + Files.createDirectories(outputDir); |
| 48 | + } |
| 49 | + fileManager.setLocation(StandardLocation.SOURCE_OUTPUT, Collections.singleton(outputDir.toFile())); |
| 50 | + fileManager.setLocation(StandardLocation.CLASS_PATH, dependencyResolver.getClasspathDependencies()); |
| 51 | + Iterable<? extends JavaFileObject> sources = fileManager.getJavaFileObjectsFromFiles(walkAllSourceFiles(compileSourceRoots)); |
| 52 | + |
| 53 | + JavaCompiler.CompilationTask task = compiler.getTask(logger, fileManager, diagnosticListener, compilerOptions, null, sources); |
| 54 | + task.setProcessors(Collections.singleton(processor)); |
| 55 | + task.call(); |
| 56 | + } |
| 57 | + } |
| 58 | + |
| 59 | + private static List<File> walkAllSourceFiles(Iterable<Path> compileSourceRoots) throws IOException { |
| 60 | + SourceFileVisitor visitor = new SourceFileVisitor(); |
| 61 | + for (Path compileSourceRoot : compileSourceRoots) { |
| 62 | + if (Files.isDirectory(compileSourceRoot)) { |
| 63 | + Files.walkFileTree(compileSourceRoot, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, visitor); |
| 64 | + } |
| 65 | + } |
| 66 | + return visitor.getFiles(); |
| 67 | + } |
| 68 | + |
| 69 | + private static JavaCompiler getJavaCompiler() throws Exception { |
| 70 | + String javaVersion = System.getProperty("java.specification.version"); |
| 71 | + JavaCompiler compiler; |
| 72 | + if (JAVA8_VERSION.equals(javaVersion)) { |
| 73 | + Class<?> javacToolClass = Class.forName("com.sun.tools.javac.api.JavacTool"); |
| 74 | + compiler = (JavaCompiler) javacToolClass.getConstructor().newInstance(); |
| 75 | + } else { |
| 76 | + compiler = ToolProvider.getSystemJavaCompiler(); |
| 77 | + } |
| 78 | + if (compiler != null) { |
| 79 | + return compiler; |
| 80 | + } |
| 81 | + throw new ClassNotFoundException("Java compiler not found, currently only compiler from jdk.compiler module is supported."); |
| 82 | + } |
| 83 | + |
| 84 | + private static Charset getCharset(String encoding) { |
| 85 | + if (encoding != null) { |
| 86 | + return Charset.forName(encoding); |
| 87 | + } |
| 88 | + return null; |
| 89 | + } |
| 90 | +} |
0 commit comments