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