1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugin.compiler;
20
21 import javax.tools.OptionChecker;
22
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.lang.module.ModuleDescriptor;
26 import java.nio.file.Files;
27 import java.nio.file.Path;
28 import java.nio.file.Paths;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.TreeMap;
34
35 import org.apache.maven.api.JavaPathType;
36 import org.apache.maven.api.PathType;
37 import org.apache.maven.api.ProducedArtifact;
38 import org.apache.maven.api.ProjectScope;
39 import org.apache.maven.api.annotations.Nonnull;
40 import org.apache.maven.api.annotations.Nullable;
41 import org.apache.maven.api.plugin.MojoException;
42 import org.apache.maven.api.plugin.annotations.Mojo;
43 import org.apache.maven.api.plugin.annotations.Parameter;
44
45 import static org.apache.maven.plugin.compiler.SourceDirectory.CLASS_FILE_SUFFIX;
46 import static org.apache.maven.plugin.compiler.SourceDirectory.JAVA_FILE_SUFFIX;
47 import static org.apache.maven.plugin.compiler.SourceDirectory.MODULE_INFO;
48
49
50
51
52
53
54
55
56
57
58 @Mojo(name = "compile", defaultPhase = "compile")
59 public class CompilerMojo extends AbstractCompilerMojo {
60
61
62
63
64 @Parameter(property = "maven.main.skip")
65 protected boolean skipMain;
66
67
68
69
70
71 @Parameter
72 protected List<String> compileSourceRoots;
73
74
75
76
77
78
79 @Parameter(defaultValue = "${project.build.directory}/generated-sources/annotations")
80 protected Path generatedSourcesDirectory;
81
82
83
84
85 @Parameter
86 protected Set<String> includes;
87
88
89
90
91 @Parameter
92 protected Set<String> excludes;
93
94
95
96
97
98
99
100
101
102
103
104 @Parameter
105 protected Set<String> incrementalExcludes;
106
107
108
109
110 @Parameter(defaultValue = "${project.build.outputDirectory}", required = true, readonly = true)
111 protected Path outputDirectory;
112
113
114
115
116 @Parameter(defaultValue = "${project.mainArtifact}", readonly = true, required = true)
117 protected ProducedArtifact projectArtifact;
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 @Parameter
133 @Deprecated(since = "4.0.0")
134 protected boolean multiReleaseOutput;
135
136
137
138
139
140
141
142
143
144 @Parameter(defaultValue = "javac.args")
145 protected String debugFileName;
146
147
148
149
150 public CompilerMojo() {
151 super(false);
152 }
153
154
155
156
157
158
159 @Override
160 public void execute() throws MojoException {
161 if (skipMain) {
162 logger.info("Not compiling main sources");
163 return;
164 }
165 super.execute();
166 @SuppressWarnings("LocalVariableHidesMemberVariable")
167 Path outputDirectory = getOutputDirectory();
168 if (Files.isDirectory(outputDirectory) && projectArtifact != null) {
169 artifactManager.setPath(projectArtifact, outputDirectory);
170 }
171 }
172
173
174
175
176
177
178
179 @Override
180 @SuppressWarnings("deprecation")
181 protected Options acceptParameters(final OptionChecker compiler) {
182 Options compilerConfiguration = super.acceptParameters(compiler);
183 compilerConfiguration.addUnchecked(compilerArgs);
184 compilerConfiguration.addUnchecked(compilerArgument);
185 return compilerConfiguration;
186 }
187
188
189
190
191
192
193 @Nonnull
194 @Override
195 protected List<Path> getCompileSourceRoots() {
196 List<Path> sources;
197 if (compileSourceRoots == null || compileSourceRoots.isEmpty()) {
198 sources = projectManager.getCompileSourceRoots(project, ProjectScope.MAIN);
199 } else {
200 sources = compileSourceRoots.stream().map(Paths::get).toList();
201 }
202 return sources;
203 }
204
205
206
207
208 @Nullable
209 @Override
210 protected Path getGeneratedSourcesDirectory() {
211 return generatedSourcesDirectory;
212 }
213
214
215
216
217 @Override
218 protected Set<String> getIncludes() {
219 return (includes != null) ? includes : Set.of();
220 }
221
222
223
224
225 @Override
226 protected Set<String> getExcludes() {
227 return (excludes != null) ? excludes : Set.of();
228 }
229
230
231
232
233 @Override
234 protected Set<String> getIncrementalExcludes() {
235 return (incrementalExcludes != null) ? incrementalExcludes : Set.of();
236 }
237
238
239
240
241
242
243 @Nonnull
244 @Override
245 protected Path getOutputDirectory() {
246 if (SUPPORT_LEGACY && multiReleaseOutput && release != null) {
247 return outputDirectory.resolve(Path.of("META-INF", "versions", release));
248 }
249 return outputDirectory;
250 }
251
252
253
254
255 @Nullable
256 @Override
257 protected String getDebugFileName() {
258 return debugFileName;
259 }
260
261
262
263
264
265
266
267
268
269
270 @Override
271 @Deprecated(since = "4.0.0")
272 protected void addImplicitDependencies(Map<PathType, List<Path>> addTo, boolean hasModuleDeclaration)
273 throws IOException {
274 if (SUPPORT_LEGACY && multiReleaseOutput) {
275 var paths = new TreeMap<Integer, Path>();
276 Path root = outputDirectory.resolve(Path.of("META-INF", "versions"));
277 Files.walk(root, 1).forEach((path) -> {
278 int version;
279 if (path.equals(root)) {
280 path = outputDirectory;
281 version = 0;
282 } else {
283 try {
284 version = Integer.parseInt(path.getFileName().toString());
285 } catch (NumberFormatException e) {
286 throw new CompilationFailureException("Invalid version number for " + path, e);
287 }
288 }
289 if (paths.put(version, path) != null) {
290 throw new CompilationFailureException("Duplicated version number for " + path);
291 }
292 });
293
294
295
296
297 String moduleName = null;
298 for (Path path : paths.values()) {
299 path = path.resolve(MODULE_INFO + CLASS_FILE_SUFFIX);
300 if (Files.exists(path)) {
301 try (InputStream in = Files.newInputStream(path)) {
302 moduleName = ModuleDescriptor.read(in).name();
303 }
304 break;
305 }
306 }
307
308
309
310
311 if (moduleName == null) {
312 for (Path path : getCompileSourceRoots()) {
313 moduleName = parseModuleInfoName(path.resolve(MODULE_INFO + JAVA_FILE_SUFFIX));
314 if (moduleName != null) {
315 break;
316 }
317 }
318 }
319 var pathType = (moduleName != null) ? JavaPathType.patchModule(moduleName) : JavaPathType.CLASSES;
320 addTo.computeIfAbsent(pathType, (key) -> new ArrayList<>())
321 .addAll(paths.descendingMap().values());
322 }
323 }
324 }