1   package org.apache.maven.shared.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.File;
23  import java.io.IOException;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Map.Entry;
27  import java.util.Properties;
28  
29  import org.apache.maven.shared.invoker.InvocationRequest.CheckSumPolicy;
30  import org.apache.maven.shared.invoker.InvocationRequest.ReactorFailureBehavior;
31  import org.apache.maven.shared.utils.Os;
32  import org.apache.maven.shared.utils.StringUtils;
33  import org.apache.maven.shared.utils.cli.CommandLineException;
34  import org.apache.maven.shared.utils.cli.CommandLineUtils;
35  import org.apache.maven.shared.utils.cli.Commandline;
36  
37  
38  
39  
40  public class MavenCommandLineBuilder
41  {
42  
43      private static final InvokerLogger DEFAULT_LOGGER = new SystemOutLogger();
44  
45      private InvokerLogger logger = DEFAULT_LOGGER;
46  
47      private File workingDirectory;
48  
49      private File localRepositoryDirectory;
50  
51      private File mavenHome;
52  
53      private File mavenExecutable;
54  
55      private Properties systemEnvVars;
56  
57      
58  
59  
60  
61  
62  
63  
64      public Commandline build( InvocationRequest request )
65          throws CommandLineConfigurationException
66      {
67          try
68          {
69              checkRequiredState();
70          }
71          catch ( IOException e )
72          {
73              throw new CommandLineConfigurationException( e.getMessage(), e );
74          }
75          File mvn;
76          try
77          {
78              mvn = findMavenExecutable();
79          }
80          catch ( IOException e )
81          {
82              throw new CommandLineConfigurationException( e.getMessage(), e );
83          }
84          Commandline cli = new Commandline();
85  
86          cli.setExecutable( mvn.getAbsolutePath() );
87  
88          
89          setShellEnvironment( request, cli );
90  
91          
92          
93          setFlags( request, cli );
94  
95          
96          
97          setReactorBehavior( request, cli );
98  
99          
100         setEnvironmentPaths( request, cli );
101 
102         
103         setPomLocation( request, cli );
104 
105         setSettingsLocation( request, cli );
106 
107         setToolchainsLocation( request, cli );
108 
109         setProperties( request, cli );
110 
111         setProfiles( request, cli );
112 
113         setGoals( request, cli );
114 
115         setThreads( request, cli );
116 
117         return cli;
118     }
119 
120     
121 
122 
123 
124 
125     protected void checkRequiredState()
126         throws IOException
127     {
128         if ( logger == null )
129         {
130             throw new IllegalStateException( "A logger instance is required." );
131         }
132 
133         if ( ( mavenHome == null ) && ( System.getProperty( "maven.home" ) == null ) )
134         
135         
136         {
137             if ( !getSystemEnvVars().containsKey( "M2_HOME" ) )
138             {
139                 throw new IllegalStateException( "Maven application directory was not "
140                     + "specified, and ${maven.home} is not provided in the system "
141                     + "properties. Specify at least one of these." );
142             }
143         }
144     }
145 
146     
147 
148 
149 
150 
151 
152     protected void setSettingsLocation( InvocationRequest request, Commandline cli )
153     {
154         File userSettingsFile = request.getUserSettingsFile();
155 
156         if ( userSettingsFile != null )
157         {
158             try
159             {
160                 userSettingsFile = userSettingsFile.getCanonicalFile();
161             }
162             catch ( IOException e )
163             {
164                 logger.debug( "Failed to canonicalize user settings path: " + userSettingsFile.getAbsolutePath()
165                     + ". Using as-is.", e );
166             }
167 
168             cli.createArg().setValue( "-s" );
169             cli.createArg().setValue( userSettingsFile.getPath() );
170         }
171 
172         File globalSettingsFile = request.getGlobalSettingsFile();
173 
174         if ( globalSettingsFile != null )
175         {
176             try
177             {
178                 globalSettingsFile = globalSettingsFile.getCanonicalFile();
179             }
180             catch ( IOException e )
181             {
182                 logger.debug( "Failed to canonicalize global settings path: " + globalSettingsFile.getAbsolutePath()
183                     + ". Using as-is.", e );
184             }
185 
186             cli.createArg().setValue( "-gs" );
187             cli.createArg().setValue( globalSettingsFile.getPath() );
188         }
189 
190     }
191 
192     
193 
194 
195 
196 
197 
198     protected void setToolchainsLocation( InvocationRequest request, Commandline cli )
199     {
200         File toolchainsFile = request.getToolchainsFile();
201 
202         if ( toolchainsFile != null )
203         {
204             try
205             {
206                 toolchainsFile = toolchainsFile.getCanonicalFile();
207             }
208             catch ( IOException e )
209             {
210                 logger.debug( "Failed to canonicalize toolchains path: " + toolchainsFile.getAbsolutePath()
211                     + ". Using as-is.", e );
212             }
213 
214             cli.createArg().setValue( "-t" );
215             cli.createArg().setValue( toolchainsFile.getPath() );
216         }
217     }
218 
219     
220 
221 
222 
223 
224 
225 
226     protected void setShellEnvironment( InvocationRequest request, Commandline cli )
227         throws CommandLineConfigurationException
228     {
229         if ( request.isShellEnvironmentInherited() )
230         {
231             try
232             {
233                 cli.addSystemEnvironment();
234                 cli.addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
235                 
236                 
237                 cli.addEnvironment( "M2_HOME", getMavenHome().getAbsolutePath() );
238             }
239             catch ( RuntimeException e )
240             {
241                 throw e;
242             }
243             catch ( Exception e )
244             {
245                 throw new IllegalStateException(
246                         "Unknown error retrieving shell environment variables. Reason: " + e.getMessage(), e );
247             }
248         }
249 
250         if ( request.getJavaHome() != null )
251         {
252             cli.addEnvironment( "JAVA_HOME", request.getJavaHome().getAbsolutePath() );
253         }
254 
255         if ( request.getMavenOpts() != null )
256         {
257             cli.addEnvironment( "MAVEN_OPTS", request.getMavenOpts() );
258         }
259 
260         for ( Map.Entry<String, String> entry : request.getShellEnvironments().entrySet() )
261         {
262             cli.addEnvironment( entry.getKey(), entry.getValue() );
263         }
264     }
265 
266     
267 
268 
269 
270 
271 
272     protected void setProfiles( InvocationRequest request, Commandline cli )
273     {
274         List<String> profiles = request.getProfiles();
275 
276         if ( ( profiles != null ) && !profiles.isEmpty() )
277         {
278             cli.createArg().setValue( "-P" );
279             cli.createArg().setValue( StringUtils.join( profiles.iterator(), "," ) );
280         }
281 
282     }
283 
284     
285 
286 
287 
288 
289 
290 
291     protected void setGoals( InvocationRequest request, Commandline cli ) throws CommandLineConfigurationException
292     {
293         List<String> goals = request.getGoals();
294 
295         if ( ( goals != null ) && !goals.isEmpty() )
296         {
297             try
298             {
299                 cli.createArg().setLine( StringUtils.join( goals.iterator(), " " ) );
300             }
301             catch ( CommandLineException e )
302             {
303                 throw new CommandLineConfigurationException( "Problem to set goals: " + e.getMessage(), e );
304             }
305         }
306     }
307 
308     
309 
310 
311 
312 
313 
314     protected void setProperties( InvocationRequest request, Commandline cli )
315     {
316         Properties properties = request.getProperties();
317 
318         if ( properties != null )
319         {
320             for ( Entry<Object, Object> entry : properties.entrySet() )
321             {
322                 String key = (String) entry.getKey();
323                 String value = (String) entry.getValue();
324 
325                 cli.createArg().setValue( "-D" );
326                 cli.createArg().setValue( key + '=' + value );
327             }
328         }
329     }
330 
331     
332 
333 
334 
335 
336 
337     protected void setPomLocation( InvocationRequest request, Commandline cli )
338     {
339         boolean pomSpecified = false;
340 
341         File pom = request.getPomFile();
342         String pomFilename = request.getPomFileName();
343         File baseDirectory = request.getBaseDirectory();
344 
345         if ( pom != null )
346         {
347             pomSpecified = true;
348         }
349         else if ( baseDirectory != null )
350         {
351             if ( baseDirectory.isDirectory() )
352             {
353                 if ( pomFilename != null )
354                 {
355                     pom = new File( baseDirectory, pomFilename );
356 
357                     pomSpecified = true;
358                 }
359                 else
360                 {
361                     pom = new File( baseDirectory, "pom.xml" );
362                 }
363             }
364             else
365             {
366                 logger.warn( "Base directory is a file. Using base directory as POM location." );
367 
368                 pom = baseDirectory;
369 
370                 pomSpecified = true;
371             }
372         }
373 
374         if ( pomSpecified )
375         {
376             try
377             {
378                 pom = pom.getCanonicalFile();
379             }
380             catch ( IOException e )
381             {
382                 logger.debug( "Failed to canonicalize the POM path: " + pom + ". Using as-is.", e );
383             }
384 
385             if ( !"pom.xml".equals( pom.getName() ) )
386             {
387                 logger.debug( "Specified POM file is not named 'pom.xml'. "
388                     + "Using the '-f' command-line option to accommodate non-standard filename..." );
389 
390                 cli.createArg().setValue( "-f" );
391                 cli.createArg().setValue( pom.getName() );
392             }
393         }
394     }
395 
396     
397 
398 
399 
400 
401 
402     protected void setEnvironmentPaths( InvocationRequest request, Commandline cli )
403     {
404         File workingDirectory = request.getBaseDirectory();
405 
406         if ( workingDirectory == null )
407         {
408             File pomFile = request.getPomFile();
409             if ( pomFile != null )
410             {
411                 workingDirectory = pomFile.getParentFile();
412             }
413         }
414 
415         if ( workingDirectory == null )
416         {
417             workingDirectory = this.workingDirectory;
418         }
419 
420         if ( workingDirectory == null )
421         {
422             workingDirectory = new File( System.getProperty( "user.dir" ) );
423         }
424         else if ( workingDirectory.isFile() )
425         {
426             logger.warn( "Specified base directory (" + workingDirectory + ") is a file."
427                 + " Using its parent directory..." );
428 
429             workingDirectory = workingDirectory.getParentFile();
430         }
431 
432         try
433         {
434             cli.setWorkingDirectory( workingDirectory.getCanonicalPath() );
435         }
436         catch ( IOException e )
437         {
438             logger.debug( "Failed to canonicalize base directory: " + workingDirectory + ". Using as-is.", e );
439 
440             cli.setWorkingDirectory( workingDirectory.getAbsolutePath() );
441         }
442 
443         File localRepositoryDirectory = request.getLocalRepositoryDirectory( this.localRepositoryDirectory );
444 
445         if ( localRepositoryDirectory != null )
446         {
447             try
448             {
449                 localRepositoryDirectory = localRepositoryDirectory.getCanonicalFile();
450             }
451             catch ( IOException e )
452             {
453                 logger.debug( "Failed to canonicalize local repository directory: " + localRepositoryDirectory
454                     + ". Using as-is.", e );
455             }
456 
457             if ( !localRepositoryDirectory.isDirectory() )
458             {
459                 throw new IllegalArgumentException( "Local repository location: '" + localRepositoryDirectory
460                     + "' is NOT a directory." );
461             }
462 
463             cli.createArg().setValue( "-D" );
464             cli.createArg().setValue( "maven.repo.local=" + localRepositoryDirectory.getPath() );
465         }
466     }
467 
468     
469 
470 
471 
472 
473 
474     protected void setReactorBehavior( InvocationRequest request, Commandline cli )
475     {
476         
477         ReactorFailureBehavior failureBehavior = request.getReactorFailureBehavior();
478 
479         if ( failureBehavior != null )
480         {
481             if ( ReactorFailureBehavior.FailAtEnd.equals( failureBehavior ) )
482             {
483                 cli.createArg().setValue( "-" + ReactorFailureBehavior.FailAtEnd.getShortOption() );
484             }
485             else if ( ReactorFailureBehavior.FailNever.equals( failureBehavior ) )
486             {
487                 cli.createArg().setValue( "-" + ReactorFailureBehavior.FailNever.getShortOption() );
488             }
489 
490         }
491 
492         if ( StringUtils.isNotEmpty( request.getResumeFrom() ) )
493         {
494             cli.createArg().setValue( "-rf" );
495             cli.createArg().setValue( request.getResumeFrom() );
496         }
497 
498         List<String> projectList = request.getProjects();
499         if ( projectList != null )
500         {
501             cli.createArg().setValue( "-pl" );
502             cli.createArg().setValue( StringUtils.join( projectList.iterator(), "," ) );
503 
504             if ( request.isAlsoMake() )
505             {
506                 cli.createArg().setValue( "-am" );
507             }
508 
509             if ( request.isAlsoMakeDependents() )
510             {
511                 cli.createArg().setValue( "-amd" );
512             }
513         }
514     }
515 
516     
517 
518 
519 
520 
521 
522     protected void setFlags( InvocationRequest request, Commandline cli )
523     {
524         if ( request.isBatchMode() )
525         {
526             cli.createArg().setValue( "-B" );
527         }
528 
529         if ( request.isOffline() )
530         {
531             cli.createArg().setValue( "-o" );
532         }
533 
534         if ( request.isUpdateSnapshots() )
535         {
536             cli.createArg().setValue( "-U" );
537         }
538 
539         if ( !request.isRecursive() )
540         {
541             cli.createArg().setValue( "-N" );
542         }
543 
544         if ( request.isDebug() )
545         {
546             cli.createArg().setValue( "-X" );
547         }
548         
549         else if ( request.isShowErrors() )
550         {
551             cli.createArg().setValue( "-e" );
552         }
553 
554         CheckSumPolicy checksumPolicy = request.getGlobalChecksumPolicy();
555         if ( CheckSumPolicy.Fail.equals( checksumPolicy ) )
556         {
557             cli.createArg().setValue( "-C" );
558         }
559         else if ( CheckSumPolicy.Warn.equals( checksumPolicy ) )
560         {
561             cli.createArg().setValue( "-c" );
562         }
563 
564         if ( request.isNonPluginUpdates() )
565         {
566             cli.createArg().setValue( "-npu" );
567         }
568 
569         if ( request.isShowVersion() )
570         {
571             cli.createArg().setValue( "-V" );
572         }
573 
574         if ( request.getBuilder() != null )
575         {
576             cli.createArg().setValue( request.getBuilder() );
577         }
578 
579         if ( request.isQuiet() )
580         {
581             cli.createArg().setValue( "-q" );
582         }
583     }
584 
585     
586 
587 
588 
589 
590 
591     protected void setThreads( InvocationRequest request, Commandline cli )
592     {
593         String threads = request.getThreads();
594         if ( StringUtils.isNotEmpty( threads ) )
595         {
596             cli.createArg().setValue( "-T" );
597             cli.createArg().setValue( threads );
598         }
599 
600     }
601 
602     
603 
604 
605 
606 
607 
608 
609     protected File findMavenExecutable()
610         throws CommandLineConfigurationException, IOException
611     {
612         if ( mavenHome == null )
613         {
614             String mavenHomeProperty = System.getProperty( "maven.home" );
615             if ( mavenHomeProperty != null )
616             {
617                 mavenHome = new File( mavenHomeProperty );
618                 if ( !mavenHome.isDirectory() )
619                 {
620                     File binDir = mavenHome.getParentFile();
621                     if ( binDir != null && "bin".equals( binDir.getName() ) )
622                     {
623                         
624                         
625                         mavenHome = binDir.getParentFile();
626                     }
627                     else
628                     {
629                         throw new IllegalStateException( "${maven.home} is not specified as a directory: '"
630                             + mavenHomeProperty + "'." );
631                     }
632                 }
633             }
634 
635             if ( ( mavenHome == null ) && ( getSystemEnvVars().getProperty( "M2_HOME" ) != null ) )
636             {
637                 mavenHome = new File( getSystemEnvVars().getProperty( "M2_HOME" ) );
638             }
639         }
640 
641         logger.debug( "Using ${maven.home} of: '" + mavenHome + "'." );
642 
643         if ( mavenExecutable == null || !mavenExecutable.isAbsolute() )
644         {
645             String executable;
646             if ( mavenExecutable != null )
647             {
648                 executable = mavenExecutable.getPath();
649             }
650             else if ( Os.isFamily( "windows" ) )
651             {
652                 if ( new File( mavenHome, "/bin/mvn.cmd" ).exists() )
653                 {
654                     executable = "mvn.cmd";
655                 }
656                 else
657                 {
658                     executable = "mvn.bat";
659                 }
660             }
661             else
662             {
663                 executable = "mvn";
664             }
665 
666             mavenExecutable = new File( mavenHome, "/bin/" + executable );
667 
668             try
669             {
670                 mavenExecutable = mavenExecutable.getCanonicalFile();
671             }
672             catch ( IOException e )
673             {
674                 logger.debug( "Failed to canonicalize maven executable: " + mavenExecutable + ". Using as-is.", e );
675             }
676 
677             if ( !mavenExecutable.isFile() )
678             {
679                 throw new CommandLineConfigurationException( "Maven executable not found at: " + mavenExecutable );
680             }
681         }
682 
683         return mavenExecutable;
684     }
685 
686     private Properties getSystemEnvVars()
687     {
688         if ( this.systemEnvVars == null )
689         {
690             
691             this.systemEnvVars = CommandLineUtils.getSystemEnvVars();
692         }
693         return this.systemEnvVars;
694     }
695 
696     
697 
698 
699 
700 
701     public File getLocalRepositoryDirectory()
702     {
703         return localRepositoryDirectory;
704     }
705 
706     
707 
708 
709 
710 
711     public void setLocalRepositoryDirectory( File localRepositoryDirectory )
712     {
713         this.localRepositoryDirectory = localRepositoryDirectory;
714     }
715 
716     
717 
718 
719 
720 
721     public InvokerLogger getLogger()
722     {
723         return logger;
724     }
725 
726     
727 
728 
729 
730 
731     public void setLogger( InvokerLogger logger )
732     {
733         this.logger = logger;
734     }
735 
736     
737 
738 
739 
740 
741     public File getMavenHome()
742     {
743         return mavenHome;
744     }
745 
746     
747 
748 
749 
750 
751     public void setMavenHome( File mavenHome )
752     {
753         this.mavenHome = mavenHome;
754     }
755 
756     
757 
758 
759 
760 
761     public File getWorkingDirectory()
762     {
763         return workingDirectory;
764     }
765 
766     
767 
768 
769 
770 
771     public void setWorkingDirectory( File workingDirectory )
772     {
773         this.workingDirectory = workingDirectory;
774     }
775 
776     
777 
778 
779 
780 
781     public void setMavenExecutable( File mavenExecutable )
782     {
783         this.mavenExecutable = mavenExecutable;
784     }
785 
786     
787 
788 
789 
790 
791     public File getMavenExecutable()
792     {
793         return mavenExecutable;
794     }
795 
796 }