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.FileNotFoundException;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.PrintStream;
29 import java.io.Reader;
30 import java.io.Writer;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collections;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Properties;
38 import java.util.StringTokenizer;
39 import java.util.TreeSet;
40
41 import org.apache.maven.plugin.AbstractMojo;
42 import org.apache.maven.plugin.MojoExecutionException;
43 import org.apache.maven.plugin.MojoFailureException;
44 import org.apache.maven.project.MavenProject;
45 import org.apache.maven.settings.Settings;
46 import org.apache.maven.shared.invoker.CommandLineConfigurationException;
47 import org.apache.maven.shared.invoker.DefaultInvocationRequest;
48 import org.apache.maven.shared.invoker.InvocationRequest;
49 import org.apache.maven.shared.invoker.InvocationResult;
50 import org.apache.maven.shared.invoker.Invoker;
51 import org.apache.maven.shared.invoker.MavenCommandLineBuilder;
52 import org.apache.maven.shared.invoker.MavenInvocationException;
53 import org.apache.maven.shared.model.fileset.FileSet;
54 import org.apache.maven.shared.model.fileset.util.FileSetManager;
55 import org.codehaus.plexus.util.DirectoryScanner;
56 import org.codehaus.plexus.util.FileUtils;
57 import org.codehaus.plexus.util.IOUtil;
58 import org.codehaus.plexus.util.InterpolationFilterReader;
59 import org.codehaus.plexus.util.ReaderFactory;
60 import org.codehaus.plexus.util.StringUtils;
61 import org.codehaus.plexus.util.WriterFactory;
62 import org.codehaus.plexus.util.cli.CommandLineException;
63 import org.codehaus.plexus.interpolation.InterpolationException;
64 import org.codehaus.plexus.interpolation.Interpolator;
65 import org.codehaus.plexus.interpolation.MapBasedValueSource;
66 import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
67
68 import bsh.EvalError;
69 import bsh.Interpreter;
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 public class InvokerMojo
85 extends AbstractMojo
86 {
87
88
89
90
91
92
93
94
95 private boolean skipInvocation;
96
97
98
99
100
101
102
103
104
105 private boolean suppressSummaries;
106
107
108
109
110
111
112 private boolean streamLogs;
113
114
115
116
117
118
119 private File localRepositoryPath;
120
121
122
123
124
125
126 private File projectsDirectory;
127
128
129
130
131
132
133
134
135
136 private File cloneProjectsTo;
137
138
139
140
141
142
143
144
145
146
147 private boolean cloneAllFiles;
148
149
150
151
152
153
154 private File pom;
155
156
157
158
159
160
161
162
163 private List pomIncludes = Collections.singletonList( "*/pom.xml" );
164
165
166
167
168
169
170
171 private List pomExcludes = Collections.EMPTY_LIST;
172
173
174
175
176
177
178 private List goals = Collections.singletonList( "package" );
179
180
181
182
183
184
185
186
187 private String goalsFile;
188
189
190
191
192 private Invoker invoker;
193
194
195
196
197
198
199 private String preBuildHookScript;
200
201
202
203
204
205
206 private String postBuildHookScript;
207
208
209
210
211
212
213 private String testPropertiesFile;
214
215
216
217
218
219
220
221 private Properties testProperties;
222
223
224
225
226
227
228
229 private Map properties;
230
231
232
233
234
235
236 private boolean showErrors;
237
238
239
240
241
242
243 private boolean debug;
244
245
246
247
248
249
250 private boolean noLog;
251
252
253
254
255
256
257
258 private List profiles;
259
260
261
262
263
264
265
266 private Properties interpolationsProperties;
267
268
269
270
271
272
273
274
275
276 private MavenProject project;
277
278
279
280
281
282
283
284
285
286
287 private String invokerTest;
288
289
290
291
292
293
294
295
296
297
298 private String profilesFile;
299
300
301
302
303
304
305
306 private File settingsFile;
307
308
309
310
311
312
313
314
315 private String mavenOpts;
316
317
318
319
320
321
322
323 private String encoding;
324
325
326
327
328
329
330
331
332
333 private Settings settings;
334
335
336
337
338
339
340
341
342
343
344
345 private boolean addTestClassPath;
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379 private String invokerPropertiesFile;
380
381
382 public void execute()
383 throws MojoExecutionException, MojoFailureException
384 {
385 if ( skipInvocation )
386 {
387 getLog().info( "Skipping invocation per configuration."
388 + " If this is incorrect, ensure the skipInvocation parameter is not set to true." );
389 return;
390 }
391
392 String[] includedPoms;
393 if ( pom != null )
394 {
395 try
396 {
397 projectsDirectory = pom.getCanonicalFile().getParentFile();
398 }
399 catch ( IOException e )
400 {
401 throw new MojoExecutionException( "Failed to discover projectsDirectory from pom File parameter."
402 + " Reason: " + e.getMessage(), e );
403 }
404
405 includedPoms = new String[]{ pom.getName() };
406 }
407 else
408 {
409 try
410 {
411 includedPoms = getPoms();
412 }
413 catch ( final IOException e )
414 {
415 throw new MojoExecutionException( "Error retrieving POM list from includes, excludes, "
416 + "and projects directory. Reason: " + e.getMessage(), e );
417 }
418 }
419
420
421 if ( ( includedPoms == null ) || ( includedPoms.length < 1 ) )
422 {
423 getLog().info( "No test-projects were selected for execution." );
424 return;
425 }
426
427 if ( StringUtils.isEmpty( encoding ) )
428 {
429 getLog().warn(
430 "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
431 + ", i.e. build is platform dependent!" );
432 }
433
434 File projectsDir = projectsDirectory;
435
436 if ( cloneProjectsTo != null )
437 {
438 cloneProjectsTo.mkdirs();
439
440 try
441 {
442 cloneProjects( includedPoms );
443 }
444 catch ( IOException e )
445 {
446 throw new MojoExecutionException( "Failed to clone projects from: " + projectsDirectory + " to: "
447 + cloneProjectsTo + ". Reason: " + e.getMessage(), e );
448 }
449
450 projectsDir = cloneProjectsTo;
451 }
452
453 final List failures = new ArrayList();
454
455 for ( int i = 0; i < includedPoms.length; i++ )
456 {
457 final String pom = includedPoms[i];
458
459 runBuild( projectsDir, pom, failures );
460 }
461
462
463 if ( !suppressSummaries )
464 {
465 final StringBuffer summary = new StringBuffer();
466 summary.append( "\n\n" );
467 summary.append( "---------------------------------------\n" );
468 summary.append( "Execution Summary:\n" );
469 summary.append( "Builds Passing: " ).append( includedPoms.length - failures.size() ).append( "\n" );
470 summary.append( "Builds Failing: " ).append( failures.size() ).append( "\n" );
471 summary.append( "---------------------------------------\n" );
472
473 if ( !failures.isEmpty() )
474 {
475 summary.append( "\nThe following builds failed:\n" );
476
477 for ( final Iterator it = failures.iterator(); it.hasNext(); )
478 {
479 final String pom = ( String ) it.next();
480 summary.append( "\n* " ).append( pom );
481 }
482
483 summary.append( "\n" );
484 }
485
486 getLog().info( summary.toString() );
487 }
488
489 if ( !failures.isEmpty() )
490 {
491 String message = failures.size() + " builds failed.";
492
493 throw new MojoFailureException( this, message, message );
494 }
495 }
496
497
498
499
500
501
502
503
504 private Reader newReader( File file )
505 throws IOException
506 {
507 if ( StringUtils.isNotEmpty( encoding ) )
508 {
509 return ReaderFactory.newReader( file, encoding );
510 }
511 else
512 {
513 return ReaderFactory.newPlatformReader( file );
514 }
515 }
516
517 private void cloneProjects( String[] includedPoms )
518 throws IOException
519 {
520 List clonedSubpaths = new ArrayList();
521
522 for ( int i = 0; i < includedPoms.length; i++ )
523 {
524 String subpath = includedPoms[i];
525 int lastSep = subpath.lastIndexOf( File.separator );
526
527 if ( lastSep > -1 )
528 {
529 subpath = subpath.substring( 0, lastSep );
530 }
531 else
532 {
533 subpath = ".";
534 }
535
536
537 if ( !alreadyCloned( subpath, clonedSubpaths ) )
538 {
539
540 if ( ".".equals( subpath ) )
541 {
542 String cloneSubdir = normalizePath( cloneProjectsTo, projectsDirectory.getCanonicalPath() );
543
544
545 if ( cloneSubdir != null )
546 {
547 File temp = File.createTempFile( "pre-invocation-clone.", "" );
548 temp.delete();
549 temp.mkdirs();
550
551 copyDirectoryStructure( projectsDirectory, temp );
552
553 FileUtils.deleteDirectory( new File( temp, cloneSubdir ) );
554
555 copyDirectoryStructure( temp, cloneProjectsTo );
556 }
557 else
558 {
559 copyDirectoryStructure( projectsDirectory, cloneProjectsTo );
560 }
561 }
562 else
563 {
564 copyDirectoryStructure( new File( projectsDirectory, subpath ), new File( cloneProjectsTo,
565 subpath ) );
566 }
567
568 clonedSubpaths.add( subpath );
569 }
570 }
571 }
572
573
574
575
576
577
578
579
580 private void copyDirectoryStructure( File sourceDir, File destDir ) throws IOException
581 {
582 DirectoryScanner scanner = new DirectoryScanner();
583 scanner.setBasedir( sourceDir );
584 if ( ! cloneAllFiles )
585 {
586 scanner.addDefaultExcludes();
587 }
588 scanner.scan();
589
590 String [] includedFiles = scanner.getIncludedFiles();
591 for ( int i = 0; i < includedFiles.length; ++i )
592 {
593 File sourceFile = new File( sourceDir, includedFiles[ i ] );
594 File destFile = new File( destDir, includedFiles[ i ] );
595 FileUtils.copyFile( sourceFile, destFile );
596 }
597 }
598
599 static boolean alreadyCloned( String subpath, List clonedSubpaths )
600 {
601 for ( Iterator iter = clonedSubpaths.iterator(); iter.hasNext(); )
602 {
603 String path = (String) iter.next();
604
605 if ( ".".equals( path ) || subpath.equals( path ) || subpath.startsWith( path + File.separator ) )
606 {
607 return true;
608 }
609 }
610
611 return false;
612 }
613
614 private void runBuild( final File projectsDir, final String pom, final List failures )
615 throws MojoExecutionException
616 {
617
618 File pomFile = new File( projectsDir, pom );
619 final File basedir = pomFile.getParentFile();
620 File interpolatedPomFile = buildInterpolatedFile( pomFile, basedir, "interpolated-pom.xml" );
621 FileLogger logger = null;
622 try
623 {
624 getLog().info( "Building: " + pom );
625
626 final File outputLog = new File( basedir, "build.log" );
627
628 final Properties invokerProperties = getInvokerProperties( basedir );
629 if ( getLog().isDebugEnabled() && !invokerProperties.isEmpty() )
630 {
631 getLog().debug( "Using invoker properties:" );
632 for ( Iterator it = new TreeSet( invokerProperties.keySet() ).iterator(); it.hasNext(); )
633 {
634 String key = (String) it.next();
635 String value = invokerProperties.getProperty( key );
636 getLog().debug( " " + key + " = " + value );
637 }
638 }
639
640 if ( !noLog )
641 {
642 outputLog.getParentFile().mkdirs();
643
644 try
645 {
646 if ( streamLogs )
647 {
648 logger = new FileLogger( outputLog, getLog() );
649 }
650 else
651 {
652 logger = new FileLogger( outputLog );
653 }
654
655 getLog().debug( "build log initialized in: " + outputLog );
656 }
657 catch ( final IOException e )
658 {
659 getLog().debug( "Error initializing build logfile in: " + outputLog, e );
660 getLog().info( "...FAILED[could not initialize logfile in: " + outputLog + "]" );
661
662 failures.add( pom );
663
664 return;
665 }
666 }
667
668 if ( !prebuild( basedir, interpolatedPomFile, failures, logger ) )
669 {
670 getLog().info( "...FAILED[pre-build script returned false]" );
671
672 failures.add( pom );
673
674 return;
675 }
676
677 final InvocationRequest request = new DefaultInvocationRequest();
678
679 final List invocationGoals = getGoals( basedir );
680
681 if ( ( invocationGoals.size() == 1 ) && "_default".equals( invocationGoals.get( 0 ) ) )
682 {
683 getLog().debug( "Executing default goal for project in: " + pom );
684 }
685 else
686 {
687 getLog().debug( "Executing goals: " + invocationGoals + " for project in: " + pom );
688
689 request.setGoals( invocationGoals );
690 }
691
692 try
693 {
694 Properties collectedTestProperties = new Properties();
695
696 if ( testProperties != null )
697 {
698 collectedTestProperties.putAll( testProperties );
699 }
700
701 if ( properties != null )
702 {
703 collectedTestProperties.putAll( properties );
704 }
705
706 final Properties loadedProperties = loadTestProperties( basedir );
707
708 if ( loadedProperties != null )
709 {
710 collectedTestProperties.putAll( loadedProperties );
711 }
712
713 request.setProperties( collectedTestProperties );
714 }
715 catch ( final IOException e )
716 {
717 getLog().debug( "Error reading test-properties file in: " + testPropertiesFile, e );
718 getLog().info( "...FAILED[error reading test properties in: " + testPropertiesFile + "]" );
719
720 failures.add( pom );
721
722 return;
723 }
724
725 if ( localRepositoryPath != null )
726 {
727 File localRepoDir = localRepositoryPath;
728
729 getLog().debug( "Using local repository: " + localRepoDir );
730
731 if ( ! localRepositoryPath.exists() )
732 {
733 localRepositoryPath.mkdirs();
734 }
735
736 request.setLocalRepositoryDirectory( localRepoDir );
737 }
738
739 request.setInteractive( false );
740
741 request.setShowErrors( showErrors );
742
743 request.setDebug( debug );
744
745 request.setBaseDirectory( basedir );
746
747 if ( !noLog )
748 {
749 request.setErrorHandler( logger );
750
751 request.setOutputHandler( logger );
752 }
753
754 request.setPomFile( interpolatedPomFile );
755
756 request.setProfiles( getProfiles( basedir ) );
757
758 if ( settingsFile != null )
759 {
760 buildInterpolatedFile( settingsFile, settingsFile.getParentFile(), settingsFile.getName()
761 + ".interpolated" );
762 request.setUserSettingsFile( new File( settingsFile.getParentFile(), settingsFile.getName()
763 + ".interpolated" ) );
764 }
765
766 request.setMavenOpts( mavenOpts );
767
768 configureInvocation( request, invokerProperties );
769
770 try
771 {
772 getLog().debug( "Using MAVEN_OPTS: " + request.getMavenOpts() );
773 getLog().debug( "Executing: " + new MavenCommandLineBuilder().build( request ) );
774 }
775 catch ( CommandLineConfigurationException e )
776 {
777 getLog().debug( "Failed to display command line: " + e.getMessage() );
778 }
779
780 InvocationResult result = null;
781
782 try
783 {
784 result = invoker.execute( request );
785 }
786 catch ( final MavenInvocationException e )
787 {
788 getLog().debug( "Error invoking Maven: " + e.getMessage(), e );
789 getLog().info( "...FAILED[error invoking Maven]" );
790
791 failures.add( pom );
792
793 return;
794 }
795
796 final CommandLineException executionException = result.getExecutionException();
797 final boolean nonZeroExit =
798 "failure".equalsIgnoreCase( invokerProperties.getProperty( "invoker.buildResult" ) );
799
800 if ( executionException != null )
801 {
802 if ( !suppressSummaries )
803 {
804 StringBuffer buffer = new StringBuffer( 256 );
805 buffer.append( "...FAILED. " );
806 if ( !noLog )
807 {
808 buffer.append( "See " ).append( outputLog.getAbsolutePath() ).append( " for details." );
809 }
810 else
811 {
812 buffer.append( "See console output for details." );
813 }
814 getLog().info( buffer.toString() );
815 }
816
817 failures.add( pom );
818 }
819 else if ( ( result.getExitCode() != 0 ) != nonZeroExit )
820 {
821 if ( !suppressSummaries )
822 {
823 StringBuffer buffer = new StringBuffer( 256 );
824 buffer.append( "...FAILED[code=" ).append( result.getExitCode() ).append( "]. " );
825 if ( !noLog )
826 {
827 buffer.append( "See " ).append( outputLog.getAbsolutePath() ).append( " for details." );
828 }
829 else
830 {
831 buffer.append( "See console output for details." );
832 }
833 getLog().info( buffer.toString() );
834 }
835
836 failures.add( pom );
837 }
838 else if ( !verify( basedir, interpolatedPomFile, failures, logger ) )
839 {
840 if ( !suppressSummaries )
841 {
842 getLog().info( "...FAILED[verify script returned false]." );
843 }
844
845 failures.add( pom );
846 }
847 else if ( !suppressSummaries )
848 {
849 getLog().info( "...SUCCESS." );
850 }
851 }
852 finally
853 {
854 if ( logger != null )
855 {
856 logger.close();
857 }
858 }
859 }
860
861 private Properties loadTestProperties( final File basedir )
862 throws IOException
863 {
864 final Properties testProps = new Properties();
865
866 if ( testPropertiesFile != null )
867 {
868 final File testProperties = new File( basedir, testPropertiesFile );
869
870 if ( testProperties.exists() )
871 {
872 InputStream fin = null;
873 try
874 {
875 fin = new FileInputStream( testProperties );
876
877 testProps.load( fin );
878 }
879 finally
880 {
881 IOUtil.close( fin );
882 }
883 }
884 }
885
886 return testProps;
887 }
888
889 private boolean verify( final File basedir, final File pom, final List failures, final FileLogger logger )
890 {
891 boolean result = true;
892
893 if ( postBuildHookScript != null )
894 {
895 try
896 {
897 result = runScript( "verification script", basedir, postBuildHookScript, logger );
898 }
899 catch ( final IOException e )
900 {
901 result = false;
902 }
903 catch ( final EvalError e )
904 {
905 String errorMessage = "error evaluating script " + basedir.getPath() + File.separatorChar
906 + postBuildHookScript + ", " + e.getMessage();
907 getLog().error( errorMessage, e );
908 result = false;
909 }
910 }
911
912 return result;
913 }
914
915 private boolean runScript( final String scriptDescription, final File basedir, final String relativeScriptPath,
916 final FileLogger logger )
917 throws IOException, EvalError
918 {
919 final File script = new File( basedir, relativeScriptPath );
920
921 boolean scriptResult = false;
922
923 if ( script.exists() )
924 {
925 final Interpreter engine = new Interpreter();
926
927 if ( addTestClassPath )
928 {
929 getLog().debug( "Adding test class path to BeanShell interpreter:" );
930 try
931 {
932 List testClassPath = project.getTestClasspathElements();
933 for ( Iterator it = testClassPath.iterator(); it.hasNext(); )
934 {
935 String path = (String) it.next();
936 getLog().debug( " " + path );
937 engine.getClassManager().addClassPath( new File( path ).toURI().toURL() );
938 }
939 }
940 catch ( Exception e )
941 {
942 getLog().error( "Failed to add test class path to BeanShell interpreter", e );
943 }
944 }
945
946 PrintStream origOut = System.out;
947 PrintStream origErr = System.err;
948
949 Reader reader = null;
950 try
951 {
952 if ( !noLog )
953 {
954 logger.consumeLine( "Running " + scriptDescription + " in: " + script );
955
956 System.setErr( logger.getPrintStream() );
957 System.setOut( logger.getPrintStream() );
958
959 engine.setErr( logger.getPrintStream() );
960 engine.setOut( logger.getPrintStream() );
961 }
962
963 engine.set( "basedir", basedir );
964
965 reader = newReader( script );
966
967 final Object result = engine.eval( reader );
968
969 scriptResult = Boolean.TRUE.equals( result ) || "true".equals( result );
970 }
971 finally
972 {
973 IOUtil.close( reader );
974 System.setErr( origErr );
975 System.setOut( origOut );
976 }
977
978 if ( !noLog )
979 {
980 logger.consumeLine( "Finished " + scriptDescription + " in: " + script );
981 }
982 }
983 else
984 {
985 scriptResult = true;
986 }
987
988 return scriptResult;
989 }
990
991 private boolean prebuild( final File basedir, final File pom, final List failures, final FileLogger logger )
992 {
993 boolean result = true;
994
995 if ( preBuildHookScript != null )
996 {
997 try
998 {
999 result = runScript( "pre-build script", basedir, preBuildHookScript, logger );
1000 }
1001 catch ( final IOException e )
1002 {
1003 result = false;
1004 }
1005 catch ( final EvalError e )
1006 {
1007 String errorMessage = "error evaluating script " + basedir.getPath() + File.separatorChar
1008 + postBuildHookScript + ", " + e.getMessage();
1009 getLog().error( errorMessage, e );
1010 result = false;
1011 }
1012 }
1013
1014 return result;
1015 }
1016
1017 protected List getGoals( final File basedir )
1018 {
1019 List invocationGoals = goals;
1020
1021 if ( goalsFile != null )
1022 {
1023 final File projectGoalList = new File( basedir, goalsFile );
1024
1025 if ( projectGoalList.exists() )
1026 {
1027 final List goals = readFromFile( projectGoalList );
1028
1029 if ( ( goals != null ) && !goals.isEmpty() )
1030 {
1031 getLog().debug( "Using goals specified in file: " + projectGoalList );
1032 invocationGoals = goals;
1033 }
1034 }
1035 }
1036
1037 return invocationGoals;
1038 }
1039
1040 protected String[] getPoms()
1041 throws IOException
1042 {
1043 String[] poms;
1044
1045 if ( ( pom != null ) && pom.exists() )
1046 {
1047 poms = new String[]{ pom.getAbsolutePath() };
1048 }
1049 else if ( invokerTest != null )
1050 {
1051 String[] testRegexes = StringUtils.split( invokerTest, "," );
1052 List
1053
1054 for ( int i = 0, size = testRegexes.length; i < size; i++ )
1055 {
1056
1057 includes.add( testRegexes[i].endsWith( "pom.xml" ) ? testRegexes[i] : testRegexes[i]
1058 + File.separatorChar + "pom.xml" );
1059 }
1060
1061 final FileSet fs = new FileSet();
1062
1063 fs.setIncludes( includes );
1064
1065 fs.setDirectory( projectsDirectory.getCanonicalPath() );
1066 fs.setFollowSymlinks( false );
1067 fs.setUseDefaultExcludes( false );
1068
1069 final FileSetManager fsm = new FileSetManager( getLog() );
1070
1071 poms = fsm.getIncludedFiles( fs );
1072 }
1073 else
1074 {
1075 final FileSet fs = new FileSet();
1076
1077 fs.setIncludes( pomIncludes );
1078 fs.setExcludes( pomExcludes );
1079 fs.setDirectory( projectsDirectory.getCanonicalPath() );
1080 fs.setFollowSymlinks( false );
1081 fs.setUseDefaultExcludes( false );
1082
1083 final FileSetManager fsm = new FileSetManager( getLog() );
1084
1085 poms = fsm.getIncludedFiles( fs );
1086 }
1087
1088 poms = normalizePomPaths( poms );
1089
1090 return poms;
1091 }
1092
1093 private String[] normalizePomPaths( String[] poms )
1094 throws IOException
1095 {
1096 String projectsDirPath = projectsDirectory.getCanonicalPath();
1097
1098 String[] results = new String[poms.length];
1099 for ( int i = 0; i < poms.length; i++ )
1100 {
1101 String pomPath = poms[i];
1102
1103 File pom = new File( pomPath );
1104
1105 if ( !pom.isAbsolute() )
1106 {
1107 pom = new File( projectsDirectory, pomPath );
1108 }
1109
1110 String normalizedPath = normalizePath( pom, projectsDirPath );
1111
1112 if ( normalizedPath == null )
1113 {
1114 normalizedPath = pomPath;
1115 }
1116
1117 results[i] = normalizedPath;
1118 }
1119
1120 return results;
1121 }
1122
1123 private String normalizePath( File path, String withinDirPath )
1124 throws IOException
1125 {
1126 String normalizedPath = path.getCanonicalPath();
1127
1128 if ( normalizedPath.startsWith( withinDirPath ) )
1129 {
1130 normalizedPath = normalizedPath.substring( withinDirPath.length() );
1131 if ( normalizedPath.startsWith( File.separator ) )
1132 {
1133 normalizedPath = normalizedPath.substring( File.separator.length() );
1134 }
1135
1136 return normalizedPath;
1137 }
1138 else
1139 {
1140 return null;
1141 }
1142 }
1143
1144 private List readFromFile( final File projectGoalList )
1145 {
1146 BufferedReader reader = null;
1147
1148 List result = null;
1149
1150 try
1151 {
1152 Map composite = new CompositeMap( this.project, this.interpolationsProperties );
1153 reader = new BufferedReader( new InterpolationFilterReader( newReader( projectGoalList ), composite ) );
1154
1155 result = new ArrayList();
1156
1157 String line = null;
1158 while ( ( line = reader.readLine() ) != null )
1159 {
1160 result.addAll( collectListFromCSV( line ) );
1161 }
1162 }
1163 catch ( final IOException e )
1164 {
1165 getLog().warn(
1166 "Failed to load goal list from file: " + projectGoalList
1167 + ". Using 'goal' parameter configured on this plugin instead." );
1168 getLog().debug( "Error reading goals file: " + projectGoalList, e );
1169 }
1170 finally
1171 {
1172 IOUtil.close( reader );
1173 }
1174
1175 return result;
1176 }
1177
1178 private List collectListFromCSV( final String csv )
1179 {
1180 final List result = new ArrayList();
1181
1182 if ( ( csv != null ) && ( csv.trim().length() > 0 ) )
1183 {
1184 final StringTokenizer st = new StringTokenizer( csv, "," );
1185
1186 while ( st.hasMoreTokens() )
1187 {
1188 result.add( st.nextToken().trim() );
1189 }
1190 }
1191
1192 return result;
1193 }
1194
1195 protected File buildInterpolatedFile( File originalFile, File targetDirectory, String targetFileName )
1196 throws MojoExecutionException
1197 {
1198 File interpolatedFile = new File( targetDirectory, targetFileName );
1199 if ( interpolatedFile.exists() )
1200 {
1201 interpolatedFile.delete();
1202 }
1203 interpolatedFile.deleteOnExit();
1204 if ( settings.getLocalRepository() != null )
1205 {
1206 if ( this.interpolationsProperties == null )
1207 {
1208 this.interpolationsProperties = new Properties();
1209 }
1210 this.interpolationsProperties.put( "localRepository", settings.getLocalRepository() );
1211 }
1212 Map composite = new CompositeMap( this.project, this.interpolationsProperties );
1213
1214 try
1215 {
1216 boolean created = interpolatedFile.createNewFile();
1217 if ( !created )
1218 {
1219 throw new MojoExecutionException( "fail to create file " + interpolatedFile.getPath() );
1220 }
1221 }
1222 catch ( IOException e )
1223 {
1224 throw new MojoExecutionException( "fail to create file " + interpolatedFile.getPath() );
1225 }
1226 getLog().debug( "interpolate it pom to create interpolated in " + interpolatedFile.getPath() );
1227
1228 BufferedReader reader = null;
1229 Writer writer = null;
1230 try
1231 {
1232
1233 reader = new BufferedReader( new InterpolationFilterReader( ReaderFactory.newXmlReader( originalFile ),
1234 composite, "@", "@" ) );
1235 writer = WriterFactory.newXmlWriter( interpolatedFile );
1236 String line = null;
1237 while ( ( line = reader.readLine() ) != null )
1238 {
1239 writer.write( line );
1240 }
1241 writer.flush();
1242 }
1243 catch ( IOException e )
1244 {
1245 String message = "error when interpolating it pom";
1246 throw new MojoExecutionException( message, e );
1247 }
1248 finally
1249 {
1250
1251 IOUtil.close( reader );
1252 IOUtil.close( writer );
1253 }
1254
1255 if ( interpolatedFile == null )
1256 {
1257
1258 throw new MojoExecutionException( "pom file is null after interpolation" );
1259 }
1260 return interpolatedFile;
1261 }
1262
1263 protected List getProfiles( File projectDirectory )
1264 throws MojoExecutionException
1265 {
1266 if ( profilesFile == null )
1267 {
1268 return profiles == null ? Collections.EMPTY_LIST : profiles;
1269 }
1270 File projectProfilesFile = new File( projectDirectory, profilesFile );
1271 if ( !projectProfilesFile.exists() )
1272 {
1273 return profiles == null ? Collections.EMPTY_LIST : profiles;
1274 }
1275 BufferedReader reader = null;
1276 try
1277 {
1278 List profilesInFiles = new ArrayList();
1279 reader = new BufferedReader( newReader( projectProfilesFile ) );
1280 String line = null;
1281 while ( ( line = reader.readLine() ) != null )
1282 {
1283 profilesInFiles.addAll( collectListFromCSV( line ) );
1284 }
1285 return profilesInFiles;
1286 }
1287 catch ( FileNotFoundException e )
1288 {
1289
1290 throw new MojoExecutionException( projectProfilesFile + " not found ", e );
1291 }
1292 catch ( IOException e )
1293 {
1294 throw new MojoExecutionException( "error reading profile in file " + projectProfilesFile + " not found ",
1295 e );
1296 }
1297 finally
1298 {
1299 IOUtil.close( reader );
1300 }
1301 }
1302
1303
1304
1305
1306
1307
1308
1309
1310 private Properties getInvokerProperties( final File projectDirectory )
1311 throws MojoExecutionException
1312 {
1313 Properties props = new Properties();
1314 if ( invokerPropertiesFile != null )
1315 {
1316 File propertiesFile = new File( projectDirectory, invokerPropertiesFile );
1317 if ( propertiesFile.isFile() )
1318 {
1319 InputStream in = null;
1320 try
1321 {
1322 in = new FileInputStream( propertiesFile );
1323 props.load( in );
1324 }
1325 catch ( IOException e )
1326 {
1327 throw new MojoExecutionException( "Failed to read invoker properties: " + propertiesFile, e );
1328 }
1329 finally
1330 {
1331 IOUtil.close( in );
1332 }
1333 }
1334
1335 Map filter = new CompositeMap( project, this.interpolationsProperties );
1336 Interpolator interpolator = new RegexBasedInterpolator();
1337 interpolator.addValueSource( new MapBasedValueSource( filter ) );
1338 for ( Iterator it = props.keySet().iterator(); it.hasNext(); )
1339 {
1340 String key = (String) it.next();
1341 String value = props.getProperty( key );
1342 try
1343 {
1344 value = interpolator.interpolate( value, "" );
1345 }
1346 catch ( InterpolationException e )
1347 {
1348 throw new MojoExecutionException( "Failed to interpolate invoker properties: " + propertiesFile,
1349 e );
1350 }
1351 props.setProperty( key, value );
1352 }
1353 }
1354 return props;
1355 }
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365 private InvocationRequest configureInvocation( InvocationRequest request, Properties properties )
1366 {
1367 String goals = properties.getProperty( "invoker.goals" );
1368 if ( goals != null )
1369 {
1370 request.setGoals( new ArrayList( Arrays.asList( goals.split( "[,\\s]+" ) ) ) );
1371 }
1372
1373 String profiles = properties.getProperty( "invoker.profiles" );
1374 if ( profiles != null )
1375 {
1376 request.setProfiles( new ArrayList( Arrays.asList( profiles.split( "[,\\s]+" ) ) ) );
1377 }
1378
1379 String opts = properties.getProperty( "invoker.mavenOpts" );
1380 if ( opts != null )
1381 {
1382 request.setMavenOpts( opts );
1383 }
1384
1385 String failureBehavior = properties.getProperty( "invoker.failureBehavior" );
1386 if ( failureBehavior != null )
1387 {
1388 request.setFailureBehavior( failureBehavior );
1389 }
1390
1391 String nonRecursive = properties.getProperty( "invoker.nonRecursive" );
1392 if ( nonRecursive != null )
1393 {
1394 request.setRecursive( !Boolean.valueOf( nonRecursive ).booleanValue() );
1395 }
1396
1397 return request;
1398 }
1399
1400 }