1 | |
package org.apache.maven.plugin.invoker; |
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
import java.io.BufferedReader; |
23 | |
import java.io.File; |
24 | |
import java.io.FileInputStream; |
25 | |
import java.io.FileOutputStream; |
26 | |
import java.io.FileWriter; |
27 | |
import java.io.IOException; |
28 | |
import java.io.InputStream; |
29 | |
import java.io.OutputStreamWriter; |
30 | |
import java.io.Reader; |
31 | |
import java.io.Writer; |
32 | |
import java.text.DecimalFormat; |
33 | |
import java.text.DecimalFormatSymbols; |
34 | |
import java.util.ArrayList; |
35 | |
import java.util.Arrays; |
36 | |
import java.util.Collection; |
37 | |
import java.util.Collections; |
38 | |
import java.util.HashMap; |
39 | |
import java.util.LinkedHashMap; |
40 | |
import java.util.LinkedHashSet; |
41 | |
import java.util.List; |
42 | |
import java.util.Locale; |
43 | |
import java.util.Map; |
44 | |
import java.util.Properties; |
45 | |
import java.util.Set; |
46 | |
import java.util.StringTokenizer; |
47 | |
import java.util.TreeSet; |
48 | |
import java.util.concurrent.ExecutorService; |
49 | |
import java.util.concurrent.Executors; |
50 | |
import java.util.concurrent.TimeUnit; |
51 | |
|
52 | |
import org.apache.commons.io.input.XmlStreamReader; |
53 | |
import org.apache.maven.artifact.Artifact; |
54 | |
import org.apache.maven.model.Model; |
55 | |
import org.apache.maven.model.Profile; |
56 | |
import org.apache.maven.plugin.AbstractMojo; |
57 | |
import org.apache.maven.plugin.MojoExecution; |
58 | |
import org.apache.maven.plugin.MojoExecutionException; |
59 | |
import org.apache.maven.plugin.MojoFailureException; |
60 | |
import org.apache.maven.plugin.invoker.model.BuildJob; |
61 | |
import org.apache.maven.plugin.invoker.model.io.xpp3.BuildJobXpp3Writer; |
62 | |
import org.apache.maven.plugin.registry.TrackableBase; |
63 | |
import org.apache.maven.plugins.annotations.Component; |
64 | |
import org.apache.maven.plugins.annotations.Parameter; |
65 | |
import org.apache.maven.project.MavenProject; |
66 | |
import org.apache.maven.settings.RuntimeInfo; |
67 | |
import org.apache.maven.settings.Settings; |
68 | |
import org.apache.maven.settings.SettingsUtils; |
69 | |
import org.apache.maven.settings.io.xpp3.SettingsXpp3Reader; |
70 | |
import org.apache.maven.settings.io.xpp3.SettingsXpp3Writer; |
71 | |
import org.apache.maven.shared.invoker.CommandLineConfigurationException; |
72 | |
import org.apache.maven.shared.invoker.DefaultInvocationRequest; |
73 | |
import org.apache.maven.shared.invoker.InvocationRequest; |
74 | |
import org.apache.maven.shared.invoker.InvocationResult; |
75 | |
import org.apache.maven.shared.invoker.Invoker; |
76 | |
import org.apache.maven.shared.invoker.MavenCommandLineBuilder; |
77 | |
import org.apache.maven.shared.invoker.MavenInvocationException; |
78 | |
import org.apache.maven.shared.scriptinterpreter.RunErrorException; |
79 | |
import org.apache.maven.shared.scriptinterpreter.RunFailureException; |
80 | |
import org.apache.maven.shared.scriptinterpreter.ScriptRunner; |
81 | |
import org.codehaus.plexus.interpolation.InterpolationException; |
82 | |
import org.codehaus.plexus.interpolation.Interpolator; |
83 | |
import org.codehaus.plexus.interpolation.MapBasedValueSource; |
84 | |
import org.codehaus.plexus.interpolation.RegexBasedInterpolator; |
85 | |
import org.codehaus.plexus.util.DirectoryScanner; |
86 | |
import org.codehaus.plexus.util.FileUtils; |
87 | |
import org.codehaus.plexus.util.IOUtil; |
88 | |
import org.codehaus.plexus.util.InterpolationFilterReader; |
89 | |
import org.codehaus.plexus.util.ReaderFactory; |
90 | |
import org.codehaus.plexus.util.ReflectionUtils; |
91 | |
import org.codehaus.plexus.util.StringUtils; |
92 | |
import org.codehaus.plexus.util.WriterFactory; |
93 | |
import org.codehaus.plexus.util.cli.CommandLineException; |
94 | |
import org.codehaus.plexus.util.cli.CommandLineUtils; |
95 | |
import org.codehaus.plexus.util.cli.Commandline; |
96 | |
import org.codehaus.plexus.util.cli.StreamConsumer; |
97 | |
import org.codehaus.plexus.util.xml.pull.XmlPullParserException; |
98 | |
|
99 | |
|
100 | |
|
101 | |
|
102 | |
|
103 | |
|
104 | |
|
105 | 18 | public abstract class AbstractInvokerMojo |
106 | |
extends AbstractMojo |
107 | |
{ |
108 | |
|
109 | |
private static final int SELECTOR_MAVENVERSION = 1; |
110 | |
|
111 | |
private static final int SELECTOR_JREVERSION = 2; |
112 | |
|
113 | |
private static final int SELECTOR_OSFAMILY = 4; |
114 | |
|
115 | |
|
116 | |
|
117 | |
|
118 | |
|
119 | |
|
120 | |
@Parameter( property = "invoker.skip", defaultValue = "false" ) |
121 | |
private boolean skipInvocation; |
122 | |
|
123 | |
|
124 | |
|
125 | |
|
126 | |
|
127 | |
|
128 | |
|
129 | |
@Parameter( defaultValue = "false" ) |
130 | |
protected boolean suppressSummaries; |
131 | |
|
132 | |
|
133 | |
|
134 | |
|
135 | |
@Parameter( property = "invoker.streamLogs", defaultValue = "false" ) |
136 | |
private boolean streamLogs; |
137 | |
|
138 | |
|
139 | |
|
140 | |
|
141 | |
|
142 | |
|
143 | |
@Parameter( property = "invoker.localRepositoryPath", defaultValue = "${settings.localRepository}" ) |
144 | |
private File localRepositoryPath; |
145 | |
|
146 | |
|
147 | |
|
148 | |
|
149 | |
@Parameter( property = "invoker.projectsDirectory", defaultValue = "${basedir}/src/it/" ) |
150 | |
private File projectsDirectory; |
151 | |
|
152 | |
|
153 | |
|
154 | |
|
155 | |
|
156 | |
|
157 | |
|
158 | |
|
159 | |
|
160 | |
@Parameter( property = "invoker.reportsDirectory", defaultValue = "${project.build.directory}/invoker-reports" ) |
161 | |
private File reportsDirectory; |
162 | |
|
163 | |
|
164 | |
|
165 | |
|
166 | |
|
167 | |
|
168 | |
@Parameter( property = "invoker.disableReports", defaultValue = "false" ) |
169 | |
private boolean disableReports; |
170 | |
|
171 | |
|
172 | |
|
173 | |
|
174 | |
|
175 | |
|
176 | |
|
177 | |
|
178 | |
@Parameter |
179 | |
private File cloneProjectsTo; |
180 | |
|
181 | |
|
182 | |
|
183 | |
|
184 | |
|
185 | |
|
186 | |
|
187 | |
|
188 | |
|
189 | |
@Parameter( defaultValue = "false" ) |
190 | |
private boolean cloneAllFiles; |
191 | |
|
192 | |
|
193 | |
|
194 | |
|
195 | |
|
196 | |
|
197 | |
@Parameter( defaultValue = "false" ) |
198 | |
private boolean cloneClean; |
199 | |
|
200 | |
|
201 | |
|
202 | |
|
203 | |
@Parameter( property = "invoker.pom" ) |
204 | |
private File pom; |
205 | |
|
206 | |
|
207 | |
|
208 | |
|
209 | |
|
210 | |
|
211 | |
|
212 | |
|
213 | |
|
214 | |
|
215 | |
|
216 | 18 | @Parameter |
217 | |
private List<String> pomIncludes = Collections.singletonList( "*/pom.xml" ); |
218 | |
|
219 | |
|
220 | |
|
221 | |
|
222 | |
|
223 | |
|
224 | 18 | @Parameter |
225 | |
private List<String> pomExcludes = Collections.emptyList(); |
226 | |
|
227 | |
|
228 | |
|
229 | |
|
230 | |
|
231 | |
|
232 | |
|
233 | |
|
234 | |
|
235 | |
|
236 | 18 | @Parameter |
237 | |
private List<String> setupIncludes = Collections.singletonList( "setup*/pom.xml" ); |
238 | |
|
239 | |
|
240 | |
|
241 | |
|
242 | 18 | @Parameter |
243 | |
private List<String> goals = Collections.singletonList( "package" ); |
244 | |
|
245 | |
|
246 | |
|
247 | |
|
248 | |
|
249 | |
|
250 | |
|
251 | |
@Parameter( property = "invoker.goalsFile", defaultValue = "goals.txt" ) |
252 | |
private String goalsFile; |
253 | |
|
254 | |
|
255 | |
|
256 | |
@Component |
257 | |
private Invoker invoker; |
258 | |
|
259 | |
|
260 | |
|
261 | |
|
262 | |
|
263 | |
|
264 | |
|
265 | |
|
266 | |
|
267 | |
|
268 | |
|
269 | |
|
270 | |
|
271 | |
@Parameter( property = "invoker.selectorScript", defaultValue = "selector" ) |
272 | |
private String selectorScript; |
273 | |
|
274 | |
|
275 | |
|
276 | |
|
277 | |
|
278 | |
|
279 | |
|
280 | |
|
281 | |
|
282 | |
@Parameter( property = "invoker.preBuildHookScript", defaultValue = "prebuild" ) |
283 | |
private String preBuildHookScript; |
284 | |
|
285 | |
|
286 | |
|
287 | |
|
288 | |
|
289 | |
|
290 | |
|
291 | |
|
292 | |
@Parameter( property = "invoker.postBuildHookScript", defaultValue = "postbuild" ) |
293 | |
private String postBuildHookScript; |
294 | |
|
295 | |
|
296 | |
|
297 | |
|
298 | |
@Parameter( property = "invoker.testPropertiesFile", defaultValue = "test.properties" ) |
299 | |
private String testPropertiesFile; |
300 | |
|
301 | |
|
302 | |
|
303 | |
|
304 | |
|
305 | |
|
306 | |
@Parameter |
307 | |
private Properties testProperties; |
308 | |
|
309 | |
|
310 | |
|
311 | |
|
312 | |
|
313 | |
|
314 | |
@Parameter |
315 | |
private Map<String, String> properties; |
316 | |
|
317 | |
|
318 | |
|
319 | |
|
320 | |
@Parameter( property = "invoker.showErrors", defaultValue = "false" ) |
321 | |
private boolean showErrors; |
322 | |
|
323 | |
|
324 | |
|
325 | |
|
326 | |
@Parameter( property = "invoker.debug", defaultValue = "false" ) |
327 | |
private boolean debug; |
328 | |
|
329 | |
|
330 | |
|
331 | |
|
332 | |
@Parameter( property = "invoker.noLog", defaultValue = "false" ) |
333 | |
private boolean noLog; |
334 | |
|
335 | |
|
336 | |
|
337 | |
|
338 | |
|
339 | |
|
340 | |
@Parameter |
341 | |
private List<String> profiles; |
342 | |
|
343 | |
|
344 | |
|
345 | |
|
346 | |
|
347 | |
|
348 | |
|
349 | |
@Parameter |
350 | |
private Properties interpolationsProperties; |
351 | |
|
352 | |
|
353 | |
|
354 | |
|
355 | |
|
356 | |
|
357 | |
@Parameter |
358 | |
private Map<String, String> filterProperties; |
359 | |
|
360 | |
|
361 | |
|
362 | |
|
363 | |
|
364 | |
|
365 | |
@Component |
366 | |
private MavenProject project; |
367 | |
|
368 | |
@Component |
369 | |
private MojoExecution mojoExecution; |
370 | |
|
371 | |
|
372 | |
|
373 | |
|
374 | |
|
375 | |
|
376 | |
|
377 | |
|
378 | |
|
379 | |
|
380 | |
|
381 | |
|
382 | |
|
383 | |
@Parameter( property = "invoker.test" ) |
384 | |
private String invokerTest; |
385 | |
|
386 | |
|
387 | |
|
388 | |
|
389 | |
|
390 | |
|
391 | |
|
392 | |
|
393 | |
|
394 | |
@Parameter( property = "invoker.profilesFile", defaultValue = "profiles.txt" ) |
395 | |
private String profilesFile; |
396 | |
|
397 | |
|
398 | |
|
399 | |
|
400 | |
|
401 | |
|
402 | |
|
403 | |
|
404 | |
@Parameter( property = "invoker.settingsFile" ) |
405 | |
private File settingsFile; |
406 | |
|
407 | |
|
408 | |
|
409 | |
|
410 | |
|
411 | |
|
412 | |
|
413 | |
@Parameter( property = "invoker.mavenOpts" ) |
414 | |
private String mavenOpts; |
415 | |
|
416 | |
|
417 | |
|
418 | |
|
419 | |
|
420 | |
|
421 | |
|
422 | |
@Parameter( property = "invoker.mavenHome" ) |
423 | |
private File mavenHome; |
424 | |
|
425 | |
|
426 | |
|
427 | |
|
428 | |
|
429 | |
|
430 | |
|
431 | |
@Parameter( property = "invoker.mavenExecutable" ) |
432 | |
private String mavenExecutable; |
433 | |
|
434 | |
|
435 | |
|
436 | |
|
437 | |
|
438 | |
|
439 | |
|
440 | |
@Parameter( property = "invoker.javaHome" ) |
441 | |
private File javaHome; |
442 | |
|
443 | |
|
444 | |
|
445 | |
|
446 | |
|
447 | |
|
448 | |
@Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" ) |
449 | |
private String encoding; |
450 | |
|
451 | |
|
452 | |
|
453 | |
|
454 | |
|
455 | |
|
456 | |
@Component |
457 | |
private Settings settings; |
458 | |
|
459 | |
|
460 | |
|
461 | |
|
462 | |
|
463 | |
|
464 | |
|
465 | |
|
466 | |
|
467 | |
|
468 | |
@Parameter( property = "invoker.addTestClassPath", defaultValue = "false" ) |
469 | |
private boolean addTestClassPath; |
470 | |
|
471 | |
|
472 | |
|
473 | |
|
474 | |
@Parameter( defaultValue = "${project.testClasspathElements}", readonly = true ) |
475 | |
private List<String> testClassPath; |
476 | |
|
477 | |
|
478 | |
|
479 | |
|
480 | |
|
481 | |
|
482 | |
|
483 | |
|
484 | |
|
485 | |
|
486 | |
|
487 | |
|
488 | |
|
489 | |
|
490 | |
|
491 | |
|
492 | |
|
493 | |
|
494 | |
|
495 | |
|
496 | |
|
497 | |
|
498 | |
|
499 | |
|
500 | |
|
501 | |
|
502 | |
|
503 | |
|
504 | |
|
505 | |
|
506 | |
|
507 | |
|
508 | |
|
509 | |
|
510 | |
|
511 | |
|
512 | |
|
513 | |
|
514 | |
|
515 | |
|
516 | |
|
517 | |
|
518 | |
|
519 | |
|
520 | |
|
521 | |
|
522 | |
|
523 | |
|
524 | |
|
525 | |
|
526 | |
|
527 | |
|
528 | |
|
529 | |
|
530 | |
|
531 | |
|
532 | |
|
533 | |
|
534 | |
|
535 | |
|
536 | |
|
537 | |
|
538 | |
|
539 | |
|
540 | |
|
541 | |
|
542 | |
|
543 | |
|
544 | |
|
545 | |
|
546 | |
|
547 | |
|
548 | |
@Parameter( property = "invoker.invokerPropertiesFile", defaultValue = "invoker.properties" ) |
549 | |
private String invokerPropertiesFile; |
550 | |
|
551 | |
|
552 | |
|
553 | |
|
554 | |
|
555 | |
|
556 | |
@Parameter( property = "invoker.showVersion", defaultValue = "false" ) |
557 | |
private boolean showVersion; |
558 | |
|
559 | |
|
560 | |
|
561 | |
|
562 | |
|
563 | |
|
564 | |
|
565 | |
@Parameter( property = "invoker.parallelThreads", defaultValue = "1" ) |
566 | |
private int parallelThreads; |
567 | |
|
568 | |
|
569 | |
|
570 | |
|
571 | |
@Parameter( property = "plugin.artifacts", required = true, readonly = true ) |
572 | |
private List<Artifact> pluginArtifacts; |
573 | |
|
574 | |
|
575 | |
|
576 | |
|
577 | |
|
578 | |
|
579 | |
|
580 | |
@Parameter( property = "invoker.mergeUserSettings", defaultValue = "false" ) |
581 | |
private boolean mergeUserSettings; |
582 | |
|
583 | |
|
584 | |
|
585 | |
|
586 | |
|
587 | |
@Parameter |
588 | |
private Map<String, String> environmentVariables; |
589 | |
|
590 | |
|
591 | |
|
592 | |
private ScriptRunner scriptRunner; |
593 | |
|
594 | |
|
595 | |
|
596 | |
|
597 | |
|
598 | |
|
599 | 18 | private String filteredPomPrefix = "interpolated-"; |
600 | |
|
601 | |
|
602 | |
|
603 | |
|
604 | 18 | private final DecimalFormat secFormat = new DecimalFormat( "(0.0 s)", new DecimalFormatSymbols( Locale.ENGLISH ) ); |
605 | |
|
606 | |
|
607 | |
|
608 | |
|
609 | |
private String actualMavenVersion; |
610 | |
|
611 | |
|
612 | |
|
613 | |
|
614 | |
private String actualJreVersion; |
615 | |
|
616 | |
|
617 | |
private void setActualJreVersion( String actualJreVersion ) |
618 | |
{ |
619 | 0 | this.actualJreVersion = actualJreVersion; |
620 | 0 | } |
621 | |
|
622 | |
|
623 | |
|
624 | |
|
625 | |
|
626 | |
|
627 | |
|
628 | |
|
629 | |
|
630 | |
public void execute() |
631 | |
throws MojoExecutionException, MojoFailureException |
632 | |
{ |
633 | 0 | if ( skipInvocation ) |
634 | |
{ |
635 | 0 | getLog().info( "Skipping invocation per configuration." |
636 | |
+ " If this is incorrect, ensure the skipInvocation parameter is not set to true." ); |
637 | 0 | return; |
638 | |
} |
639 | |
|
640 | |
|
641 | 0 | if ( !disableReports && !reportsDirectory.exists() ) |
642 | |
{ |
643 | 0 | reportsDirectory.mkdirs(); |
644 | |
} |
645 | |
|
646 | |
BuildJob[] buildJobs; |
647 | 0 | if ( pom != null ) |
648 | |
{ |
649 | |
try |
650 | |
{ |
651 | 0 | projectsDirectory = pom.getCanonicalFile().getParentFile(); |
652 | |
} |
653 | 0 | catch ( IOException e ) |
654 | |
{ |
655 | 0 | throw new MojoExecutionException( |
656 | |
"Failed to discover projectsDirectory from pom File parameter." + " Reason: " + e.getMessage(), e ); |
657 | 0 | } |
658 | |
|
659 | 0 | buildJobs = new BuildJob[]{ new BuildJob( pom.getName(), BuildJob.Type.NORMAL ) }; |
660 | |
} |
661 | |
else |
662 | |
{ |
663 | |
try |
664 | |
{ |
665 | 0 | buildJobs = getBuildJobs(); |
666 | |
} |
667 | 0 | catch ( final IOException e ) |
668 | |
{ |
669 | 0 | throw new MojoExecutionException( |
670 | |
"Error retrieving POM list from includes, excludes, " + "and projects directory. Reason: " |
671 | |
+ e.getMessage(), e ); |
672 | 0 | } |
673 | |
} |
674 | |
|
675 | 0 | if ( ( buildJobs == null ) || ( buildJobs.length < 1 ) ) |
676 | |
{ |
677 | 0 | getLog().info( "No projects were selected for execution." ); |
678 | 0 | return; |
679 | |
} |
680 | |
|
681 | 0 | if ( StringUtils.isEmpty( encoding ) ) |
682 | |
{ |
683 | 0 | getLog().warn( "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING |
684 | |
+ ", i.e. build is platform dependent!" ); |
685 | |
} |
686 | |
|
687 | |
final List<String> scriptClassPath; |
688 | 0 | if ( addTestClassPath ) |
689 | |
{ |
690 | 0 | scriptClassPath = new ArrayList<String>( testClassPath ); |
691 | 0 | for ( Artifact pluginArtifact : pluginArtifacts ) |
692 | |
{ |
693 | 0 | scriptClassPath.remove( pluginArtifact.getFile().getAbsolutePath() ); |
694 | |
} |
695 | |
} |
696 | |
else |
697 | |
{ |
698 | 0 | scriptClassPath = null; |
699 | |
} |
700 | 0 | scriptRunner = new ScriptRunner( getLog() ); |
701 | 0 | scriptRunner.setScriptEncoding( encoding ); |
702 | 0 | scriptRunner.setGlobalVariable( "localRepositoryPath", localRepositoryPath ); |
703 | 0 | scriptRunner.setClassPath( scriptClassPath ); |
704 | |
|
705 | 0 | Collection<String> collectedProjects = new LinkedHashSet<String>(); |
706 | 0 | for ( BuildJob buildJob : buildJobs ) |
707 | |
{ |
708 | 0 | collectProjects( projectsDirectory, buildJob.getProject(), collectedProjects, true ); |
709 | |
} |
710 | |
|
711 | 0 | File projectsDir = projectsDirectory; |
712 | |
|
713 | 0 | if ( cloneProjectsTo != null ) |
714 | |
{ |
715 | 0 | cloneProjects( collectedProjects ); |
716 | 0 | projectsDir = cloneProjectsTo; |
717 | |
} |
718 | |
else |
719 | |
{ |
720 | 0 | getLog().warn( "Filtering of parent/child POMs is not supported without cloning the projects" ); |
721 | |
} |
722 | |
|
723 | 0 | runBuilds( projectsDir, buildJobs ); |
724 | |
|
725 | 0 | processResults( new InvokerSession( buildJobs ) ); |
726 | 0 | } |
727 | |
|
728 | |
|
729 | |
|
730 | |
|
731 | |
|
732 | |
|
733 | |
|
734 | |
|
735 | |
abstract void processResults( InvokerSession invokerSession ) |
736 | |
throws MojoFailureException; |
737 | |
|
738 | |
|
739 | |
|
740 | |
|
741 | |
|
742 | |
|
743 | |
|
744 | |
|
745 | |
private Reader newReader( File file ) |
746 | |
throws IOException |
747 | |
{ |
748 | 8 | if ( StringUtils.isNotEmpty( encoding ) ) |
749 | |
{ |
750 | 0 | return ReaderFactory.newReader( file, encoding ); |
751 | |
} |
752 | |
else |
753 | |
{ |
754 | 8 | return ReaderFactory.newPlatformReader( file ); |
755 | |
} |
756 | |
} |
757 | |
|
758 | |
|
759 | |
|
760 | |
|
761 | |
|
762 | |
|
763 | |
|
764 | |
|
765 | |
|
766 | |
|
767 | |
|
768 | |
|
769 | |
|
770 | |
|
771 | |
|
772 | |
|
773 | |
private void collectProjects( File projectsDir, String projectPath, Collection<String> projectPaths, |
774 | |
boolean included ) |
775 | |
throws MojoExecutionException |
776 | |
{ |
777 | 0 | projectPath = projectPath.replace( '\\', '/' ); |
778 | 0 | File pomFile = new File( projectsDir, projectPath ); |
779 | 0 | if ( pomFile.isDirectory() ) |
780 | |
{ |
781 | 0 | pomFile = new File( pomFile, "pom.xml" ); |
782 | 0 | if ( !pomFile.exists() ) |
783 | |
{ |
784 | 0 | if ( included ) |
785 | |
{ |
786 | 0 | projectPaths.add( projectPath ); |
787 | |
} |
788 | 0 | return; |
789 | |
} |
790 | 0 | if ( !projectPath.endsWith( "/" ) ) |
791 | |
{ |
792 | 0 | projectPath += '/'; |
793 | |
} |
794 | 0 | projectPath += "pom.xml"; |
795 | |
} |
796 | 0 | else if ( !pomFile.isFile() ) |
797 | |
{ |
798 | 0 | return; |
799 | |
} |
800 | 0 | if ( !projectPaths.add( projectPath ) ) |
801 | |
{ |
802 | 0 | return; |
803 | |
} |
804 | 0 | getLog().debug( "Collecting parent/child projects of " + projectPath ); |
805 | |
|
806 | 0 | Model model = PomUtils.loadPom( pomFile ); |
807 | |
|
808 | |
try |
809 | |
{ |
810 | 0 | String projectsRoot = projectsDir.getCanonicalPath(); |
811 | 0 | String projectDir = pomFile.getParent(); |
812 | |
|
813 | 0 | String parentPath = "../pom.xml"; |
814 | 0 | if ( model.getParent() != null && StringUtils.isNotEmpty( model.getParent().getRelativePath() ) ) |
815 | |
{ |
816 | 0 | parentPath = model.getParent().getRelativePath(); |
817 | |
} |
818 | 0 | String parent = relativizePath( new File( projectDir, parentPath ), projectsRoot ); |
819 | 0 | if ( parent != null ) |
820 | |
{ |
821 | 0 | collectProjects( projectsDir, parent, projectPaths, false ); |
822 | |
} |
823 | |
|
824 | 0 | Collection<String> modulePaths = new LinkedHashSet<String>(); |
825 | |
|
826 | 0 | modulePaths.addAll( (List<String>) model.getModules() ); |
827 | |
|
828 | 0 | for ( Profile profile : (List<Profile>) model.getProfiles() ) |
829 | |
{ |
830 | 0 | modulePaths.addAll( (List<String>) profile.getModules() ); |
831 | |
} |
832 | |
|
833 | 0 | for ( String modulePath : modulePaths ) |
834 | |
{ |
835 | 0 | String module = relativizePath( new File( projectDir, modulePath ), projectsRoot ); |
836 | 0 | if ( module != null ) |
837 | |
{ |
838 | 0 | collectProjects( projectsDir, module, projectPaths, false ); |
839 | |
} |
840 | 0 | } |
841 | |
} |
842 | 0 | catch ( IOException e ) |
843 | |
{ |
844 | 0 | throw new MojoExecutionException( "Failed to analyze POM: " + pomFile, e ); |
845 | 0 | } |
846 | 0 | } |
847 | |
|
848 | |
|
849 | |
|
850 | |
|
851 | |
|
852 | |
|
853 | |
|
854 | |
|
855 | |
|
856 | |
|
857 | |
private void cloneProjects( Collection<String> projectPaths ) |
858 | |
throws MojoExecutionException |
859 | |
{ |
860 | 0 | if ( !cloneProjectsTo.mkdirs() && cloneClean ) |
861 | |
{ |
862 | |
try |
863 | |
{ |
864 | 0 | FileUtils.cleanDirectory( cloneProjectsTo ); |
865 | |
} |
866 | 0 | catch ( IOException e ) |
867 | |
{ |
868 | 0 | throw new MojoExecutionException( |
869 | |
"Could not clean the cloneProjectsTo directory. Reason: " + e.getMessage(), e ); |
870 | 0 | } |
871 | |
} |
872 | |
|
873 | |
|
874 | 0 | Collection<String> dirs = new LinkedHashSet<String>(); |
875 | 0 | for ( String projectPath : projectPaths ) |
876 | |
{ |
877 | 0 | if ( !new File( projectsDirectory, projectPath ).isDirectory() ) |
878 | |
{ |
879 | 0 | projectPath = getParentPath( projectPath ); |
880 | |
} |
881 | 0 | dirs.add( projectPath ); |
882 | |
} |
883 | |
|
884 | 0 | boolean filter = false; |
885 | |
|
886 | |
|
887 | |
try |
888 | |
{ |
889 | 0 | filter = !cloneProjectsTo.getCanonicalFile().equals( projectsDirectory.getCanonicalFile() ); |
890 | |
|
891 | 0 | List<String> clonedSubpaths = new ArrayList<String>(); |
892 | |
|
893 | 0 | for ( String subpath : dirs ) |
894 | |
{ |
895 | |
|
896 | 0 | if ( !".".equals( subpath ) && dirs.contains( getParentPath( subpath ) ) ) |
897 | |
{ |
898 | 0 | continue; |
899 | |
} |
900 | |
|
901 | |
|
902 | 0 | if ( !alreadyCloned( subpath, clonedSubpaths ) ) |
903 | |
{ |
904 | |
|
905 | 0 | if ( ".".equals( subpath ) ) |
906 | |
{ |
907 | 0 | String cloneSubdir = relativizePath( cloneProjectsTo, projectsDirectory.getCanonicalPath() ); |
908 | |
|
909 | |
|
910 | 0 | if ( cloneSubdir != null ) |
911 | |
{ |
912 | 0 | File temp = File.createTempFile( "pre-invocation-clone.", "" ); |
913 | 0 | temp.delete(); |
914 | 0 | temp.mkdirs(); |
915 | |
|
916 | 0 | copyDirectoryStructure( projectsDirectory, temp ); |
917 | |
|
918 | 0 | FileUtils.deleteDirectory( new File( temp, cloneSubdir ) ); |
919 | |
|
920 | 0 | copyDirectoryStructure( temp, cloneProjectsTo ); |
921 | 0 | } |
922 | |
else |
923 | |
{ |
924 | 0 | copyDirectoryStructure( projectsDirectory, cloneProjectsTo ); |
925 | |
} |
926 | 0 | } |
927 | |
else |
928 | |
{ |
929 | 0 | File srcDir = new File( projectsDirectory, subpath ); |
930 | 0 | File dstDir = new File( cloneProjectsTo, subpath ); |
931 | 0 | copyDirectoryStructure( srcDir, dstDir ); |
932 | |
} |
933 | |
|
934 | 0 | clonedSubpaths.add( subpath ); |
935 | |
} |
936 | |
} |
937 | |
} |
938 | 0 | catch ( IOException e ) |
939 | |
{ |
940 | 0 | throw new MojoExecutionException( |
941 | |
"Failed to clone projects from: " + projectsDirectory + " to: " + cloneProjectsTo + ". Reason: " |
942 | |
+ e.getMessage(), e ); |
943 | 0 | } |
944 | |
|
945 | |
|
946 | 0 | if ( filter ) |
947 | |
{ |
948 | 0 | for ( String projectPath : projectPaths ) |
949 | |
{ |
950 | 0 | File pomFile = new File( cloneProjectsTo, projectPath ); |
951 | 0 | if ( pomFile.isFile() ) |
952 | |
{ |
953 | 0 | buildInterpolatedFile( pomFile, pomFile ); |
954 | |
} |
955 | 0 | } |
956 | 0 | filteredPomPrefix = null; |
957 | |
} |
958 | 0 | } |
959 | |
|
960 | |
|
961 | |
|
962 | |
|
963 | |
|
964 | |
|
965 | |
|
966 | |
private String getParentPath( String path ) |
967 | |
{ |
968 | 0 | int lastSep = Math.max( path.lastIndexOf( '/' ), path.lastIndexOf( '\\' ) ); |
969 | 0 | return ( lastSep < 0 ) ? "." : path.substring( 0, lastSep ); |
970 | |
} |
971 | |
|
972 | |
|
973 | |
|
974 | |
|
975 | |
|
976 | |
|
977 | |
|
978 | |
|
979 | |
private void copyDirectoryStructure( File sourceDir, File destDir ) |
980 | |
throws IOException |
981 | |
{ |
982 | 0 | DirectoryScanner scanner = new DirectoryScanner(); |
983 | 0 | scanner.setBasedir( sourceDir ); |
984 | 0 | if ( !cloneAllFiles ) |
985 | |
{ |
986 | 0 | scanner.addDefaultExcludes(); |
987 | |
} |
988 | 0 | scanner.scan(); |
989 | |
|
990 | |
|
991 | |
|
992 | |
|
993 | 0 | destDir.mkdirs(); |
994 | 0 | for ( String includedDir : scanner.getIncludedDirectories() ) |
995 | |
{ |
996 | 0 | File clonedDir = new File( destDir, includedDir ); |
997 | 0 | clonedDir.mkdirs(); |
998 | |
} |
999 | |
|
1000 | 0 | for ( String includedFile : scanner.getIncludedFiles() ) |
1001 | |
{ |
1002 | 0 | File sourceFile = new File( sourceDir, includedFile ); |
1003 | 0 | File destFile = new File( destDir, includedFile ); |
1004 | 0 | FileUtils.copyFile( sourceFile, destFile ); |
1005 | |
} |
1006 | 0 | } |
1007 | |
|
1008 | |
|
1009 | |
|
1010 | |
|
1011 | |
|
1012 | |
|
1013 | |
|
1014 | |
|
1015 | |
|
1016 | |
|
1017 | |
static boolean alreadyCloned( String subpath, List<String> clonedSubpaths ) |
1018 | |
{ |
1019 | 8 | for ( String path : clonedSubpaths ) |
1020 | |
{ |
1021 | 6 | if ( ".".equals( path ) || subpath.equals( path ) || subpath.startsWith( path + File.separator ) ) |
1022 | |
{ |
1023 | 4 | return true; |
1024 | |
} |
1025 | |
} |
1026 | |
|
1027 | 4 | return false; |
1028 | |
} |
1029 | |
|
1030 | |
|
1031 | |
|
1032 | |
|
1033 | |
|
1034 | |
|
1035 | |
|
1036 | |
|
1037 | |
|
1038 | |
private void runBuilds( final File projectsDir, BuildJob[] buildJobs ) |
1039 | |
throws MojoExecutionException |
1040 | |
{ |
1041 | 0 | if ( !localRepositoryPath.exists() ) |
1042 | |
{ |
1043 | 0 | localRepositoryPath.mkdirs(); |
1044 | |
} |
1045 | |
|
1046 | |
|
1047 | |
|
1048 | |
|
1049 | |
|
1050 | 0 | File interpolatedSettingsFile = null; |
1051 | 0 | if ( settingsFile != null ) |
1052 | |
{ |
1053 | 0 | if ( cloneProjectsTo != null ) |
1054 | |
{ |
1055 | 0 | interpolatedSettingsFile = new File( cloneProjectsTo, "interpolated-" + settingsFile.getName() ); |
1056 | |
} |
1057 | |
else |
1058 | |
{ |
1059 | 0 | interpolatedSettingsFile = |
1060 | |
new File( settingsFile.getParentFile(), "interpolated-" + settingsFile.getName() ); |
1061 | |
} |
1062 | 0 | buildInterpolatedFile( settingsFile, interpolatedSettingsFile ); |
1063 | |
} |
1064 | |
|
1065 | |
|
1066 | |
|
1067 | |
|
1068 | |
|
1069 | 0 | SettingsXpp3Writer settingsWriter = new SettingsXpp3Writer(); |
1070 | |
|
1071 | |
File mergedSettingsFile; |
1072 | 0 | Settings mergedSettings = this.settings; |
1073 | 0 | if ( mergeUserSettings ) |
1074 | |
{ |
1075 | 0 | if ( interpolatedSettingsFile != null ) |
1076 | |
{ |
1077 | |
|
1078 | 0 | Reader reader = null; |
1079 | |
try |
1080 | |
{ |
1081 | 0 | reader = new XmlStreamReader( interpolatedSettingsFile ); |
1082 | 0 | SettingsXpp3Reader settingsReader = new SettingsXpp3Reader(); |
1083 | 0 | Settings dominantSettings = settingsReader.read( reader ); |
1084 | |
|
1085 | |
|
1086 | |
|
1087 | 0 | if ( dominantSettings.getRuntimeInfo() == null ) |
1088 | |
{ |
1089 | 0 | RuntimeInfo rtInfo = new RuntimeInfo( dominantSettings ); |
1090 | 0 | rtInfo.setFile( interpolatedSettingsFile ); |
1091 | 0 | dominantSettings.setRuntimeInfo( rtInfo ); |
1092 | |
} |
1093 | |
|
1094 | 0 | Settings recessiveSettings = cloneSettings(); |
1095 | |
|
1096 | 0 | SettingsUtils.merge( dominantSettings, recessiveSettings, TrackableBase.USER_LEVEL ); |
1097 | |
|
1098 | 0 | mergedSettings = dominantSettings; |
1099 | 0 | getLog().debug( "Merged specified settings file with settings of invoking process" ); |
1100 | |
} |
1101 | 0 | catch ( XmlPullParserException e ) |
1102 | |
{ |
1103 | 0 | throw new MojoExecutionException( "Could not read specified settings file", e ); |
1104 | |
} |
1105 | 0 | catch ( IOException e ) |
1106 | |
{ |
1107 | 0 | throw new MojoExecutionException( "Could not read specified settings file", e ); |
1108 | |
} |
1109 | |
finally |
1110 | |
{ |
1111 | 0 | IOUtil.close( reader ); |
1112 | 0 | } |
1113 | |
} |
1114 | |
} |
1115 | 0 | if ( this.settingsFile != null && !mergeUserSettings ) |
1116 | |
{ |
1117 | 0 | mergedSettingsFile = interpolatedSettingsFile; |
1118 | |
} |
1119 | |
else |
1120 | |
{ |
1121 | |
try |
1122 | |
{ |
1123 | 0 | mergedSettingsFile = File.createTempFile( "invoker-settings", ".xml" ); |
1124 | |
|
1125 | 0 | FileWriter fileWriter = null; |
1126 | |
try |
1127 | |
{ |
1128 | 0 | fileWriter = new FileWriter( mergedSettingsFile ); |
1129 | 0 | settingsWriter.write( fileWriter, mergedSettings ); |
1130 | |
} |
1131 | |
finally |
1132 | |
{ |
1133 | 0 | IOUtil.close( fileWriter ); |
1134 | 0 | } |
1135 | |
|
1136 | 0 | if ( getLog().isDebugEnabled() ) |
1137 | |
{ |
1138 | 0 | getLog().debug( |
1139 | |
"Created temporary file for invoker settings.xml: " + mergedSettingsFile.getAbsolutePath() ); |
1140 | |
} |
1141 | |
|
1142 | |
} |
1143 | 0 | catch ( IOException e ) |
1144 | |
{ |
1145 | 0 | throw new MojoExecutionException( "Could not create temporary file for invoker settings.xml", e ); |
1146 | 0 | } |
1147 | |
} |
1148 | 0 | final File finalSettingsFile = mergedSettingsFile; |
1149 | |
|
1150 | 0 | if ( mavenHome != null ) |
1151 | |
{ |
1152 | 0 | actualMavenVersion = SelectorUtils.getMavenVersion( mavenHome ); |
1153 | |
} |
1154 | |
else |
1155 | |
{ |
1156 | 0 | actualMavenVersion = SelectorUtils.getMavenVersion(); |
1157 | |
} |
1158 | |
|
1159 | 0 | if ( javaHome != null ) |
1160 | |
{ |
1161 | 0 | resolveExternalJreVersion(); |
1162 | |
} |
1163 | |
else |
1164 | |
{ |
1165 | 0 | actualJreVersion = SelectorUtils.getJreVersion(); |
1166 | |
} |
1167 | |
|
1168 | |
try |
1169 | |
{ |
1170 | 0 | if ( isParallelRun() ) |
1171 | |
{ |
1172 | 0 | getLog().info( "use parallelThreads " + parallelThreads ); |
1173 | |
|
1174 | 0 | ExecutorService executorService = Executors.newFixedThreadPool( parallelThreads ); |
1175 | 0 | for ( final BuildJob job : buildJobs ) |
1176 | |
{ |
1177 | 0 | executorService.execute( new Runnable() |
1178 | 0 | { |
1179 | |
|
1180 | |
public void run() |
1181 | |
{ |
1182 | |
try |
1183 | |
{ |
1184 | 0 | runBuild( projectsDir, job, finalSettingsFile ); |
1185 | |
} |
1186 | 0 | catch ( MojoExecutionException e ) |
1187 | |
{ |
1188 | 0 | throw new RuntimeException( e.getMessage(), e ); |
1189 | 0 | } |
1190 | 0 | } |
1191 | |
} ); |
1192 | |
} |
1193 | |
|
1194 | |
try |
1195 | |
{ |
1196 | 0 | executorService.shutdown(); |
1197 | |
|
1198 | 0 | executorService.awaitTermination( Long.MAX_VALUE, TimeUnit.MILLISECONDS ); |
1199 | |
} |
1200 | 0 | catch ( InterruptedException e ) |
1201 | |
{ |
1202 | 0 | throw new MojoExecutionException( e.getMessage(), e ); |
1203 | 0 | } |
1204 | |
|
1205 | 0 | } |
1206 | |
else |
1207 | |
{ |
1208 | 0 | for ( BuildJob job : buildJobs ) |
1209 | |
{ |
1210 | 0 | runBuild( projectsDir, job, finalSettingsFile ); |
1211 | |
} |
1212 | |
} |
1213 | |
} |
1214 | |
finally |
1215 | |
{ |
1216 | 0 | if ( interpolatedSettingsFile != null && cloneProjectsTo == null ) |
1217 | |
{ |
1218 | 0 | interpolatedSettingsFile.delete(); |
1219 | |
} |
1220 | 0 | if ( mergedSettingsFile != null && mergedSettingsFile.exists() ) |
1221 | |
{ |
1222 | 0 | mergedSettingsFile.delete(); |
1223 | |
} |
1224 | |
|
1225 | |
} |
1226 | 0 | } |
1227 | |
|
1228 | |
private Settings cloneSettings() |
1229 | |
{ |
1230 | 0 | Settings recessiveSettings = SettingsUtils.copySettings( this.settings ); |
1231 | |
|
1232 | |
|
1233 | 0 | resetSourceLevelSet( recessiveSettings ); |
1234 | 0 | for ( org.apache.maven.settings.Mirror mirror : recessiveSettings.getMirrors() ) |
1235 | |
{ |
1236 | 0 | resetSourceLevelSet( mirror ); |
1237 | |
} |
1238 | 0 | for ( org.apache.maven.settings.Server server : recessiveSettings.getServers() ) |
1239 | |
{ |
1240 | 0 | resetSourceLevelSet( server ); |
1241 | |
} |
1242 | 0 | for ( org.apache.maven.settings.Proxy proxy : recessiveSettings.getProxies() ) |
1243 | |
{ |
1244 | 0 | resetSourceLevelSet( proxy ); |
1245 | |
} |
1246 | 0 | for ( org.apache.maven.settings.Profile profile : recessiveSettings.getProfiles() ) |
1247 | |
{ |
1248 | 0 | resetSourceLevelSet( profile ); |
1249 | |
} |
1250 | |
|
1251 | 0 | return recessiveSettings; |
1252 | |
} |
1253 | |
|
1254 | |
private void resetSourceLevelSet( org.apache.maven.settings.TrackableBase trackable ) |
1255 | |
{ |
1256 | |
try |
1257 | |
{ |
1258 | 0 | ReflectionUtils.setVariableValueInObject( trackable, "sourceLevelSet", Boolean.FALSE ); |
1259 | 0 | getLog().debug( "sourceLevelSet: " + ReflectionUtils.getValueIncludingSuperclasses( "sourceLevelSet", trackable ) ); |
1260 | |
} |
1261 | 0 | catch ( IllegalAccessException e ) |
1262 | |
{ |
1263 | |
|
1264 | 0 | } |
1265 | 0 | } |
1266 | |
|
1267 | |
private void resolveExternalJreVersion() |
1268 | |
{ |
1269 | 0 | Artifact pluginArtifact = mojoExecution.getMojoDescriptor().getPluginDescriptor().getPluginArtifact(); |
1270 | 0 | pluginArtifact.getFile(); |
1271 | |
|
1272 | 0 | Commandline commandLine = new Commandline(); |
1273 | 0 | commandLine.setExecutable( new File( javaHome, "bin/java" ).getAbsolutePath() ); |
1274 | 0 | commandLine.createArg().setValue( "-cp" ); |
1275 | 0 | commandLine.createArg().setFile( pluginArtifact.getFile() ); |
1276 | 0 | commandLine.createArg().setValue( SystemPropertyPrinter.class.getName() ); |
1277 | 0 | commandLine.createArg().setValue( "java.version" ); |
1278 | |
|
1279 | 0 | StreamConsumer consumer = new StreamConsumer() |
1280 | 0 | { |
1281 | |
public void consumeLine( String line ) |
1282 | |
{ |
1283 | 0 | setActualJreVersion( line ); |
1284 | 0 | } |
1285 | |
}; |
1286 | |
try |
1287 | |
{ |
1288 | 0 | CommandLineUtils.executeCommandLine( commandLine, consumer, null ); |
1289 | |
} |
1290 | 0 | catch ( CommandLineException e ) |
1291 | |
{ |
1292 | 0 | getLog().warn( e.getMessage() ); |
1293 | 0 | } |
1294 | 0 | } |
1295 | |
|
1296 | |
|
1297 | |
|
1298 | |
|
1299 | |
|
1300 | |
|
1301 | |
|
1302 | |
|
1303 | |
|
1304 | |
|
1305 | |
|
1306 | |
private void runBuild( File projectsDir, BuildJob buildJob, File settingsFile ) |
1307 | |
throws MojoExecutionException |
1308 | |
{ |
1309 | 0 | File pomFile = new File( projectsDir, buildJob.getProject() ); |
1310 | |
File basedir; |
1311 | 0 | if ( pomFile.isDirectory() ) |
1312 | |
{ |
1313 | 0 | basedir = pomFile; |
1314 | 0 | pomFile = new File( basedir, "pom.xml" ); |
1315 | 0 | if ( !pomFile.exists() ) |
1316 | |
{ |
1317 | 0 | pomFile = null; |
1318 | |
} |
1319 | |
else |
1320 | |
{ |
1321 | 0 | buildJob.setProject( buildJob.getProject() + File.separator + "pom.xml" ); |
1322 | |
} |
1323 | |
} |
1324 | |
else |
1325 | |
{ |
1326 | 0 | basedir = pomFile.getParentFile(); |
1327 | |
} |
1328 | |
|
1329 | 0 | getLog().info( "Building: " + buildJob.getProject() ); |
1330 | |
|
1331 | 0 | File interpolatedPomFile = null; |
1332 | 0 | if ( pomFile != null ) |
1333 | |
{ |
1334 | 0 | if ( filteredPomPrefix != null ) |
1335 | |
{ |
1336 | 0 | interpolatedPomFile = new File( basedir, filteredPomPrefix + pomFile.getName() ); |
1337 | 0 | buildInterpolatedFile( pomFile, interpolatedPomFile ); |
1338 | |
} |
1339 | |
else |
1340 | |
{ |
1341 | 0 | interpolatedPomFile = pomFile; |
1342 | |
} |
1343 | |
} |
1344 | |
|
1345 | 0 | InvokerProperties invokerProperties = getInvokerProperties( basedir ); |
1346 | |
|
1347 | |
|
1348 | 0 | buildJob.setName( invokerProperties.getJobName() ); |
1349 | 0 | buildJob.setDescription( invokerProperties.getJobDescription() ); |
1350 | |
|
1351 | |
try |
1352 | |
{ |
1353 | 0 | int selection = getSelection( invokerProperties ); |
1354 | 0 | if ( selection == 0 ) |
1355 | |
{ |
1356 | 0 | long milliseconds = System.currentTimeMillis(); |
1357 | |
boolean executed; |
1358 | |
try |
1359 | |
{ |
1360 | 0 | executed = runBuild( basedir, interpolatedPomFile, settingsFile, invokerProperties ); |
1361 | |
} |
1362 | |
finally |
1363 | |
{ |
1364 | 0 | milliseconds = System.currentTimeMillis() - milliseconds; |
1365 | 0 | buildJob.setTime( milliseconds / 1000.0 ); |
1366 | 0 | } |
1367 | |
|
1368 | 0 | if ( executed ) |
1369 | |
{ |
1370 | |
|
1371 | 0 | buildJob.setResult( BuildJob.Result.SUCCESS ); |
1372 | |
|
1373 | 0 | if ( !suppressSummaries ) |
1374 | |
{ |
1375 | 0 | getLog().info( "..SUCCESS " + formatTime( buildJob.getTime() ) ); |
1376 | |
} |
1377 | |
} |
1378 | |
else |
1379 | |
{ |
1380 | 0 | buildJob.setResult( BuildJob.Result.SKIPPED ); |
1381 | |
|
1382 | 0 | if ( !suppressSummaries ) |
1383 | |
{ |
1384 | 0 | getLog().info( "..SKIPPED " + formatTime( buildJob.getTime() ) ); |
1385 | |
} |
1386 | |
} |
1387 | 0 | } |
1388 | |
else |
1389 | |
{ |
1390 | 0 | buildJob.setResult( BuildJob.Result.SKIPPED ); |
1391 | |
|
1392 | 0 | StringBuilder message = new StringBuilder(); |
1393 | 0 | if ( ( selection & SELECTOR_MAVENVERSION ) != 0 ) |
1394 | |
{ |
1395 | 0 | message.append( "Maven version" ); |
1396 | |
} |
1397 | 0 | if ( ( selection & SELECTOR_JREVERSION ) != 0 ) |
1398 | |
{ |
1399 | 0 | if ( message.length() > 0 ) |
1400 | |
{ |
1401 | 0 | message.append( ", " ); |
1402 | |
} |
1403 | 0 | message.append( "JRE version" ); |
1404 | |
} |
1405 | 0 | if ( ( selection & SELECTOR_OSFAMILY ) != 0 ) |
1406 | |
{ |
1407 | 0 | if ( message.length() > 0 ) |
1408 | |
{ |
1409 | 0 | message.append( ", " ); |
1410 | |
} |
1411 | 0 | message.append( "OS" ); |
1412 | |
} |
1413 | |
|
1414 | 0 | if ( !suppressSummaries ) |
1415 | |
{ |
1416 | 0 | getLog().info( "..SKIPPED due to " + message.toString() ); |
1417 | |
} |
1418 | |
|
1419 | |
|
1420 | |
|
1421 | 0 | buildJob.setFailureMessage( "Skipped due to " + message.toString() ); |
1422 | |
} |
1423 | |
} |
1424 | 0 | catch ( RunErrorException e ) |
1425 | |
{ |
1426 | 0 | buildJob.setResult( BuildJob.Result.ERROR ); |
1427 | 0 | buildJob.setFailureMessage( e.getMessage() ); |
1428 | |
|
1429 | 0 | if ( !suppressSummaries ) |
1430 | |
{ |
1431 | 0 | getLog().info( "..ERROR " + formatTime( buildJob.getTime() ) ); |
1432 | 0 | getLog().info( " " + e.getMessage() ); |
1433 | |
} |
1434 | |
} |
1435 | 0 | catch ( RunFailureException e ) |
1436 | |
{ |
1437 | 0 | buildJob.setResult( e.getType() ); |
1438 | 0 | buildJob.setFailureMessage( e.getMessage() ); |
1439 | |
|
1440 | 0 | if ( !suppressSummaries ) |
1441 | |
{ |
1442 | 0 | getLog().info( "..FAILED " + formatTime( buildJob.getTime() ) ); |
1443 | 0 | getLog().info( " " + e.getMessage() ); |
1444 | |
} |
1445 | |
} |
1446 | |
finally |
1447 | |
{ |
1448 | 0 | if ( interpolatedPomFile != null && StringUtils.isNotEmpty( filteredPomPrefix ) ) |
1449 | |
{ |
1450 | 0 | interpolatedPomFile.delete(); |
1451 | |
} |
1452 | 0 | writeBuildReport( buildJob ); |
1453 | 0 | } |
1454 | 0 | } |
1455 | |
|
1456 | |
|
1457 | |
|
1458 | |
|
1459 | |
|
1460 | |
|
1461 | |
|
1462 | |
|
1463 | |
private int getSelection( InvokerProperties invokerProperties ) |
1464 | |
{ |
1465 | 0 | int selection = 0; |
1466 | 0 | if ( !SelectorUtils.isMavenVersion( invokerProperties.getMavenVersion(), actualMavenVersion ) ) |
1467 | |
{ |
1468 | 0 | selection |= SELECTOR_MAVENVERSION; |
1469 | |
} |
1470 | |
|
1471 | 0 | if ( !SelectorUtils.isJreVersion( invokerProperties.getJreVersion(), actualJreVersion ) ) |
1472 | |
{ |
1473 | 0 | selection |= SELECTOR_JREVERSION; |
1474 | |
} |
1475 | |
|
1476 | 0 | if ( !SelectorUtils.isOsFamily( invokerProperties.getOsFamily() ) ) |
1477 | |
{ |
1478 | 0 | selection |= SELECTOR_OSFAMILY; |
1479 | |
} |
1480 | |
|
1481 | 0 | return selection; |
1482 | |
} |
1483 | |
|
1484 | |
|
1485 | |
|
1486 | |
|
1487 | |
|
1488 | |
|
1489 | |
|
1490 | |
|
1491 | |
private void writeBuildReport( BuildJob buildJob ) |
1492 | |
throws MojoExecutionException |
1493 | |
{ |
1494 | 0 | if ( disableReports ) |
1495 | |
{ |
1496 | 0 | return; |
1497 | |
} |
1498 | |
|
1499 | 0 | String safeFileName = buildJob.getProject().replace( '/', '_' ).replace( '\\', '_' ).replace( ' ', '_' ); |
1500 | 0 | if ( safeFileName.endsWith( "_pom.xml" ) ) |
1501 | |
{ |
1502 | 0 | safeFileName = safeFileName.substring( 0, safeFileName.length() - "_pom.xml".length() ); |
1503 | |
} |
1504 | |
|
1505 | 0 | File reportFile = new File( reportsDirectory, "BUILD-" + safeFileName + ".xml" ); |
1506 | |
try |
1507 | |
{ |
1508 | 0 | FileOutputStream fos = new FileOutputStream( reportFile ); |
1509 | |
try |
1510 | |
{ |
1511 | 0 | Writer osw = new OutputStreamWriter( fos, buildJob.getModelEncoding() ); |
1512 | 0 | BuildJobXpp3Writer writer = new BuildJobXpp3Writer(); |
1513 | 0 | writer.write( osw, buildJob ); |
1514 | 0 | osw.close(); |
1515 | |
} |
1516 | |
finally |
1517 | |
{ |
1518 | 0 | fos.close(); |
1519 | 0 | } |
1520 | |
} |
1521 | 0 | catch ( IOException e ) |
1522 | |
{ |
1523 | 0 | throw new MojoExecutionException( "Failed to write build report " + reportFile, e ); |
1524 | 0 | } |
1525 | 0 | } |
1526 | |
|
1527 | |
|
1528 | |
|
1529 | |
|
1530 | |
|
1531 | |
|
1532 | |
|
1533 | |
private String formatTime( double seconds ) |
1534 | |
{ |
1535 | 0 | return secFormat.format( seconds ); |
1536 | |
} |
1537 | |
|
1538 | |
|
1539 | |
|
1540 | |
|
1541 | |
|
1542 | |
|
1543 | |
|
1544 | |
|
1545 | |
|
1546 | |
|
1547 | |
|
1548 | |
|
1549 | |
|
1550 | |
|
1551 | |
|
1552 | |
|
1553 | |
private boolean runBuild( File basedir, File pomFile, File settingsFile, InvokerProperties invokerProperties ) |
1554 | |
throws MojoExecutionException, RunFailureException |
1555 | |
{ |
1556 | 0 | if ( getLog().isDebugEnabled() && !invokerProperties.getProperties().isEmpty() ) |
1557 | |
{ |
1558 | 0 | Properties props = invokerProperties.getProperties(); |
1559 | 0 | getLog().debug( "Using invoker properties:" ); |
1560 | 0 | for ( String key : new TreeSet<String>( (Set) props.keySet() ) ) |
1561 | |
{ |
1562 | 0 | String value = props.getProperty( key ); |
1563 | 0 | getLog().debug( " " + key + " = " + value ); |
1564 | 0 | } |
1565 | |
} |
1566 | |
|
1567 | 0 | List<String> goals = getGoals( basedir ); |
1568 | |
|
1569 | 0 | List<String> profiles = getProfiles( basedir ); |
1570 | |
|
1571 | 0 | Map<String, Object> context = new LinkedHashMap<String, Object>(); |
1572 | |
|
1573 | 0 | FileLogger logger = setupLogger( basedir ); |
1574 | |
try |
1575 | |
{ |
1576 | |
try |
1577 | |
{ |
1578 | 0 | scriptRunner.run( "selector script", basedir, selectorScript, context, logger, BuildJob.Result.SKIPPED, |
1579 | |
false ); |
1580 | |
} |
1581 | 0 | catch ( RunErrorException e ) |
1582 | |
{ |
1583 | 0 | throw e; |
1584 | |
} |
1585 | 0 | catch ( RunFailureException e ) |
1586 | |
{ |
1587 | 0 | return false; |
1588 | 0 | } |
1589 | |
|
1590 | 0 | scriptRunner.run( "pre-build script", basedir, preBuildHookScript, context, logger, |
1591 | |
BuildJob.Result.FAILURE_PRE_HOOK, false ); |
1592 | |
|
1593 | 0 | final InvocationRequest request = new DefaultInvocationRequest(); |
1594 | |
|
1595 | 0 | request.setLocalRepositoryDirectory( localRepositoryPath ); |
1596 | |
|
1597 | 0 | request.setInteractive( false ); |
1598 | |
|
1599 | 0 | request.setShowErrors( showErrors ); |
1600 | |
|
1601 | 0 | request.setDebug( debug ); |
1602 | |
|
1603 | 0 | request.setShowVersion( showVersion ); |
1604 | |
|
1605 | 0 | if ( logger != null ) |
1606 | |
{ |
1607 | 0 | request.setErrorHandler( logger ); |
1608 | |
|
1609 | 0 | request.setOutputHandler( logger ); |
1610 | |
} |
1611 | |
|
1612 | 0 | if ( mavenHome != null ) |
1613 | |
{ |
1614 | 0 | invoker.setMavenHome( mavenHome ); |
1615 | 0 | request.addShellEnvironment( "M2_HOME", mavenHome.getAbsolutePath() ); |
1616 | |
} |
1617 | |
|
1618 | 0 | if ( mavenExecutable != null ) |
1619 | |
{ |
1620 | 0 | invoker.setMavenExecutable( new File( mavenExecutable ) ); |
1621 | |
} |
1622 | |
|
1623 | 0 | if ( javaHome != null ) |
1624 | |
{ |
1625 | 0 | request.setJavaHome( javaHome ); |
1626 | |
} |
1627 | |
|
1628 | 0 | if ( environmentVariables != null ) |
1629 | |
{ |
1630 | 0 | for ( Map.Entry<String, String> variable : environmentVariables.entrySet() ) |
1631 | |
{ |
1632 | 0 | request.addShellEnvironment( variable.getKey(), variable.getValue() ); |
1633 | |
} |
1634 | |
} |
1635 | |
|
1636 | 0 | for ( int invocationIndex = 1; ; invocationIndex++ ) |
1637 | |
{ |
1638 | 0 | if ( invocationIndex > 1 && !invokerProperties.isInvocationDefined( invocationIndex ) ) |
1639 | |
{ |
1640 | 0 | break; |
1641 | |
} |
1642 | |
|
1643 | 0 | request.setBaseDirectory( basedir ); |
1644 | |
|
1645 | 0 | request.setPomFile( pomFile ); |
1646 | |
|
1647 | 0 | request.setGoals( goals ); |
1648 | |
|
1649 | 0 | request.setProfiles( profiles ); |
1650 | |
|
1651 | 0 | request.setMavenOpts( mavenOpts ); |
1652 | |
|
1653 | 0 | request.setOffline( false ); |
1654 | |
|
1655 | 0 | request.setUserSettingsFile( settingsFile ); |
1656 | |
|
1657 | 0 | Properties systemProperties = |
1658 | |
getSystemProperties( basedir, invokerProperties.getSystemPropertiesFile( invocationIndex ) ); |
1659 | 0 | request.setProperties( systemProperties ); |
1660 | |
|
1661 | 0 | invokerProperties.configureInvocation( request, invocationIndex ); |
1662 | |
|
1663 | 0 | if ( getLog().isDebugEnabled() ) |
1664 | |
{ |
1665 | |
try |
1666 | |
{ |
1667 | 0 | getLog().debug( "Using MAVEN_OPTS: " + request.getMavenOpts() ); |
1668 | 0 | getLog().debug( "Executing: " + new MavenCommandLineBuilder().build( request ) ); |
1669 | |
} |
1670 | 0 | catch ( CommandLineConfigurationException e ) |
1671 | |
{ |
1672 | 0 | getLog().debug( "Failed to display command line: " + e.getMessage() ); |
1673 | 0 | } |
1674 | |
} |
1675 | |
|
1676 | |
InvocationResult result; |
1677 | |
|
1678 | |
try |
1679 | |
{ |
1680 | 0 | result = invoker.execute( request ); |
1681 | |
} |
1682 | 0 | catch ( final MavenInvocationException e ) |
1683 | |
{ |
1684 | 0 | getLog().debug( "Error invoking Maven: " + e.getMessage(), e ); |
1685 | 0 | throw new RunFailureException( "Maven invocation failed. " + e.getMessage(), |
1686 | |
BuildJob.Result.FAILURE_BUILD ); |
1687 | 0 | } |
1688 | |
|
1689 | 0 | verify( result, invocationIndex, invokerProperties, logger ); |
1690 | |
} |
1691 | |
|
1692 | 0 | scriptRunner.run( "post-build script", basedir, postBuildHookScript, context, logger, |
1693 | |
BuildJob.Result.FAILURE_POST_HOOK, true ); |
1694 | |
} |
1695 | 0 | catch ( IOException e ) |
1696 | |
{ |
1697 | 0 | throw new MojoExecutionException( e.getMessage(), e ); |
1698 | |
} |
1699 | |
finally |
1700 | |
{ |
1701 | 0 | if ( logger != null ) |
1702 | |
{ |
1703 | 0 | logger.close(); |
1704 | |
} |
1705 | |
} |
1706 | 0 | return true; |
1707 | |
} |
1708 | |
|
1709 | |
|
1710 | |
|
1711 | |
|
1712 | |
|
1713 | |
|
1714 | |
|
1715 | |
|
1716 | |
|
1717 | |
private FileLogger setupLogger( File basedir ) |
1718 | |
throws MojoExecutionException |
1719 | |
{ |
1720 | 0 | FileLogger logger = null; |
1721 | |
|
1722 | 0 | if ( !noLog ) |
1723 | |
{ |
1724 | 0 | File outputLog = new File( basedir, "build.log" ); |
1725 | |
try |
1726 | |
{ |
1727 | 0 | if ( streamLogs ) |
1728 | |
{ |
1729 | 0 | logger = new FileLogger( outputLog, getLog() ); |
1730 | |
} |
1731 | |
else |
1732 | |
{ |
1733 | 0 | logger = new FileLogger( outputLog ); |
1734 | |
} |
1735 | |
|
1736 | 0 | getLog().debug( "build log initialized in: " + outputLog ); |
1737 | |
} |
1738 | 0 | catch ( IOException e ) |
1739 | |
{ |
1740 | 0 | throw new MojoExecutionException( "Error initializing build logfile in: " + outputLog, e ); |
1741 | 0 | } |
1742 | |
} |
1743 | |
|
1744 | 0 | return logger; |
1745 | |
} |
1746 | |
|
1747 | |
|
1748 | |
|
1749 | |
|
1750 | |
|
1751 | |
|
1752 | |
|
1753 | |
|
1754 | |
|
1755 | |
|
1756 | |
|
1757 | |
private Properties getSystemProperties( final File basedir, final String filename ) |
1758 | |
throws MojoExecutionException |
1759 | |
{ |
1760 | 0 | Properties collectedTestProperties = new Properties(); |
1761 | |
|
1762 | 0 | if ( testProperties != null ) |
1763 | |
{ |
1764 | 0 | collectedTestProperties.putAll( testProperties ); |
1765 | |
} |
1766 | |
|
1767 | 0 | if ( properties != null ) |
1768 | |
{ |
1769 | |
|
1770 | 0 | for ( Map.Entry<String, String> entry : properties.entrySet() ) |
1771 | |
{ |
1772 | 0 | if ( entry.getValue() != null ) |
1773 | |
{ |
1774 | 0 | collectedTestProperties.put( entry.getKey(), entry.getValue() ); |
1775 | |
} |
1776 | |
} |
1777 | |
} |
1778 | |
|
1779 | 0 | File propertiesFile = null; |
1780 | 0 | if ( filename != null ) |
1781 | |
{ |
1782 | 0 | propertiesFile = new File( basedir, filename ); |
1783 | |
} |
1784 | 0 | else if ( testPropertiesFile != null ) |
1785 | |
{ |
1786 | 0 | propertiesFile = new File( basedir, testPropertiesFile ); |
1787 | |
} |
1788 | |
|
1789 | 0 | if ( propertiesFile != null && propertiesFile.isFile() ) |
1790 | |
{ |
1791 | 0 | InputStream fin = null; |
1792 | |
try |
1793 | |
{ |
1794 | 0 | fin = new FileInputStream( propertiesFile ); |
1795 | |
|
1796 | 0 | Properties loadedProperties = new Properties(); |
1797 | 0 | loadedProperties.load( fin ); |
1798 | 0 | collectedTestProperties.putAll( loadedProperties ); |
1799 | |
} |
1800 | 0 | catch ( IOException e ) |
1801 | |
{ |
1802 | 0 | throw new MojoExecutionException( "Error reading system properties from " + propertiesFile ); |
1803 | |
} |
1804 | |
finally |
1805 | |
{ |
1806 | 0 | IOUtil.close( fin ); |
1807 | 0 | } |
1808 | |
} |
1809 | |
|
1810 | 0 | return collectedTestProperties; |
1811 | |
} |
1812 | |
|
1813 | |
|
1814 | |
|
1815 | |
|
1816 | |
|
1817 | |
|
1818 | |
|
1819 | |
|
1820 | |
|
1821 | |
|
1822 | |
|
1823 | |
private void verify( InvocationResult result, int invocationIndex, InvokerProperties invokerProperties, |
1824 | |
FileLogger logger ) |
1825 | |
throws RunFailureException |
1826 | |
{ |
1827 | 0 | if ( result.getExecutionException() != null ) |
1828 | |
{ |
1829 | 0 | throw new RunFailureException( |
1830 | |
"The Maven invocation failed. " + result.getExecutionException().getMessage(), BuildJob.Result.ERROR ); |
1831 | |
} |
1832 | 0 | else if ( !invokerProperties.isExpectedResult( result.getExitCode(), invocationIndex ) ) |
1833 | |
{ |
1834 | 0 | StringBuilder buffer = new StringBuilder( 256 ); |
1835 | 0 | buffer.append( "The build exited with code " ).append( result.getExitCode() ).append( ". " ); |
1836 | 0 | if ( logger != null ) |
1837 | |
{ |
1838 | 0 | buffer.append( "See " ); |
1839 | 0 | buffer.append( logger.getOutputFile().getAbsolutePath() ); |
1840 | 0 | buffer.append( " for details." ); |
1841 | |
} |
1842 | |
else |
1843 | |
{ |
1844 | 0 | buffer.append( "See console output for details." ); |
1845 | |
} |
1846 | 0 | throw new RunFailureException( buffer.toString(), BuildJob.Result.FAILURE_BUILD ); |
1847 | |
} |
1848 | 0 | } |
1849 | |
|
1850 | |
|
1851 | |
|
1852 | |
|
1853 | |
|
1854 | |
|
1855 | |
|
1856 | |
|
1857 | |
|
1858 | |
List<String> getGoals( final File basedir ) |
1859 | |
throws MojoExecutionException |
1860 | |
{ |
1861 | |
try |
1862 | |
{ |
1863 | 10 | return getTokens( basedir, goalsFile, goals ); |
1864 | |
} |
1865 | 0 | catch ( IOException e ) |
1866 | |
{ |
1867 | 0 | throw new MojoExecutionException( "error reading goals", e ); |
1868 | |
} |
1869 | |
} |
1870 | |
|
1871 | |
|
1872 | |
|
1873 | |
|
1874 | |
|
1875 | |
|
1876 | |
|
1877 | |
|
1878 | |
|
1879 | |
List<String> getProfiles( File basedir ) |
1880 | |
throws MojoExecutionException |
1881 | |
{ |
1882 | |
try |
1883 | |
{ |
1884 | 6 | return getTokens( basedir, profilesFile, profiles ); |
1885 | |
} |
1886 | 0 | catch ( IOException e ) |
1887 | |
{ |
1888 | 0 | throw new MojoExecutionException( "error reading profiles", e ); |
1889 | |
} |
1890 | |
} |
1891 | |
|
1892 | |
|
1893 | |
|
1894 | |
|
1895 | |
|
1896 | |
|
1897 | |
|
1898 | |
BuildJob[] getBuildJobs() |
1899 | |
throws IOException |
1900 | |
{ |
1901 | |
BuildJob[] buildJobs; |
1902 | |
|
1903 | 6 | if ( ( pom != null ) && pom.exists() ) |
1904 | |
{ |
1905 | 0 | buildJobs = new BuildJob[]{ new BuildJob( pom.getAbsolutePath(), BuildJob.Type.NORMAL ) }; |
1906 | |
} |
1907 | 6 | else if ( invokerTest != null ) |
1908 | |
{ |
1909 | 6 | String[] testRegexes = StringUtils.split( invokerTest, "," ); |
1910 | 6 | List<String> includes = new ArrayList<String>( testRegexes.length ); |
1911 | 6 | List<String> excludes = new ArrayList<String>(); |
1912 | |
|
1913 | 14 | for ( String regex : testRegexes ) |
1914 | |
{ |
1915 | |
|
1916 | 8 | if ( regex.startsWith( "!" ) ) |
1917 | |
{ |
1918 | 0 | excludes.add( regex.substring( 1 ) ); |
1919 | |
} |
1920 | |
else |
1921 | |
{ |
1922 | 8 | includes.add( regex ); |
1923 | |
} |
1924 | |
} |
1925 | |
|
1926 | |
|
1927 | |
|
1928 | 6 | buildJobs = scanProjectsDirectory( includes, excludes, BuildJob.Type.DIRECT ); |
1929 | 6 | } |
1930 | |
else |
1931 | |
{ |
1932 | 0 | List<String> excludes = |
1933 | |
( pomExcludes != null ) ? new ArrayList<String>( pomExcludes ) : new ArrayList<String>(); |
1934 | 0 | if ( this.settingsFile != null ) |
1935 | |
{ |
1936 | 0 | String exclude = relativizePath( this.settingsFile, projectsDirectory.getCanonicalPath() ); |
1937 | 0 | if ( exclude != null ) |
1938 | |
{ |
1939 | 0 | excludes.add( exclude.replace( '\\', '/' ) ); |
1940 | 0 | getLog().debug( "Automatically excluded " + exclude + " from project scanning" ); |
1941 | |
} |
1942 | |
} |
1943 | |
|
1944 | 0 | BuildJob[] setupPoms = scanProjectsDirectory( setupIncludes, excludes, BuildJob.Type.SETUP ); |
1945 | 0 | getLog().debug( "Setup projects: " + Arrays.asList( setupPoms ) ); |
1946 | |
|
1947 | 0 | BuildJob[] normalPoms = scanProjectsDirectory( pomIncludes, excludes, BuildJob.Type.NORMAL ); |
1948 | |
|
1949 | 0 | Map<String, BuildJob> uniquePoms = new LinkedHashMap<String, BuildJob>(); |
1950 | 0 | for ( BuildJob setupPom : setupPoms ) |
1951 | |
{ |
1952 | 0 | uniquePoms.put( setupPom.getProject(), setupPom ); |
1953 | |
} |
1954 | 0 | for ( BuildJob normalPom : normalPoms ) |
1955 | |
{ |
1956 | 0 | if ( !uniquePoms.containsKey( normalPom.getProject() ) ) |
1957 | |
{ |
1958 | 0 | uniquePoms.put( normalPom.getProject(), normalPom ); |
1959 | |
} |
1960 | |
} |
1961 | |
|
1962 | 0 | buildJobs = uniquePoms.values().toArray( new BuildJob[uniquePoms.size()] ); |
1963 | |
} |
1964 | |
|
1965 | 6 | relativizeProjectPaths( buildJobs ); |
1966 | |
|
1967 | 6 | return buildJobs; |
1968 | |
} |
1969 | |
|
1970 | |
|
1971 | |
|
1972 | |
|
1973 | |
|
1974 | |
|
1975 | |
|
1976 | |
|
1977 | |
|
1978 | |
|
1979 | |
|
1980 | |
|
1981 | |
|
1982 | |
private BuildJob[] scanProjectsDirectory( List<String> includes, List<String> excludes, String type ) |
1983 | |
throws IOException |
1984 | |
{ |
1985 | 6 | if ( !projectsDirectory.isDirectory() ) |
1986 | |
{ |
1987 | 0 | return new BuildJob[0]; |
1988 | |
} |
1989 | |
|
1990 | 6 | DirectoryScanner scanner = new DirectoryScanner(); |
1991 | 6 | scanner.setBasedir( projectsDirectory.getCanonicalFile() ); |
1992 | 6 | scanner.setFollowSymlinks( false ); |
1993 | 6 | if ( includes != null ) |
1994 | |
{ |
1995 | 6 | scanner.setIncludes( includes.toArray( new String[includes.size()] ) ); |
1996 | |
} |
1997 | 6 | if ( excludes != null ) |
1998 | |
{ |
1999 | 6 | scanner.setExcludes( excludes.toArray( new String[excludes.size()] ) ); |
2000 | |
} |
2001 | 6 | scanner.addDefaultExcludes(); |
2002 | 6 | scanner.scan(); |
2003 | |
|
2004 | 6 | Map<String, BuildJob> matches = new LinkedHashMap<String, BuildJob>(); |
2005 | |
|
2006 | 6 | for ( String includedFile : scanner.getIncludedFiles() ) |
2007 | |
{ |
2008 | 0 | matches.put( includedFile, new BuildJob( includedFile, type ) ); |
2009 | |
} |
2010 | |
|
2011 | 20 | for ( String includedDir : scanner.getIncludedDirectories() ) |
2012 | |
{ |
2013 | 14 | String includedFile = includedDir + File.separatorChar + "pom.xml"; |
2014 | 14 | if ( new File( scanner.getBasedir(), includedFile ).isFile() ) |
2015 | |
{ |
2016 | 12 | matches.put( includedFile, new BuildJob( includedFile, type ) ); |
2017 | |
} |
2018 | |
else |
2019 | |
{ |
2020 | 2 | matches.put( includedDir, new BuildJob( includedDir, type ) ); |
2021 | |
} |
2022 | |
} |
2023 | |
|
2024 | 6 | return matches.values().toArray( new BuildJob[matches.size()] ); |
2025 | |
} |
2026 | |
|
2027 | |
|
2028 | |
|
2029 | |
|
2030 | |
|
2031 | |
|
2032 | |
|
2033 | |
|
2034 | |
|
2035 | |
|
2036 | |
private void relativizeProjectPaths( BuildJob[] buildJobs ) |
2037 | |
throws IOException |
2038 | |
{ |
2039 | 6 | String projectsDirPath = projectsDirectory.getCanonicalPath(); |
2040 | |
|
2041 | 20 | for ( BuildJob buildJob : buildJobs ) |
2042 | |
{ |
2043 | 14 | String projectPath = buildJob.getProject(); |
2044 | |
|
2045 | 14 | File file = new File( projectPath ); |
2046 | |
|
2047 | 14 | if ( !file.isAbsolute() ) |
2048 | |
{ |
2049 | 14 | file = new File( projectsDirectory, projectPath ); |
2050 | |
} |
2051 | |
|
2052 | 14 | String relativizedPath = relativizePath( file, projectsDirPath ); |
2053 | |
|
2054 | 14 | if ( relativizedPath == null ) |
2055 | |
{ |
2056 | 0 | relativizedPath = projectPath; |
2057 | |
} |
2058 | |
|
2059 | 14 | buildJob.setProject( relativizedPath ); |
2060 | |
} |
2061 | 6 | } |
2062 | |
|
2063 | |
|
2064 | |
|
2065 | |
|
2066 | |
|
2067 | |
|
2068 | |
|
2069 | |
|
2070 | |
|
2071 | |
|
2072 | |
|
2073 | |
private String relativizePath( File path, String basedir ) |
2074 | |
throws IOException |
2075 | |
{ |
2076 | 14 | String relativizedPath = path.getCanonicalPath(); |
2077 | |
|
2078 | 14 | if ( relativizedPath.startsWith( basedir ) ) |
2079 | |
{ |
2080 | 14 | relativizedPath = relativizedPath.substring( basedir.length() ); |
2081 | 14 | if ( relativizedPath.startsWith( File.separator ) ) |
2082 | |
{ |
2083 | 14 | relativizedPath = relativizedPath.substring( File.separator.length() ); |
2084 | |
} |
2085 | |
|
2086 | 14 | return relativizedPath; |
2087 | |
} |
2088 | |
else |
2089 | |
{ |
2090 | 0 | return null; |
2091 | |
} |
2092 | |
} |
2093 | |
|
2094 | |
|
2095 | |
|
2096 | |
|
2097 | |
|
2098 | |
|
2099 | |
private Map<String, Object> getInterpolationValueSource() |
2100 | |
{ |
2101 | 12 | Map<String, Object> props = new HashMap<String, Object>(); |
2102 | 12 | if ( interpolationsProperties != null ) |
2103 | |
{ |
2104 | 6 | props.putAll( (Map) interpolationsProperties ); |
2105 | |
} |
2106 | 12 | if ( filterProperties != null ) |
2107 | |
{ |
2108 | 0 | props.putAll( filterProperties ); |
2109 | |
} |
2110 | 12 | props.put( "basedir", this.project.getBasedir().getAbsolutePath() ); |
2111 | 12 | props.put( "baseurl", toUrl( this.project.getBasedir().getAbsolutePath() ) ); |
2112 | 12 | if ( settings.getLocalRepository() != null ) |
2113 | |
{ |
2114 | 0 | props.put( "localRepository", settings.getLocalRepository() ); |
2115 | 0 | props.put( "localRepositoryUrl", toUrl( settings.getLocalRepository() ) ); |
2116 | |
} |
2117 | 12 | return new CompositeMap( this.project, props ); |
2118 | |
} |
2119 | |
|
2120 | |
|
2121 | |
|
2122 | |
|
2123 | |
|
2124 | |
|
2125 | |
|
2126 | |
|
2127 | |
private static String toUrl( String filename ) |
2128 | |
{ |
2129 | |
|
2130 | |
|
2131 | |
|
2132 | |
|
2133 | 12 | String url = "file://" + new File( filename ).toURI().getPath(); |
2134 | 12 | if ( url.endsWith( "/" ) ) |
2135 | |
{ |
2136 | 12 | url = url.substring( 0, url.length() - 1 ); |
2137 | |
} |
2138 | 12 | return url; |
2139 | |
} |
2140 | |
|
2141 | |
|
2142 | |
|
2143 | |
|
2144 | |
|
2145 | |
|
2146 | |
|
2147 | |
|
2148 | |
|
2149 | |
|
2150 | |
|
2151 | |
|
2152 | |
|
2153 | |
private List<String> getTokens( File basedir, String filename, List<String> defaultTokens ) |
2154 | |
throws IOException |
2155 | |
{ |
2156 | 16 | List<String> tokens = ( defaultTokens != null ) ? defaultTokens : new ArrayList<String>(); |
2157 | |
|
2158 | 16 | if ( StringUtils.isNotEmpty( filename ) ) |
2159 | |
{ |
2160 | 16 | File tokenFile = new File( basedir, filename ); |
2161 | |
|
2162 | 16 | if ( tokenFile.exists() ) |
2163 | |
{ |
2164 | 8 | tokens = readTokens( tokenFile ); |
2165 | |
} |
2166 | |
} |
2167 | |
|
2168 | 16 | return tokens; |
2169 | |
} |
2170 | |
|
2171 | |
|
2172 | |
|
2173 | |
|
2174 | |
|
2175 | |
|
2176 | |
|
2177 | |
|
2178 | |
|
2179 | |
private List<String> readTokens( final File tokenFile ) |
2180 | |
throws IOException |
2181 | |
{ |
2182 | 8 | List<String> result = new ArrayList<String>(); |
2183 | |
|
2184 | 8 | BufferedReader reader = null; |
2185 | |
try |
2186 | |
{ |
2187 | 8 | Map<String, Object> composite = getInterpolationValueSource(); |
2188 | 8 | reader = new BufferedReader( new InterpolationFilterReader( newReader( tokenFile ), composite ) ); |
2189 | |
|
2190 | 8 | String line = null; |
2191 | 18 | while ( ( line = reader.readLine() ) != null ) |
2192 | |
{ |
2193 | 10 | result.addAll( collectListFromCSV( line ) ); |
2194 | |
} |
2195 | |
} |
2196 | |
finally |
2197 | |
{ |
2198 | 8 | IOUtil.close( reader ); |
2199 | 8 | } |
2200 | |
|
2201 | 8 | return result; |
2202 | |
} |
2203 | |
|
2204 | |
|
2205 | |
|
2206 | |
|
2207 | |
|
2208 | |
|
2209 | |
|
2210 | |
private List<String> collectListFromCSV( final String csv ) |
2211 | |
{ |
2212 | 10 | final List<String> result = new ArrayList<String>(); |
2213 | |
|
2214 | 10 | if ( ( csv != null ) && ( csv.trim().length() > 0 ) ) |
2215 | |
{ |
2216 | 10 | final StringTokenizer st = new StringTokenizer( csv, "," ); |
2217 | |
|
2218 | 24 | while ( st.hasMoreTokens() ) |
2219 | |
{ |
2220 | 14 | result.add( st.nextToken().trim() ); |
2221 | |
} |
2222 | |
} |
2223 | |
|
2224 | 10 | return result; |
2225 | |
} |
2226 | |
|
2227 | |
|
2228 | |
|
2229 | |
|
2230 | |
|
2231 | |
|
2232 | |
|
2233 | |
|
2234 | |
|
2235 | |
|
2236 | |
|
2237 | |
void buildInterpolatedFile( File originalFile, File interpolatedFile ) |
2238 | |
throws MojoExecutionException |
2239 | |
{ |
2240 | 4 | getLog().debug( "Interpolate " + originalFile.getPath() + " to " + interpolatedFile.getPath() ); |
2241 | |
|
2242 | |
try |
2243 | |
{ |
2244 | |
String xml; |
2245 | |
|
2246 | 4 | Reader reader = null; |
2247 | |
try |
2248 | |
{ |
2249 | |
|
2250 | 4 | Map<String, Object> composite = getInterpolationValueSource(); |
2251 | 4 | reader = ReaderFactory.newXmlReader( originalFile ); |
2252 | 4 | reader = new InterpolationFilterReader( reader, composite, "@", "@" ); |
2253 | 4 | xml = IOUtil.toString( reader ); |
2254 | |
} |
2255 | |
finally |
2256 | |
{ |
2257 | 4 | IOUtil.close( reader ); |
2258 | 4 | } |
2259 | |
|
2260 | 4 | Writer writer = null; |
2261 | |
try |
2262 | |
{ |
2263 | 4 | interpolatedFile.getParentFile().mkdirs(); |
2264 | 4 | writer = WriterFactory.newXmlWriter( interpolatedFile ); |
2265 | 4 | writer.write( xml ); |
2266 | 4 | writer.flush(); |
2267 | |
} |
2268 | |
finally |
2269 | |
{ |
2270 | 4 | IOUtil.close( writer ); |
2271 | 4 | } |
2272 | |
} |
2273 | 0 | catch ( IOException e ) |
2274 | |
{ |
2275 | 0 | throw new MojoExecutionException( "Failed to interpolate file " + originalFile.getPath(), e ); |
2276 | 4 | } |
2277 | 4 | } |
2278 | |
|
2279 | |
|
2280 | |
|
2281 | |
|
2282 | |
|
2283 | |
|
2284 | |
|
2285 | |
|
2286 | |
|
2287 | |
private InvokerProperties getInvokerProperties( final File projectDirectory ) |
2288 | |
throws MojoExecutionException |
2289 | |
{ |
2290 | 0 | Properties props = new Properties(); |
2291 | 0 | if ( invokerPropertiesFile != null ) |
2292 | |
{ |
2293 | 0 | File propertiesFile = new File( projectDirectory, invokerPropertiesFile ); |
2294 | 0 | if ( propertiesFile.isFile() ) |
2295 | |
{ |
2296 | 0 | InputStream in = null; |
2297 | |
try |
2298 | |
{ |
2299 | 0 | in = new FileInputStream( propertiesFile ); |
2300 | 0 | props.load( in ); |
2301 | |
} |
2302 | 0 | catch ( IOException e ) |
2303 | |
{ |
2304 | 0 | throw new MojoExecutionException( "Failed to read invoker properties: " + propertiesFile, e ); |
2305 | |
} |
2306 | |
finally |
2307 | |
{ |
2308 | 0 | IOUtil.close( in ); |
2309 | 0 | } |
2310 | |
} |
2311 | |
|
2312 | 0 | Interpolator interpolator = new RegexBasedInterpolator(); |
2313 | 0 | interpolator.addValueSource( new MapBasedValueSource( getInterpolationValueSource() ) ); |
2314 | 0 | for ( String key : (Set<String>) ( (Map) props ).keySet() ) |
2315 | |
{ |
2316 | 0 | String value = props.getProperty( key ); |
2317 | |
try |
2318 | |
{ |
2319 | 0 | value = interpolator.interpolate( value, "" ); |
2320 | |
} |
2321 | 0 | catch ( InterpolationException e ) |
2322 | |
{ |
2323 | 0 | throw new MojoExecutionException( "Failed to interpolate invoker properties: " + propertiesFile, |
2324 | |
e ); |
2325 | 0 | } |
2326 | 0 | props.setProperty( key, value ); |
2327 | 0 | } |
2328 | |
} |
2329 | 0 | return new InvokerProperties( props ); |
2330 | |
} |
2331 | |
|
2332 | |
protected boolean isParallelRun() |
2333 | |
{ |
2334 | 0 | return parallelThreads > 1; |
2335 | |
} |
2336 | |
|
2337 | |
} |