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 }