1 package org.apache.maven.plugin.compiler;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.HashSet;
28 import java.util.LinkedHashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32
33 import org.apache.maven.artifact.Artifact;
34 import org.apache.maven.plugin.MojoExecutionException;
35 import org.apache.maven.plugins.annotations.Component;
36 import org.apache.maven.plugins.annotations.LifecyclePhase;
37 import org.apache.maven.plugins.annotations.Mojo;
38 import org.apache.maven.plugins.annotations.Parameter;
39 import org.apache.maven.plugins.annotations.ResolutionScope;
40 import org.apache.maven.project.MavenProject;
41 import org.apache.maven.shared.utils.StringUtils;
42 import org.apache.maven.shared.utils.logging.MessageUtils;
43 import org.apache.maven.toolchain.Toolchain;
44 import org.apache.maven.toolchain.java.DefaultJavaToolChain;
45 import org.codehaus.plexus.compiler.util.scan.SimpleSourceInclusionScanner;
46 import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
47 import org.codehaus.plexus.compiler.util.scan.StaleSourceScanner;
48 import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor;
49 import org.codehaus.plexus.languages.java.jpms.LocationManager;
50 import org.codehaus.plexus.languages.java.jpms.ResolvePathsRequest;
51 import org.codehaus.plexus.languages.java.jpms.ResolvePathsResult;
52 import org.codehaus.plexus.languages.java.jpms.ResolvePathsResult.ModuleNameSource;
53
54
55
56
57
58
59
60
61 @Mojo( name = "compile", defaultPhase = LifecyclePhase.COMPILE, threadSafe = true,
62 requiresDependencyResolution = ResolutionScope.COMPILE )
63 public class CompilerMojo
64 extends AbstractCompilerMojo
65 {
66
67
68
69 @Parameter( defaultValue = "${project.compileSourceRoots}", readonly = true, required = true )
70 private List<String> compileSourceRoots;
71
72
73
74
75 @Parameter( defaultValue = "${project.build.outputDirectory}", required = true, readonly = true )
76 private File outputDirectory;
77
78
79
80
81
82
83 @Parameter( defaultValue = "${project.artifact}", readonly = true, required = true )
84 private Artifact projectArtifact;
85
86
87
88
89 @Parameter
90 private Set<String> includes = new HashSet<String>();
91
92
93
94
95 @Parameter
96 private Set<String> excludes = new HashSet<String>();
97
98
99
100
101
102
103
104
105 @Parameter( defaultValue = "${project.build.directory}/generated-sources/annotations" )
106 private File generatedSourcesDirectory;
107
108
109
110
111
112 @Parameter( property = "maven.main.skip" )
113 private boolean skipMain;
114
115 @Parameter( defaultValue = "${project.compileClasspathElements}", readonly = true, required = true )
116 private List<String> compilePath;
117
118 @Parameter
119 private boolean allowPartialRequirements;
120
121 @Component
122 private LocationManager locationManager;
123
124 private List<String> classpathElements;
125
126 private List<String> modulepathElements;
127
128 private Map<String, JavaModuleDescriptor> pathElements;
129
130 protected List<String> getCompileSourceRoots()
131 {
132 return compileSourceRoots;
133 }
134
135 @Override
136 protected List<String> getClasspathElements()
137 {
138 return classpathElements;
139 }
140
141 @Override
142 protected List<String> getModulepathElements()
143 {
144 return modulepathElements;
145 }
146
147 @Override
148 protected Map<String, JavaModuleDescriptor> getPathElements()
149 {
150
151 return null;
152 }
153
154 protected File getOutputDirectory()
155 {
156 return outputDirectory;
157 }
158
159 public void execute()
160 throws MojoExecutionException, CompilationFailureException
161 {
162 if ( skipMain )
163 {
164 getLog().info( "Not compiling main sources" );
165 return;
166 }
167
168 super.execute();
169
170 if ( outputDirectory.isDirectory() )
171 {
172 projectArtifact.setFile( outputDirectory );
173 }
174 }
175
176 @Override
177 protected void preparePaths( Set<File> sourceFiles )
178 {
179 assert compilePath != null;
180
181 File moduleDescriptorPath = null;
182
183 boolean hasModuleDescriptor = false;
184 for ( File sourceFile : sourceFiles )
185 {
186 if ( "module-info.java".equals( sourceFile.getName() ) )
187 {
188 moduleDescriptorPath = sourceFile;
189 hasModuleDescriptor = true;
190 break;
191 }
192 }
193
194 if ( hasModuleDescriptor )
195 {
196
197
198
199
200 modulepathElements = new ArrayList<String>( compilePath.size() );
201 classpathElements = new ArrayList<String>( compilePath.size() );
202 pathElements = new LinkedHashMap<String, JavaModuleDescriptor>( compilePath.size() );
203
204 ResolvePathsResult<File> resolvePathsResult;
205 try
206 {
207 Collection<File> dependencyArtifacts = getCompileClasspathElements( getProject() );
208
209 ResolvePathsRequest<File> request =
210 ResolvePathsRequest.withFiles( dependencyArtifacts )
211 .setMainModuleDescriptor( moduleDescriptorPath );
212
213 Toolchain toolchain = getToolchain();
214 if ( toolchain != null && toolchain instanceof DefaultJavaToolChain )
215 {
216 request.setJdkHome( new File( ( (DefaultJavaToolChain) toolchain ).getJavaHome() ) );
217 }
218
219 resolvePathsResult = locationManager.resolvePaths( request );
220
221 JavaModuleDescriptor moduleDescriptor = resolvePathsResult.getMainModuleDescriptor();
222
223 for ( Map.Entry<File, ModuleNameSource> entry : resolvePathsResult.getModulepathElements().entrySet() )
224 {
225 if ( ModuleNameSource.FILENAME.equals( entry.getValue() ) )
226 {
227 final String message = "Required filename-based automodules detected. "
228 + "Please don't publish this project to a public artifact repository!";
229
230 if ( moduleDescriptor.exports().isEmpty() )
231 {
232
233 getLog().info( message );
234 }
235 else
236 {
237
238 writeBoxedWarning( message );
239 }
240 break;
241 }
242 }
243
244 for ( Map.Entry<File, JavaModuleDescriptor> entry : resolvePathsResult.getPathElements().entrySet() )
245 {
246 pathElements.put( entry.getKey().getPath(), entry.getValue() );
247 }
248
249 for ( File file : resolvePathsResult.getClasspathElements() )
250 {
251 classpathElements.add( file.getPath() );
252 }
253
254 for ( File file : resolvePathsResult.getModulepathElements().keySet() )
255 {
256 modulepathElements.add( file.getPath() );
257 }
258 }
259 catch ( IOException e )
260 {
261 getLog().warn( e.getMessage() );
262 }
263 }
264 else
265 {
266 classpathElements = compilePath;
267 modulepathElements = Collections.emptyList();
268 }
269 }
270
271 private List<File> getCompileClasspathElements( MavenProject project )
272 {
273 List<File> list = new ArrayList<File>( project.getArtifacts().size() + 1 );
274
275 list.add( new File( project.getBuild().getOutputDirectory() ) );
276
277 for ( Artifact a : project.getArtifacts() )
278 {
279 list.add( a.getFile() );
280 }
281 return list;
282 }
283
284 protected SourceInclusionScanner getSourceInclusionScanner( int staleMillis )
285 {
286 SourceInclusionScanner scanner;
287
288 if ( includes.isEmpty() && excludes.isEmpty() )
289 {
290 scanner = new StaleSourceScanner( staleMillis );
291 }
292 else
293 {
294 if ( includes.isEmpty() )
295 {
296 includes.add( "**/*.java" );
297 }
298 scanner = new StaleSourceScanner( staleMillis, includes, excludes );
299 }
300
301 return scanner;
302 }
303
304 protected SourceInclusionScanner getSourceInclusionScanner( String inputFileEnding )
305 {
306 SourceInclusionScanner scanner;
307
308
309 String defaultIncludePattern = "**/*" + ( inputFileEnding.startsWith( "." ) ? "" : "." ) + inputFileEnding;
310
311 if ( includes.isEmpty() && excludes.isEmpty() )
312 {
313 includes = Collections.singleton( defaultIncludePattern );
314 scanner = new SimpleSourceInclusionScanner( includes, Collections.<String>emptySet() );
315 }
316 else
317 {
318 if ( includes.isEmpty() )
319 {
320 includes.add( defaultIncludePattern );
321 }
322 scanner = new SimpleSourceInclusionScanner( includes, excludes );
323 }
324
325 return scanner;
326 }
327
328 protected String getSource()
329 {
330 return source;
331 }
332
333 protected String getTarget()
334 {
335 return target;
336 }
337
338 @Override
339 protected String getRelease()
340 {
341 return release;
342 }
343
344 protected String getCompilerArgument()
345 {
346 return compilerArgument;
347 }
348
349 protected Map<String, String> getCompilerArguments()
350 {
351 return compilerArguments;
352 }
353
354 protected File getGeneratedSourcesDirectory()
355 {
356 return generatedSourcesDirectory;
357 }
358
359 private void writeBoxedWarning( String message )
360 {
361 String line = StringUtils.repeat( "*", message.length() + 4 );
362 getLog().warn( line );
363 getLog().warn( "* " + MessageUtils.buffer().strong( message ) + " *" );
364 getLog().warn( line );
365 }
366 }