1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.micronaut.build.aot;
17
18 import io.micronaut.aot.std.sourcegen.AbstractStaticServiceLoaderSourceGenerator;
19 import io.micronaut.aot.std.sourcegen.KnownMissingTypesSourceGenerator;
20 import io.micronaut.build.services.CompilerService;
21 import io.micronaut.build.services.DependencyResolutionService;
22 import io.micronaut.build.services.ExecutorService;
23 import org.apache.commons.io.FileUtils;
24 import org.apache.maven.execution.MavenSession;
25 import org.apache.maven.plugin.MojoExecutionException;
26 import org.apache.maven.plugins.annotations.Mojo;
27 import org.apache.maven.plugins.annotations.Parameter;
28 import org.apache.maven.plugins.annotations.ResolutionScope;
29 import org.apache.maven.project.MavenProject;
30 import org.eclipse.aether.RepositorySystem;
31
32 import javax.inject.Inject;
33 import java.io.File;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.OutputStream;
37 import java.nio.file.Files;
38 import java.nio.file.NoSuchFileException;
39 import java.nio.file.Path;
40 import java.util.ArrayList;
41 import java.util.List;
42 import java.util.Properties;
43 import java.util.stream.Stream;
44
45
46
47
48
49
50
51
52
53
54
55
56 @Mojo(name = AotAnalysisMojo.NAME, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME)
57 public class AotAnalysisMojo extends AbstractMicronautAotCliMojo {
58
59 public static final String NAME = "aot-analysis";
60 public static final String AOT_PROPERTIES_FILE_NAME = "aot.properties";
61
62
63
64
65 @Parameter(defaultValue = "${project.build.directory}", required = true)
66 private File baseDirectory;
67
68
69
70
71
72 @Parameter(property = "micronaut.aot.config", defaultValue = AOT_PROPERTIES_FILE_NAME)
73 private File configFile;
74
75 @Inject
76 @SuppressWarnings("CdiInjectionPointsInspection")
77 public AotAnalysisMojo(CompilerService compilerService, ExecutorService executorService, MavenProject mavenProject,
78 MavenSession mavenSession, RepositorySystem repositorySystem,
79 DependencyResolutionService dependencyResolutionService) {
80 super(compilerService, executorService, mavenProject, mavenSession, repositorySystem, dependencyResolutionService);
81 }
82
83 @Override
84 protected List<String> getExtraArgs() throws MojoExecutionException {
85 List<String> args = new ArrayList<>();
86 args.add("--output");
87 File generated = outputFile("generated");
88 args.add(generated.getAbsolutePath());
89 File effectiveConfigFile = writeEffectiveConfigFile();
90 args.add("--config");
91 args.add(effectiveConfigFile.getAbsolutePath());
92 return args;
93 }
94
95 private File writeEffectiveConfigFile() throws MojoExecutionException {
96 File userProvidedFile = this.configFile == null ? new File(baseDirectory, AOT_PROPERTIES_FILE_NAME) : this.configFile;
97 Properties props = new Properties();
98 if (userProvidedFile.exists()) {
99 try (InputStream in = Files.newInputStream(userProvidedFile.toPath())) {
100 getLog().info("Using AOT configuration file: " + configFile.getAbsolutePath());
101 props.load(in);
102 } catch (IOException e) {
103 throw new MojoExecutionException("Unable to parse configuration file", e);
104 }
105 }
106 if (!props.containsKey(KnownMissingTypesSourceGenerator.OPTION.key())) {
107 props.put(KnownMissingTypesSourceGenerator.OPTION.key(), String.join(",", Constants.TYPES_TO_CHECK));
108 }
109 props.computeIfAbsent(AbstractStaticServiceLoaderSourceGenerator.SERVICE_TYPES,
110 key -> String.join(",", Constants.SERVICE_TYPES));
111 File effectiveConfig = outputFile("effective-" + AOT_PROPERTIES_FILE_NAME);
112 try (OutputStream out = Files.newOutputStream(effectiveConfig.toPath())) {
113 props.store(out, "Effective AOT configuration");
114 } catch (IOException e) {
115 throw new MojoExecutionException("Unable to parse configuration file", e);
116 }
117 return effectiveConfig;
118 }
119
120 @Override
121 protected void onSuccess(File outputDir) throws MojoExecutionException {
122 Path generated = outputDir.toPath().resolve("generated");
123 Path generatedClasses = generated.resolve("classes");
124 try {
125 FileUtils.copyDirectory(generatedClasses.toFile(), outputDirectory);
126 try (Stream<String> linesStream = Files.lines(generated.resolve("logs").resolve("resource-filter.txt"))) {
127 linesStream.forEach(toRemove -> {
128 try {
129 Files.delete(outputDirectory.toPath().resolve(toRemove));
130 getLog().debug("Removed " + toRemove);
131 } catch (IOException e) {
132 if (!(e instanceof NoSuchFileException)) {
133 getLog().warn("Error while deleting " + toRemove, e);
134 }
135 }
136 });
137 }
138 } catch (IOException e) {
139 throw new MojoExecutionException("Error when copying the Micronaut AOT generated classes into the target directory", e);
140 }
141 }
142
143 @Override
144 String getName() {
145 return NAME;
146 }
147 }