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