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 cli.addEnvironment( "M2_HOME", getMavenHome().getAbsolutePath() );
206 }
207 catch ( IOException e )
208 {
209 throw new CommandLineConfigurationException( "Error reading shell environment variables. Reason: "
210 + e.getMessage(), e );
211 }
212 catch ( Exception e )
213 {
214 if ( e instanceof RuntimeException )
215 {
216 throw (RuntimeException) e;
217 }
218 else
219 {
220 IllegalStateException error =
221 new IllegalStateException( "Unknown error retrieving shell environment variables. Reason: "
222 + e.getMessage() );
223 error.initCause( e );
224
225 throw error;
226 }
227 }
228 }
229
230 if ( request.getJavaHome() != null )
231 {
232 cli.addEnvironment( "JAVA_HOME", request.getJavaHome().getAbsolutePath() );
233 }
234
235 if ( request.getMavenOpts() != null )
236 {
237 cli.addEnvironment( "MAVEN_OPTS", request.getMavenOpts() );
238 }
239
240 for ( Map.Entry<String, String> entry : request.getShellEnvironments().entrySet() )
241 {
242 cli.addEnvironment( entry.getKey(), entry.getValue() );
243 }
244 }
245
246 protected void setProfiles( InvocationRequest request, Commandline cli )
247 {
248 List<String> profiles = request.getProfiles();
249
250 if ( ( profiles != null ) && !profiles.isEmpty() )
251 {
252 cli.createArg().setValue( "-P" );
253 cli.createArg().setValue( StringUtils.join( profiles.iterator(), "," ) );
254 }
255
256 }
257
258 protected void setGoals( InvocationRequest request, Commandline cli )
259 {
260 List<String> goals = request.getGoals();
261
262 if ( ( goals != null ) && !goals.isEmpty() )
263 {
264 cli.createArg().setLine( StringUtils.join( goals.iterator(), " " ) );
265 }
266 }
267
268 protected void setProperties( InvocationRequest request, Commandline cli )
269 {
270 Properties properties = request.getProperties();
271
272 if ( properties != null )
273 {
274 for ( Iterator it = properties.entrySet().iterator(); it.hasNext(); )
275 {
276 Map.Entry entry = (Map.Entry) it.next();
277
278 String key = (String) entry.getKey();
279 String value = (String) entry.getValue();
280
281 cli.createArg().setValue( "-D" );
282 cli.createArg().setValue( key + '=' + value );
283 }
284 }
285 }
286
287 protected void setPomLocation( InvocationRequest request, Commandline cli )
288 {
289 boolean pomSpecified = false;
290
291 File pom = request.getPomFile();
292 String pomFilename = request.getPomFileName();
293 File baseDirectory = request.getBaseDirectory();
294
295 if ( pom != null )
296 {
297 pomSpecified = true;
298 }
299 else if ( baseDirectory != null )
300 {
301 if ( baseDirectory.isDirectory() )
302 {
303 if ( pomFilename != null )
304 {
305 pom = new File( baseDirectory, pomFilename );
306
307 pomSpecified = true;
308 }
309 else
310 {
311 pom = new File( baseDirectory, "pom.xml" );
312 }
313 }
314 else
315 {
316 logger.warn( "Base directory is a file. Using base directory as POM location." );
317
318 pom = baseDirectory;
319
320 pomSpecified = true;
321 }
322 }
323
324 if ( pomSpecified )
325 {
326 try
327 {
328 File canPom = pom.getCanonicalFile();
329 pom = canPom;
330 }
331 catch ( IOException e )
332 {
333 logger.debug( "Failed to canonicalize the POM path: " + pom + ". Using as-is.", e );
334 }
335
336 if ( !"pom.xml".equals( pom.getName() ) )
337 {
338 logger.debug( "Specified POM file is not named \'pom.xml\'. "
339 + "Using the \'-f\' command-line option to accommodate non-standard filename..." );
340
341 cli.createArg().setValue( "-f" );
342 cli.createArg().setValue( pom.getName() );
343 }
344 }
345 }
346
347 protected void setEnvironmentPaths( InvocationRequest request, Commandline cli )
348 {
349 File workingDirectory = request.getBaseDirectory();
350
351 if ( workingDirectory == null )
352 {
353 File pomFile = request.getPomFile();
354 if ( pomFile != null )
355 {
356 workingDirectory = pomFile.getParentFile();
357 }
358 }
359
360 if ( workingDirectory == null )
361 {
362 workingDirectory = this.workingDirectory;
363 }
364
365 if ( workingDirectory == null )
366 {
367 workingDirectory = new File( System.getProperty( "user.dir" ) );
368 }
369 else if ( workingDirectory.isFile() )
370 {
371 logger.warn( "Specified base directory (" + workingDirectory + ") is a file."
372 + " Using its parent directory..." );
373
374 workingDirectory = workingDirectory.getParentFile();
375 }
376
377 try
378 {
379 cli.setWorkingDirectory( workingDirectory.getCanonicalPath() );
380 }
381 catch ( IOException e )
382 {
383 logger.debug( "Failed to canonicalize base directory: " + workingDirectory + ". Using as-is.", e );
384
385 cli.setWorkingDirectory( workingDirectory.getAbsolutePath() );
386 }
387
388 File localRepositoryDirectory = request.getLocalRepositoryDirectory( this.localRepositoryDirectory );
389
390 if ( localRepositoryDirectory != null )
391 {
392 try
393 {
394 File canLRD = localRepositoryDirectory.getCanonicalFile();
395 localRepositoryDirectory = canLRD;
396 }
397 catch ( IOException e )
398 {
399 logger.debug( "Failed to canonicalize local repository directory: " + localRepositoryDirectory
400 + ". Using as-is.", e );
401 }
402
403 if ( !localRepositoryDirectory.isDirectory() )
404 {
405 throw new IllegalArgumentException( "Local repository location: \'" + localRepositoryDirectory
406 + "\' is NOT a directory." );
407 }
408
409 cli.createArg().setValue( "-D" );
410 cli.createArg().setValue( "maven.repo.local=" + localRepositoryDirectory.getPath() );
411 }
412 }
413
414 protected void setReactorBehavior( InvocationRequest request, Commandline cli )
415 {
416
417 String failureBehavior = request.getFailureBehavior();
418
419 if ( StringUtils.isNotEmpty( failureBehavior ) )
420 {
421 if ( InvocationRequest.REACTOR_FAIL_AT_END.equals( failureBehavior ) )
422 {
423 cli.createArg().setValue( "-fae" );
424 }
425 else if ( InvocationRequest.REACTOR_FAIL_NEVER.equals( failureBehavior ) )
426 {
427 cli.createArg().setValue( "-fn" );
428 }
429 }
430
431 if ( request.isActivatedReactor() )
432 {
433 cli.createArg().setValue( "-r" );
434 String[] includes = request.getActivatedReactorIncludes();
435 String[] excludes = request.getActivatedReactorExcludes();
436 if ( includes != null )
437 {
438 cli.createArg().setValue( "-D" );
439 cli.createArg().setValue( "maven.reactor.includes=" + StringUtils.join( includes, "," ) );
440 }
441 if ( excludes != null )
442 {
443 cli.createArg().setValue( "-D" );
444 cli.createArg().setValue( "maven.reactor.excludes=" + StringUtils.join( excludes, "," ) );
445 }
446 }
447
448 if ( StringUtils.isNotEmpty( request.getResumeFrom() ) )
449 {
450 cli.createArg().setValue( "-rf" );
451 cli.createArg().setValue( request.getResumeFrom() );
452 }
453
454 List<String> projectList = request.getProjects();
455 if ( projectList != null )
456 {
457 cli.createArg().setValue( "-pl" );
458 cli.createArg().setValue( StringUtils.join( projectList.iterator(), "," ) );
459
460 if ( request.isAlsoMake() )
461 {
462 cli.createArg().setValue( "-am" );
463 }
464
465 if ( request.isAlsoMakeDependents() )
466 {
467 cli.createArg().setValue( "-amd" );
468 }
469 }
470 }
471
472 protected void setFlags( InvocationRequest request, Commandline cli )
473 {
474 if ( !request.isInteractive() )
475 {
476 cli.createArg().setValue( "-B" );
477 }
478
479 if ( request.isOffline() )
480 {
481 cli.createArg().setValue( "-o" );
482 }
483
484 if ( request.isUpdateSnapshots() )
485 {
486 cli.createArg().setValue( "-U" );
487 }
488
489 if ( !request.isRecursive() )
490 {
491 cli.createArg().setValue( "-N" );
492 }
493
494 if ( request.isDebug() )
495 {
496 cli.createArg().setValue( "-X" );
497 }
498
499 else if ( request.isShowErrors() )
500 {
501 cli.createArg().setValue( "-e" );
502 }
503
504 String checksumPolicy = request.getGlobalChecksumPolicy();
505 if ( InvocationRequest.CHECKSUM_POLICY_FAIL.equals( checksumPolicy ) )
506 {
507 cli.createArg().setValue( "-C" );
508 }
509 else if ( InvocationRequest.CHECKSUM_POLICY_WARN.equals( checksumPolicy ) )
510 {
511 cli.createArg().setValue( "-c" );
512 }
513 if ( request.isNonPluginUpdates() )
514 {
515 cli.createArg().setValue( "-npu" );
516 }
517
518 if ( request.isShowVersion() )
519 {
520 cli.createArg().setValue( "-V" );
521 }
522 }
523
524 protected void setThreads( InvocationRequest request, Commandline cli )
525 {
526 String threads = request.getThreads();
527 if ( StringUtils.isNotEmpty( threads ) )
528 {
529 cli.createArg().setValue( "-T" );
530 cli.createArg().setValue( threads );
531 }
532
533 }
534
535 protected File findMavenExecutable()
536 throws CommandLineConfigurationException, IOException
537 {
538 if ( mavenHome == null )
539 {
540 String mavenHomeProperty = System.getProperty( "maven.home" );
541 if ( mavenHomeProperty != null )
542 {
543 mavenHome = new File( mavenHomeProperty );
544 if ( !mavenHome.isDirectory() )
545 {
546 File binDir = mavenHome.getParentFile();
547 if ( binDir != null && "bin".equals( binDir.getName() ) )
548 {
549
550
551 mavenHome = binDir.getParentFile();
552 }
553 else
554 {
555 throw new IllegalStateException( "${maven.home} is not specified as a directory: \'"
556 + mavenHomeProperty + "\'." );
557 }
558 }
559 }
560
561 if ( ( mavenHome == null ) && ( getSystemEnvVars().getProperty( "M2_HOME" ) != null ) )
562 {
563 mavenHome = new File( getSystemEnvVars().getProperty( "M2_HOME" ) );
564 }
565 }
566
567 logger.debug( "Using ${maven.home} of: \'" + mavenHome + "\'." );
568
569 if ( mavenExecutable == null || !mavenExecutable.isAbsolute() )
570 {
571 String executable;
572 if ( mavenExecutable != null )
573 {
574 executable = mavenExecutable.getPath();
575 }
576 else if ( Os.isFamily( "windows" ) )
577 {
578 if ( new File( mavenHome, "/bin/mvn.cmd" ).exists() )
579 {
580 executable = "mvn.cmd";
581 }
582 else
583 {
584 executable = "mvn.bat";
585 }
586 }
587 else
588 {
589 executable = "mvn";
590 }
591
592 mavenExecutable = new File( mavenHome, "/bin/" + executable );
593
594 try
595 {
596 File canonicalMvn = mavenExecutable.getCanonicalFile();
597 mavenExecutable = canonicalMvn;
598 }
599 catch ( IOException e )
600 {
601 logger.debug( "Failed to canonicalize maven executable: " + mavenExecutable + ". Using as-is.", e );
602 }
603
604 if ( !mavenExecutable.isFile() )
605 {
606 throw new CommandLineConfigurationException( "Maven executable not found at: " + mavenExecutable );
607 }
608 }
609
610 return mavenExecutable;
611 }
612
613
614
615
616
617
618
619
620 public String wrapStringWithQuotes( String path )
621 {
622 if ( path.indexOf( " " ) > -1 )
623 {
624 return "\"" + path + "\"";
625 }
626 else
627 {
628 return path;
629 }
630 }
631
632 private Properties getSystemEnvVars()
633 throws IOException
634 {
635 if ( this.systemEnvVars == null )
636 {
637
638 this.systemEnvVars = CommandLineUtils.getSystemEnvVars();
639 }
640 return this.systemEnvVars;
641 }
642
643 public File getLocalRepositoryDirectory()
644 {
645 return localRepositoryDirectory;
646 }
647
648 public void setLocalRepositoryDirectory( File localRepositoryDirectory )
649 {
650 this.localRepositoryDirectory = localRepositoryDirectory;
651 }
652
653 public InvokerLogger getLogger()
654 {
655 return logger;
656 }
657
658 public void setLogger( InvokerLogger logger )
659 {
660 this.logger = logger;
661 }
662
663 public File getMavenHome()
664 {
665 return mavenHome;
666 }
667
668 public void setMavenHome( File mavenHome )
669 {
670 this.mavenHome = mavenHome;
671 }
672
673 public File getWorkingDirectory()
674 {
675 return workingDirectory;
676 }
677
678 public void setWorkingDirectory( File workingDirectory )
679 {
680 this.workingDirectory = workingDirectory;
681 }
682
683
684
685
686
687
688 public void setMavenExecutable( File mavenExecutable )
689 {
690 this.mavenExecutable = mavenExecutable;
691 }
692
693 public File getMavenExecutable()
694 {
695 return mavenExecutable;
696 }
697
698 }