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 }