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