1 package org.codehaus.mojo.exec;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.BufferedOutputStream;
23 import java.io.File;
24 import java.io.FileOutputStream;
25 import java.io.FileWriter;
26 import java.io.IOException;
27 import java.io.OutputStream;
28 import java.io.PrintWriter;
29 import java.net.URL;
30 import java.nio.file.Path;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collection;
34 import java.util.HashMap;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Properties;
39 import java.util.Set;
40 import java.util.TreeSet;
41 import java.util.function.Consumer;
42 import java.util.jar.JarEntry;
43 import java.util.jar.JarOutputStream;
44 import java.util.jar.Manifest;
45
46 import org.apache.commons.exec.CommandLine;
47 import org.apache.commons.exec.ExecuteException;
48 import org.apache.commons.exec.ExecuteResultHandler;
49 import org.apache.commons.exec.ExecuteWatchdog;
50 import org.apache.commons.exec.Executor;
51 import org.apache.commons.exec.OS;
52 import org.apache.commons.exec.ProcessDestroyer;
53 import org.apache.commons.exec.PumpStreamHandler;
54 import org.apache.commons.exec.ShutdownHookProcessDestroyer;
55 import org.apache.maven.artifact.Artifact;
56 import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
57 import org.apache.maven.artifact.resolver.filter.IncludesArtifactFilter;
58 import org.apache.maven.execution.MavenSession;
59 import org.apache.maven.plugin.MojoExecutionException;
60 import org.apache.maven.plugins.annotations.Mojo;
61 import org.apache.maven.plugins.annotations.Parameter;
62 import org.apache.maven.plugins.annotations.ResolutionScope;
63 import org.apache.maven.project.MavenProject;
64 import org.apache.maven.toolchain.Toolchain;
65 import org.apache.maven.toolchain.ToolchainManager;
66 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
67 import org.codehaus.plexus.util.IOUtil;
68 import org.codehaus.plexus.util.StringUtils;
69 import org.codehaus.plexus.util.cli.CommandLineException;
70 import org.codehaus.plexus.util.cli.CommandLineUtils;
71 import org.codehaus.plexus.util.cli.Commandline;
72 import org.codehaus.plexus.util.cli.DefaultConsumer;
73 import org.codehaus.plexus.util.cli.StreamConsumer;
74
75
76
77
78
79
80
81
82 @Mojo( name = "exec", threadSafe = true, requiresDependencyResolution = ResolutionScope.TEST )
83 public class ExecMojo
84 extends AbstractExecMojo
85 {
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 @Parameter( property = "exec.executable" )
105 private String executable;
106
107
108
109
110
111
112
113
114
115
116
117
118
119 @Parameter( property = "exec.timeout", defaultValue = "0" )
120 private int timeout;
121
122
123
124
125
126
127 @Parameter( property = "exec.toolchain", defaultValue = "jdk" )
128 private String toolchain;
129
130
131
132
133
134
135 @Parameter( property = "exec.workingdir" )
136 private File workingDirectory;
137
138
139
140
141
142
143
144
145
146
147
148 @Parameter( property = "exec.outputFile" )
149 private File outputFile;
150
151
152
153
154
155
156
157
158 @Parameter( property = "exec.inheritIo" )
159 private boolean inheritIo;
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224 @Parameter( property = "exec.useMavenLogger", defaultValue = "false" )
225 private boolean useMavenLogger;
226
227
228
229
230
231
232
233
234 @Parameter( property = "exec.quietLogs", defaultValue = "false" )
235 private boolean quietLogs;
236
237
238
239
240
241
242
243
244
245 @Parameter
246 private List<?> arguments;
247
248
249
250
251 @Parameter( readonly = true, required = true, defaultValue = "${basedir}" )
252 private File basedir;
253
254
255
256
257 @Parameter( readonly = true, required = true, defaultValue = "${project.build.directory}" )
258 private File buildDirectory;
259
260
261
262
263
264
265
266
267
268
269
270 @Parameter
271 private Map<String, String> environmentVariables = new HashMap<String, String>();
272
273
274
275
276
277
278
279
280 @Parameter
281 private File environmentScript = null;
282
283
284
285
286 @Parameter( defaultValue = "${session}", readonly = true )
287 private MavenSession session;
288
289
290
291
292
293
294
295 @Parameter
296 private int[] successCodes;
297
298
299
300
301
302
303
304 @Parameter( property = "exec.longClasspath", defaultValue = "false" )
305 private boolean longClasspath;
306
307
308
309
310
311
312
313 @Parameter( property = "exec.longModulepath", defaultValue = "true" )
314 private boolean longModulepath;
315
316
317
318
319 @Parameter( property = "exec.async", defaultValue = "false" )
320 private boolean async;
321
322
323
324
325
326
327 @Parameter( property = "exec.asyncDestroyOnShutdown", defaultValue = "true" )
328 private boolean asyncDestroyOnShutdown = true;
329
330 public static final String CLASSPATH_TOKEN = "%classpath";
331
332 public static final String MODULEPATH_TOKEN = "%modulepath";
333
334
335
336
337
338
339 public void execute()
340 throws MojoExecutionException
341 {
342 if ( executable == null )
343 {
344 if (executableDependency == null)
345 {
346 throw new MojoExecutionException( "The parameter 'executable' is missing or invalid" );
347 }
348
349 executable = findExecutableArtifact().getFile().getAbsolutePath();
350 getLog().debug( "using executable dependency " + executable);
351 }
352
353 if ( isSkip() )
354 {
355 getLog().info( "skipping execute as per configuration" );
356 return;
357 }
358
359 if ( basedir == null )
360 {
361 throw new IllegalStateException( "basedir is null. Should not be possible." );
362 }
363
364 try
365 {
366
367 handleWorkingDirectory();
368
369 String argsProp = getSystemProperty( "exec.args" );
370
371 List<String> commandArguments = new ArrayList<String>();
372
373 if ( hasCommandlineArgs() )
374 {
375 handleCommandLineArgs( commandArguments );
376 }
377 else if ( !StringUtils.isEmpty( argsProp ) )
378 {
379 handleSystemPropertyArguments( argsProp, commandArguments );
380 }
381 else
382 {
383 if ( arguments != null )
384 {
385 handleArguments( commandArguments );
386 }
387 }
388
389 Map<String, String> enviro = handleSystemEnvVariables();
390
391 CommandLine commandLine = getExecutablePath( enviro, workingDirectory );
392
393 String[] args = commandArguments.toArray( new String[commandArguments.size()] );
394
395 commandLine.addArguments( args, false );
396
397 Executor exec = new ExtendedExecutor( inheritIo );
398 if ( this.timeout > 0 )
399 {
400 exec.setWatchdog( new ExecuteWatchdog( this.timeout ) );
401 }
402 exec.setWorkingDirectory( workingDirectory );
403 fillSuccessCodes( exec );
404
405 if ( OS.isFamilyOpenVms() && inheritIo )
406 {
407 getLog().warn("The inheritIo flag is not supported on OpenVMS, execution will proceed without stream inheritance.");
408 }
409 getLog().debug( "Executing command line: " + commandLine );
410
411 try
412 {
413 int resultCode;
414 if ( outputFile != null )
415 {
416 if ( !outputFile.getParentFile().exists() && !outputFile.getParentFile().mkdirs() )
417 {
418 getLog().warn( "Could not create non existing parent directories for log file: " + outputFile );
419 }
420
421 FileOutputStream outputStream = null;
422 try
423 {
424 outputStream = new FileOutputStream( outputFile );
425
426 resultCode = executeCommandLine( exec, commandLine, enviro, outputStream );
427 }
428 finally
429 {
430 IOUtil.close( outputStream );
431 }
432 }
433 else if (useMavenLogger)
434 {
435 getLog().debug("Will redirect program output to Maven logger");
436 final String parentThreadName = Thread.currentThread().getName();
437 final String logSuffix = "[" + parentThreadName + "] ";
438 Consumer<String> mavenOutRedirect = new Consumer<String>()
439 {
440
441 @Override
442 public void accept(String logMessage)
443 {
444 if (quietLogs)
445 {
446 getLog().debug(logSuffix + logMessage);
447 }
448 else
449 {
450 getLog().info(logSuffix + logMessage);
451 }
452 }
453 };
454 Consumer<String> mavenErrRedirect = new Consumer<String>()
455 {
456
457 @Override
458 public void accept(String logMessage)
459 {
460 getLog().error(logSuffix + logMessage);
461 }
462 };
463
464 try (OutputStream out = new LineRedirectOutputStream(mavenOutRedirect);
465 OutputStream err = new LineRedirectOutputStream(mavenErrRedirect)) {
466 resultCode = executeCommandLine(exec, commandLine, enviro, out, err);
467 }
468 }
469 else
470 {
471 resultCode = executeCommandLine( exec, commandLine, enviro, System.out, System.err );
472 }
473
474 if ( isResultCodeAFailure( resultCode ) )
475 {
476 String message = "Result of " + commandLine.toString() + " execution is: '" + resultCode + "'.";
477 getLog().error( message );
478 throw new MojoExecutionException( message );
479 }
480 }
481 catch ( ExecuteException e )
482 {
483 if ( exec.getWatchdog() != null && exec.getWatchdog().killedProcess() )
484 {
485 final String message = "Timeout. Process runs longer than " + this.timeout + " ms.";
486 getLog().error( message );
487 throw new MojoExecutionException( message, e );
488 }
489 else
490 {
491 getLog().error( "Command execution failed.", e );
492 throw new MojoExecutionException( "Command execution failed.", e );
493 }
494 }
495 catch ( IOException e )
496 {
497 getLog().error( "Command execution failed.", e );
498 throw new MojoExecutionException( "Command execution failed.", e );
499 }
500
501 registerSourceRoots();
502 }
503 catch ( IOException e )
504 {
505 throw new MojoExecutionException( "I/O Error", e );
506 }
507 }
508
509 private Map<String, String> handleSystemEnvVariables()
510 throws MojoExecutionException
511 {
512
513 Map<String, String> enviro = new HashMap<String, String>();
514 try
515 {
516 Properties systemEnvVars = CommandLineUtils.getSystemEnvVars();
517 for ( Map.Entry<?, ?> entry : systemEnvVars.entrySet() )
518 {
519 enviro.put( (String) entry.getKey(), (String) entry.getValue() );
520 }
521 }
522 catch ( IOException x )
523 {
524 getLog().error( "Could not assign default system enviroment variables.", x );
525 }
526
527 if ( environmentVariables != null )
528 {
529 enviro.putAll( environmentVariables );
530 }
531
532 if ( this.environmentScript != null )
533 {
534 getLog().info( "Pick up external environment script: " + this.environmentScript );
535 Map<String, String> envVarsFromScript = this.createEnvs( this.environmentScript );
536 if ( envVarsFromScript != null )
537 {
538 enviro.putAll( envVarsFromScript );
539 }
540 }
541
542 if ( this.getLog().isDebugEnabled() )
543 {
544 Set<String> keys = new TreeSet<String>();
545 keys.addAll( enviro.keySet() );
546 for ( String key : keys )
547 {
548 this.getLog().debug( "env: " + key + "=" + enviro.get( key ) );
549 }
550 }
551
552 return enviro;
553 }
554
555
556
557
558
559
560
561
562 private void handleWorkingDirectory()
563 throws MojoExecutionException
564 {
565 if ( workingDirectory == null )
566 {
567 workingDirectory = basedir;
568 }
569
570 if ( !workingDirectory.exists() )
571 {
572 getLog().debug( "Making working directory '" + workingDirectory.getAbsolutePath() + "'." );
573 if ( !workingDirectory.mkdirs() )
574 {
575 throw new MojoExecutionException( "Could not make working directory: '"
576 + workingDirectory.getAbsolutePath() + "'" );
577 }
578 }
579 }
580
581 private void handleSystemPropertyArguments( String argsProp, List<String> commandArguments )
582 throws MojoExecutionException
583 {
584 getLog().debug( "got arguments from system properties: " + argsProp );
585
586 try
587 {
588 String[] args = CommandLineUtils.translateCommandline( argsProp );
589 commandArguments.addAll( Arrays.asList( args ) );
590 }
591 catch ( Exception e )
592 {
593 throw new MojoExecutionException( "Couldn't parse systemproperty 'exec.args'" );
594 }
595 }
596
597 private void handleCommandLineArgs( List<String> commandArguments )
598 throws MojoExecutionException, IOException
599 {
600 String[] args = parseCommandlineArgs();
601 for ( int i = 0; i < args.length; i++ )
602 {
603 if ( isLongClassPathArgument( args[i] ) )
604 {
605
606
607
608
609 commandArguments.add( "-jar" );
610 File tmpFile = createJar( computePath( null ), args[i + 2] );
611 commandArguments.add( tmpFile.getAbsolutePath() );
612 i += 2;
613 }
614 else if ( args[i].contains( CLASSPATH_TOKEN ) )
615 {
616 commandArguments.add( args[i].replace( CLASSPATH_TOKEN, computeClasspathString( null ) ) );
617 }
618 else
619 {
620 commandArguments.add( args[i] );
621 }
622 }
623 }
624
625 private void handleArguments( List<String> commandArguments )
626 throws MojoExecutionException, IOException
627 {
628 String specialArg = null;
629
630 for ( int i = 0; i < arguments.size(); i++ )
631 {
632 Object argument = arguments.get( i );
633
634 if ( specialArg != null )
635 {
636 if ( isLongClassPathArgument( specialArg ) && argument instanceof Classpath )
637 {
638
639
640
641
642 commandArguments.add( "-jar" );
643
644 File tmpFile = createJar( computePath( (Classpath) argument ),
645 (String) arguments.get( ++i ) );
646 commandArguments.add( tmpFile.getAbsolutePath() );
647 }
648 else if ( isLongModulePathArgument( specialArg ) && argument instanceof Modulepath )
649 {
650 String filePath = new File( buildDirectory, "modulepath" ).getAbsolutePath();
651
652 StringBuilder modulePath = new StringBuilder();
653 modulePath.append( '"' );
654
655 for ( Iterator<String> it = computePath( (Modulepath) argument ).iterator(); it.hasNext(); )
656 {
657 modulePath.append( it.next().replace( "\\", "\\\\" ) );
658 if ( it.hasNext() )
659 {
660 modulePath.append( File.pathSeparatorChar );
661 }
662 }
663
664 modulePath.append( '"' );
665
666 createArgFile( filePath, Arrays.asList( "-p", modulePath.toString() ) );
667 commandArguments.add( '@' + filePath );
668 }
669 else
670 {
671 commandArguments.add( specialArg );
672 }
673
674 specialArg = null;
675
676 continue;
677 }
678
679 if ( argument instanceof Classpath )
680 {
681 Classpath specifiedClasspath = (Classpath) argument;
682 commandArguments.add( computeClasspathString( specifiedClasspath ) );
683 }
684 else if ( argument instanceof Modulepath )
685 {
686 Modulepath specifiedModulepath = (Modulepath) argument;
687 commandArguments.add( computeClasspathString( specifiedModulepath ) );
688 }
689 else if ( (argument instanceof String) && (isLongModulePathArgument( (String) argument ) || isLongClassPathArgument( (String) argument )) )
690 {
691 specialArg = (String) argument;
692 }
693 else if (argument == null)
694 {
695 commandArguments.add( "" );
696 }
697 else
698 {
699 commandArguments.add( (String) argument );
700 }
701 }
702 }
703
704 private void fillSuccessCodes( Executor exec )
705 {
706 if ( successCodes != null && successCodes.length > 0 )
707 {
708 exec.setExitValues( successCodes );
709 }
710 }
711
712 boolean isResultCodeAFailure( int result )
713 {
714 if ( successCodes == null || successCodes.length == 0 )
715 {
716 return result != 0;
717 }
718 for ( int successCode : successCodes )
719 {
720 if ( successCode == result )
721 {
722 return false;
723 }
724 }
725 return true;
726 }
727
728 private boolean isLongClassPathArgument( String arg )
729 {
730 return longClasspath && ( "-classpath".equals( arg ) || "-cp".equals( arg ) );
731 }
732
733 private boolean isLongModulePathArgument( String arg )
734 {
735 return longModulepath && ( "--module-path".equals( arg ) || "-p".equals( arg ) );
736 }
737
738
739
740
741
742
743
744
745
746
747 private String computeClasspathString( AbstractPath specifiedClasspath )
748 {
749 List<String> resultList = computePath( specifiedClasspath );
750 StringBuffer theClasspath = new StringBuffer();
751
752 for ( String str : resultList )
753 {
754 addToClasspath( theClasspath, str );
755 }
756
757 return theClasspath.toString();
758 }
759
760
761
762
763
764
765
766
767
768
769 private List<String> computePath( AbstractPath specifiedClasspath )
770 {
771 List<Artifact> artifacts = new ArrayList<>();
772 List<Path> theClasspathFiles = new ArrayList<>();
773 List<String> resultList = new ArrayList<>();
774
775 collectProjectArtifactsAndClasspath( artifacts, theClasspathFiles );
776
777 if ( ( specifiedClasspath != null ) && ( specifiedClasspath.getDependencies() != null ) )
778 {
779 artifacts = filterArtifacts( artifacts, specifiedClasspath.getDependencies() );
780 }
781
782 for ( Path f : theClasspathFiles )
783 {
784 resultList.add( f.toAbsolutePath().toString() );
785 }
786
787 for ( Artifact artifact : artifacts )
788 {
789 getLog().debug( "dealing with " + artifact );
790 resultList.add( artifact.getFile().getAbsolutePath() );
791 }
792
793 return resultList;
794 }
795
796 private static void addToClasspath( StringBuffer theClasspath, String toAdd )
797 {
798 if ( theClasspath.length() > 0 )
799 {
800 theClasspath.append( File.pathSeparator );
801 }
802 theClasspath.append( toAdd );
803 }
804
805 private List<Artifact> filterArtifacts( List<Artifact> artifacts, Collection<String> dependencies )
806 {
807 AndArtifactFilter filter = new AndArtifactFilter();
808
809 filter.add( new IncludesArtifactFilter( new ArrayList<String>( dependencies ) ) );
810
811 List<Artifact> filteredArtifacts = new ArrayList<Artifact>();
812 for ( Artifact artifact : artifacts )
813 {
814 if ( filter.include( artifact ) )
815 {
816 getLog().debug( "filtering in " + artifact );
817 filteredArtifacts.add( artifact );
818 }
819 }
820 return filteredArtifacts;
821 }
822
823 private ProcessDestroyer processDestroyer;
824
825 CommandLine getExecutablePath( Map<String, String> enviro, File dir )
826 {
827 File execFile = new File( executable );
828 String exec = null;
829 if ( execFile.isFile() )
830 {
831 getLog().debug( "Toolchains are ignored, 'executable' parameter is set to " + executable );
832 exec = execFile.getAbsolutePath();
833 }
834
835 if ( exec == null )
836 {
837 Toolchain tc = getToolchain();
838
839
840
841
842 if ( tc != null )
843 {
844 getLog().info( "Toolchain in exec-maven-plugin: " + tc );
845 exec = tc.findTool( executable );
846 }
847 else
848 {
849 if ( OS.isFamilyWindows() )
850 {
851 List<String> paths = this.getExecutablePaths( enviro );
852 paths.add( 0, dir.getAbsolutePath() );
853
854 exec = findExecutable( executable, paths );
855 }
856 }
857 }
858
859 if ( exec == null )
860 {
861 exec = executable;
862 }
863
864 CommandLine toRet;
865 if ( OS.isFamilyWindows() && !hasNativeExtension( exec ) && hasExecutableExtension( exec ) )
866 {
867
868 final String comSpec = System.getenv( "ComSpec" );
869 toRet = new CommandLine( comSpec == null ? "cmd" : comSpec );
870 toRet.addArgument( "/c" );
871 toRet.addArgument( exec );
872 }
873 else
874 {
875 toRet = new CommandLine( exec );
876 }
877
878 return toRet;
879 }
880
881 static String findExecutable( final String executable, final List<String> paths )
882 {
883 File f = null;
884 search: for ( final String path : paths )
885 {
886 f = new File( path, executable );
887 if ( !OS.isFamilyWindows() && f.isFile() )
888 break;
889 else
890 for ( final String extension : getExecutableExtensions() )
891 {
892 f = new File( path, executable + extension );
893 if ( f.isFile() )
894 break search;
895 }
896 }
897
898 if ( f == null || !f.exists() )
899 return null;
900
901 return f.getAbsolutePath();
902 }
903
904 private static boolean hasNativeExtension( final String exec )
905 {
906 final String lowerCase = exec.toLowerCase();
907 return lowerCase.endsWith( ".exe" ) || lowerCase.endsWith( ".com" );
908 }
909
910 private static boolean hasExecutableExtension( final String exec )
911 {
912 final String lowerCase = exec.toLowerCase();
913 for ( final String ext : getExecutableExtensions() )
914 if ( lowerCase.endsWith( ext ) )
915 return true;
916
917 return false;
918 }
919
920 private static List<String> getExecutableExtensions()
921 {
922 final String pathExt = System.getenv( "PATHEXT" );
923 return pathExt == null ? Arrays.asList( ".bat", ".cmd" )
924 : Arrays.asList( StringUtils.split( pathExt.toLowerCase(), File.pathSeparator ) );
925 }
926
927 private List<String> getExecutablePaths( Map<String, String> enviro )
928 {
929 List<String> paths = new ArrayList<String>();
930 paths.add( "" );
931
932 String path = enviro.get( "PATH" );
933 if ( path != null )
934 {
935 paths.addAll( Arrays.asList( StringUtils.split( path, File.pathSeparator ) ) );
936 }
937
938 return paths;
939 }
940
941 protected int executeCommandLine( Executor exec, CommandLine commandLine, Map<String, String> enviro,
942 OutputStream out, OutputStream err )
943 throws ExecuteException, IOException
944 {
945
946 PumpStreamHandler psh = new PumpStreamHandler( out, err, System.in );
947 return executeCommandLine( exec, commandLine, enviro, psh );
948 }
949
950 protected int executeCommandLine( Executor exec, CommandLine commandLine, Map<String, String> enviro,
951 FileOutputStream outputFile )
952 throws ExecuteException, IOException
953 {
954 BufferedOutputStream bos = new BufferedOutputStream( outputFile );
955 PumpStreamHandler psh = new PumpStreamHandler( bos );
956 return executeCommandLine( exec, commandLine, enviro, psh );
957 }
958
959 protected int executeCommandLine( Executor exec, final CommandLine commandLine, Map<String, String> enviro,
960 final PumpStreamHandler psh )
961 throws ExecuteException, IOException
962 {
963 exec.setStreamHandler( psh );
964
965 int result;
966 try
967 {
968 psh.start();
969 if ( async )
970 {
971 if ( asyncDestroyOnShutdown )
972 {
973 exec.setProcessDestroyer( getProcessDestroyer() );
974 }
975
976 exec.execute( commandLine, enviro, new ExecuteResultHandler()
977 {
978 public void onProcessFailed( ExecuteException e )
979 {
980 getLog().error( "Async process failed for: " + commandLine, e );
981 }
982
983 public void onProcessComplete( int exitValue )
984 {
985 getLog().info( "Async process complete, exit value = " + exitValue + " for: " + commandLine );
986 try
987 {
988 psh.stop();
989 }
990 catch ( IOException e )
991 {
992 getLog().error( "Error stopping async process stream handler for: " + commandLine, e );
993 }
994 }
995 } );
996 result = 0;
997 }
998 else
999 {
1000 result = exec.execute( commandLine, enviro );
1001 }
1002 }
1003 finally
1004 {
1005 if ( !async )
1006 {
1007 psh.stop();
1008 }
1009 }
1010 return result;
1011 }
1012
1013
1014
1015
1016
1017 void setExecutable( String executable )
1018 {
1019 this.executable = executable;
1020 }
1021
1022 String getExecutable()
1023 {
1024 return executable;
1025 }
1026
1027 void setWorkingDirectory( String workingDir )
1028 {
1029 setWorkingDirectory( new File( workingDir ) );
1030 }
1031
1032 void setWorkingDirectory( File workingDir )
1033 {
1034 this.workingDirectory = workingDir;
1035 }
1036
1037 void setArguments( List<?> arguments )
1038 {
1039 this.arguments = arguments;
1040 }
1041
1042 void setBasedir( File basedir )
1043 {
1044 this.basedir = basedir;
1045 }
1046
1047 void setProject( MavenProject project )
1048 {
1049 this.project = project;
1050 }
1051
1052 protected String getSystemProperty( String key )
1053 {
1054 return System.getProperty( key );
1055 }
1056
1057 public void setSuccessCodes( Integer... list )
1058 {
1059 this.successCodes = new int[list.length];
1060 for ( int index = 0; index < list.length; index++ )
1061 {
1062 successCodes[index] = list[index];
1063 }
1064 }
1065
1066 public int[] getSuccessCodes()
1067 {
1068 return successCodes;
1069 }
1070
1071 private Toolchain getToolchain()
1072 {
1073 Toolchain tc = null;
1074
1075 try
1076 {
1077 if ( session != null )
1078 {
1079 ToolchainManager toolchainManager =
1080 (ToolchainManager) session.getContainer().lookup( ToolchainManager.ROLE );
1081
1082 if ( toolchainManager != null )
1083 {
1084 tc = toolchainManager.getToolchainFromBuildContext( toolchain, session );
1085 }
1086 }
1087 }
1088 catch ( ComponentLookupException componentLookupException )
1089 {
1090
1091 }
1092 return tc;
1093 }
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103 private File createJar( List<String> classPath, String mainClass )
1104 throws IOException
1105 {
1106 File file = File.createTempFile( "maven-exec", ".jar" );
1107 file.deleteOnExit();
1108 FileOutputStream fos = new FileOutputStream( file );
1109 JarOutputStream jos = new JarOutputStream( fos );
1110 jos.setLevel( JarOutputStream.STORED );
1111 JarEntry je = new JarEntry( "META-INF/MANIFEST.MF" );
1112 jos.putNextEntry( je );
1113
1114 Manifest man = new Manifest();
1115
1116
1117
1118 StringBuilder cp = new StringBuilder();
1119 for ( String el : classPath )
1120 {
1121
1122 cp.append( new URL( new File( el ).toURI().toASCIIString() ).toExternalForm() + " " );
1123 }
1124
1125 man.getMainAttributes().putValue( "Manifest-Version", "1.0" );
1126 man.getMainAttributes().putValue( "Class-Path", cp.toString().trim() );
1127 man.getMainAttributes().putValue( "Main-Class", mainClass );
1128
1129 man.write( jos );
1130 jos.close();
1131
1132 return file;
1133 }
1134
1135 private void createArgFile( String filePath, List<String> lines )
1136 throws IOException
1137 {
1138 final String EOL = System.getProperty( "line.separator", "\\n" );
1139
1140 FileWriter writer = null;
1141 try
1142 {
1143 writer = new FileWriter( filePath );
1144 for ( String line : lines )
1145 {
1146 writer.append( line ).append( EOL );
1147 }
1148
1149 }
1150 finally
1151 {
1152 IOUtil.close( writer );
1153 }
1154 }
1155
1156 protected Map<String, String> createEnvs( File envScriptFile )
1157 throws MojoExecutionException
1158 {
1159 Map<String, String> results = null;
1160
1161 File tmpEnvExecFile = null;
1162 try
1163 {
1164 tmpEnvExecFile = this.createEnvWrapperFile( envScriptFile );
1165
1166 Commandline cl = new Commandline();
1167 cl.setExecutable( tmpEnvExecFile.getAbsolutePath() );
1168 if ( !OS.isFamilyWindows() )
1169 {
1170 cl.setExecutable( "sh" );
1171 cl.createArg().setFile( tmpEnvExecFile );
1172 }
1173
1174
1175 if ( environmentVariables != null )
1176 {
1177 for ( Map.Entry<String, String> item : environmentVariables.entrySet() )
1178 {
1179 cl.addEnvironment( item.getKey(), item.getValue() );
1180 }
1181 }
1182
1183 EnvStreamConsumer stdout = new EnvStreamConsumer();
1184 StreamConsumer stderr = new DefaultConsumer();
1185
1186 CommandLineUtils.executeCommandLine( cl, stdout, stderr );
1187
1188 if(!stdout.getUnparsedLines().isEmpty())
1189 {
1190 getLog().warn( "The following lines could not be parsed into environment variables :" );
1191 for ( String line : stdout.getUnparsedLines() )
1192 {
1193 getLog().warn( line );
1194 }
1195 }
1196
1197 results = stdout.getParsedEnv();
1198 }
1199 catch ( CommandLineException e )
1200 {
1201 throw new MojoExecutionException( e.getMessage() );
1202 }
1203 catch ( IOException e )
1204 {
1205 throw new MojoExecutionException( e.getMessage() );
1206 }
1207 finally
1208 {
1209 if ( tmpEnvExecFile != null )
1210 {
1211 tmpEnvExecFile.delete();
1212 }
1213 }
1214
1215 return results;
1216
1217 }
1218
1219 protected File createEnvWrapperFile( File envScript )
1220 throws IOException
1221 {
1222 PrintWriter writer = null;
1223 File tmpFile = null;
1224 try
1225 {
1226
1227 if ( OS.isFamilyWindows() )
1228 {
1229 tmpFile = File.createTempFile( "env", ".bat" );
1230 writer = new PrintWriter( tmpFile );
1231 writer.append( "@echo off" ).println();
1232 writer.append( "call \"" ).append( envScript.getCanonicalPath() ).append( "\"" ).println();
1233 writer.append( "echo " + EnvStreamConsumer.START_PARSING_INDICATOR ).println();
1234 writer.append( "set" ).println();
1235 writer.flush();
1236 }
1237 else
1238 {
1239 tmpFile = File.createTempFile( "env", ".sh" );
1240
1241 writer = new PrintWriter( tmpFile );
1242 writer.append( "#! /bin/sh" ).println();
1243 writer.append( ". " ).append( envScript.getCanonicalPath() ).println();
1244 writer.append( "echo " + EnvStreamConsumer.START_PARSING_INDICATOR ).println();
1245 writer.append( "env" ).println();
1246 writer.flush();
1247 }
1248 }
1249 finally
1250 {
1251 IOUtil.close( writer );
1252 }
1253
1254 return tmpFile;
1255
1256 }
1257
1258 protected ProcessDestroyer getProcessDestroyer()
1259 {
1260 if ( processDestroyer == null )
1261 {
1262 processDestroyer = new ShutdownHookProcessDestroyer();
1263 }
1264 return processDestroyer;
1265 }
1266 }