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 mvnCommand;
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 setProperties( request, cli );
98
99 setProfiles( request, cli );
100
101 setGoals( request, cli );
102
103 return cli;
104 }
105
106 protected void checkRequiredState()
107 throws IOException
108 {
109 if ( logger == null )
110 {
111 throw new IllegalStateException( "A logger instance is required." );
112 }
113
114 if ( ( mavenHome == null ) && ( System.getProperty( "maven.home" ) == null ) )
115
116
117 {
118 if ( !getSystemEnvVars().containsKey( "M2_HOME" ) )
119 {
120 throw new IllegalStateException( "Maven application directory was not "
121 + "specified, and ${maven.home} is not provided in the system "
122 + "properties. Please specify at least on of these." );
123 }
124 }
125 }
126
127 protected void setSettingsLocation( InvocationRequest request, Commandline cli )
128 {
129 File userSettingsFile = request.getUserSettingsFile();
130
131 if ( userSettingsFile != null )
132 {
133 try
134 {
135 File canSet = userSettingsFile.getCanonicalFile();
136 userSettingsFile = canSet;
137 }
138 catch ( IOException e )
139 {
140 logger.debug( "Failed to canonicalize user settings path: " + userSettingsFile.getAbsolutePath()
141 + ". Using as-is.", e );
142 }
143
144 cli.createArg().setValue( "-s" );
145 cli.createArg().setValue( userSettingsFile.getPath() );
146 }
147 }
148
149 protected void setShellEnvironment( InvocationRequest request, Commandline cli )
150 throws CommandLineConfigurationException
151 {
152 if ( request.isShellEnvironmentInherited() )
153 {
154 try
155 {
156 cli.addSystemEnvironment();
157 cli.addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
158 }
159 catch ( IOException e )
160 {
161 throw new CommandLineConfigurationException( "Error reading shell environment variables. Reason: "
162 + e.getMessage(), e );
163 }
164 catch ( Exception e )
165 {
166 if ( e instanceof RuntimeException )
167 {
168 throw (RuntimeException) e;
169 }
170 else
171 {
172 IllegalStateException error =
173 new IllegalStateException( "Unknown error retrieving shell environment variables. Reason: "
174 + e.getMessage() );
175 error.initCause( e );
176
177 throw error;
178 }
179 }
180 }
181
182 if ( request.getJavaHome() != null )
183 {
184 cli.addEnvironment( "JAVA_HOME", request.getJavaHome().getAbsolutePath() );
185 }
186
187 if ( request.getMavenOpts() != null )
188 {
189 cli.addEnvironment( "MAVEN_OPTS", request.getMavenOpts() );
190 }
191
192 for ( Iterator iterator = request.getShellEnvironments().keySet().iterator(); iterator.hasNext(); )
193 {
194 String key = (String) iterator.next();
195 String value = (String) request.getShellEnvironments().get( key );
196 cli.addEnvironment( key, value );
197 }
198 }
199
200 protected void setProfiles( InvocationRequest request, Commandline cli )
201 {
202 List profiles = request.getProfiles();
203
204 if ( ( profiles != null ) && !profiles.isEmpty() )
205 {
206 cli.createArg().setValue( "-P" );
207 cli.createArg().setValue( StringUtils.join( profiles.iterator(), "," ) );
208 }
209
210 }
211
212 protected void setGoals( InvocationRequest request, Commandline cli )
213 {
214 List goals = request.getGoals();
215
216 if ( ( goals != null ) && !goals.isEmpty() )
217 {
218 cli.createArg().setLine( StringUtils.join( goals.iterator(), " " ) );
219 }
220 }
221
222 protected void setProperties( InvocationRequest request, Commandline cli )
223 {
224 Properties properties = request.getProperties();
225
226 if ( properties != null )
227 {
228 for ( Iterator it = properties.entrySet().iterator(); it.hasNext(); )
229 {
230 Map.Entry entry = (Map.Entry) it.next();
231
232 String key = (String) entry.getKey();
233 String value = (String) entry.getValue();
234
235 cli.createArg().setValue( "-D" );
236 cli.createArg().setValue( key + '=' + value );
237 }
238 }
239 }
240
241 protected void setPomLocation( InvocationRequest request, Commandline cli )
242 {
243 boolean pomSpecified = false;
244
245 File pom = request.getPomFile();
246 String pomFilename = request.getPomFileName();
247 File baseDirectory = request.getBaseDirectory();
248
249 if ( pom != null )
250 {
251 pomSpecified = true;
252 }
253 else if ( baseDirectory != null )
254 {
255 if ( baseDirectory.isDirectory() )
256 {
257 if ( pomFilename != null )
258 {
259 pom = new File( baseDirectory, pomFilename );
260
261 pomSpecified = true;
262 }
263 else
264 {
265 pom = new File( baseDirectory, "pom.xml" );
266 }
267 }
268 else
269 {
270 logger.warn( "Base directory is a file. Using base directory as POM location." );
271
272 pom = baseDirectory;
273
274 pomSpecified = true;
275 }
276 }
277
278 if ( pomSpecified )
279 {
280 try
281 {
282 File canPom = pom.getCanonicalFile();
283 pom = canPom;
284 }
285 catch ( IOException e )
286 {
287 logger.debug( "Failed to canonicalize the POM path: " + pom + ". Using as-is.", e );
288 }
289
290 if ( !"pom.xml".equals( pom.getName() ) )
291 {
292 logger.debug( "Specified POM file is not named \'pom.xml\'. "
293 + "Using the \'-f\' command-line option to accommodate non-standard filename..." );
294
295 cli.createArg().setValue( "-f" );
296 cli.createArg().setValue( pom.getName() );
297 }
298 }
299 }
300
301 protected void setEnvironmentPaths( InvocationRequest request, Commandline cli )
302 {
303 File workingDirectory = request.getBaseDirectory();
304
305 if ( workingDirectory == null )
306 {
307 File pomFile = request.getPomFile();
308 if ( pomFile != null )
309 {
310 workingDirectory = pomFile.getParentFile();
311 }
312 }
313
314 if ( workingDirectory == null )
315 {
316 workingDirectory = this.workingDirectory;
317 }
318
319 if ( workingDirectory == null )
320 {
321 workingDirectory = new File( System.getProperty( "user.dir" ) );
322 }
323 else if ( workingDirectory.isFile() )
324 {
325 logger.warn( "Specified base directory (" + workingDirectory + ") is a file."
326 + " Using its parent directory..." );
327
328 workingDirectory = workingDirectory.getParentFile();
329 }
330
331 try
332 {
333 cli.setWorkingDirectory( workingDirectory.getCanonicalPath() );
334 }
335 catch ( IOException e )
336 {
337 logger.debug( "Failed to canonicalize base directory: " + workingDirectory + ". Using as-is.", e );
338
339 cli.setWorkingDirectory( workingDirectory.getAbsolutePath() );
340 }
341
342 File localRepositoryDirectory = request.getLocalRepositoryDirectory( this.localRepositoryDirectory );
343
344 if ( localRepositoryDirectory != null )
345 {
346 try
347 {
348 File canLRD = localRepositoryDirectory.getCanonicalFile();
349 localRepositoryDirectory = canLRD;
350 }
351 catch ( IOException e )
352 {
353 logger.debug( "Failed to canonicalize local repository directory: " + localRepositoryDirectory
354 + ". Using as-is.", e );
355 }
356
357 if ( !localRepositoryDirectory.isDirectory() )
358 {
359 throw new IllegalArgumentException( "Local repository location: \'" + localRepositoryDirectory
360 + "\' is NOT a directory." );
361 }
362
363 cli.createArg().setValue( "-D" );
364 cli.createArg().setValue( "maven.repo.local=" + localRepositoryDirectory.getPath() );
365 }
366 }
367
368 protected void setReactorBehavior( InvocationRequest request, Commandline cli )
369 {
370
371 String failureBehavior = request.getFailureBehavior();
372
373 if ( StringUtils.isNotEmpty( failureBehavior ) )
374 {
375 if ( InvocationRequest.REACTOR_FAIL_AT_END.equals( failureBehavior ) )
376 {
377 cli.createArg().setValue( "-fae" );
378 }
379 else if ( InvocationRequest.REACTOR_FAIL_NEVER.equals( failureBehavior ) )
380 {
381 cli.createArg().setValue( "-fn" );
382 }
383 }
384
385 if ( request.isActivatedReactor() )
386 {
387 cli.createArg().setValue( "-r" );
388 String[] includes = request.getActivatedReactorIncludes();
389 String[] excludes = request.getActivatedReactorExcludes();
390 if ( includes != null )
391 {
392 cli.createArg().setValue( "-D" );
393 cli.createArg().setValue( "maven.reactor.includes=" + StringUtils.join( includes, "," ) );
394 }
395 if ( excludes != null )
396 {
397 cli.createArg().setValue( "-D" );
398 cli.createArg().setValue( "maven.reactor.excludes=" + StringUtils.join( excludes, "," ) );
399 }
400 }
401 }
402
403 protected void setFlags( InvocationRequest request, Commandline cli )
404 {
405 if ( !request.isInteractive() )
406 {
407 cli.createArg().setValue( "-B" );
408 }
409
410 if ( request.isOffline() )
411 {
412 cli.createArg().setValue( "-o" );
413 }
414
415 if ( request.isUpdateSnapshots() )
416 {
417 cli.createArg().setValue( "-U" );
418 }
419
420 if ( !request.isRecursive() )
421 {
422 cli.createArg().setValue( "-N" );
423 }
424
425 if ( request.isDebug() )
426 {
427 cli.createArg().setValue( "-X" );
428 }
429
430 else if ( request.isShowErrors() )
431 {
432 cli.createArg().setValue( "-e" );
433 }
434
435 String checksumPolicy = request.getGlobalChecksumPolicy();
436 if ( InvocationRequest.CHECKSUM_POLICY_FAIL.equals( checksumPolicy ) )
437 {
438 cli.createArg().setValue( "-C" );
439 }
440 else if ( InvocationRequest.CHECKSUM_POLICY_WARN.equals( checksumPolicy ) )
441 {
442 cli.createArg().setValue( "-c" );
443 }
444 if ( request.isNonPluginUpdates() )
445 {
446 cli.createArg().setValue( "-npu" );
447 }
448
449 if ( request.isShowVersion() )
450 {
451 cli.createArg().setValue( "-V" );
452 }
453 }
454
455 protected File findMavenExecutable()
456 throws CommandLineConfigurationException, IOException
457 {
458 if ( mavenHome == null )
459 {
460 String mavenHomeProperty = System.getProperty( "maven.home" );
461 if ( mavenHomeProperty != null )
462 {
463 mavenHome = new File( mavenHomeProperty );
464 if ( !mavenHome.isDirectory() )
465 {
466 File binDir = mavenHome.getParentFile();
467 if ( "bin".equals( binDir.getName() ) )
468 {
469
470
471 mavenHome = binDir.getParentFile();
472 }
473 else
474 {
475 throw new IllegalStateException( "${maven.home} is not specified as a directory: \'"
476 + mavenHomeProperty + "\'." );
477 }
478 }
479 }
480
481 if ( ( mavenHome == null ) && ( getSystemEnvVars().getProperty( "M2_HOME" ) != null ) )
482 {
483 mavenHome = new File( getSystemEnvVars().getProperty( "M2_HOME" ) );
484 }
485 }
486
487 logger.debug( "Using ${maven.home} of: \'" + mavenHome + "\'." );
488
489 if ( mvnCommand == null )
490 {
491 if ( Os.isFamily( "windows" ) )
492 {
493 mvnCommand = new File( mavenHome, "/bin/mvn.bat" );
494 }
495 else
496 {
497 mvnCommand = new File( mavenHome, "/bin/mvn" );
498 }
499
500 try
501 {
502 File canonicalMvn = mvnCommand.getCanonicalFile();
503 mvnCommand = canonicalMvn;
504 }
505 catch ( IOException e )
506 {
507 logger.debug( "Failed to canonicalize maven executable: " + mvnCommand + ". Using as-is.", e );
508 }
509
510 if ( !mvnCommand.exists() )
511 {
512 throw new CommandLineConfigurationException( "Maven executable not found at: " + mvnCommand );
513 }
514 }
515
516 return mvnCommand;
517 }
518
519
520
521
522
523
524
525
526 public String wrapStringWithQuotes( String path )
527 {
528 if ( path.indexOf( " " ) > -1 )
529 {
530 return "\"" + path + "\"";
531 }
532 else
533 {
534 return path;
535 }
536 }
537
538 private Properties getSystemEnvVars()
539 throws IOException
540 {
541 if ( this.systemEnvVars == null )
542 {
543
544 this.systemEnvVars = CommandLineUtils.getSystemEnvVars();
545 }
546 return this.systemEnvVars;
547 }
548
549 public File getLocalRepositoryDirectory()
550 {
551 return localRepositoryDirectory;
552 }
553
554 public void setLocalRepositoryDirectory( File localRepositoryDirectory )
555 {
556 this.localRepositoryDirectory = localRepositoryDirectory;
557 }
558
559 public InvokerLogger getLogger()
560 {
561 return logger;
562 }
563
564 public void setLogger( InvokerLogger logger )
565 {
566 this.logger = logger;
567 }
568
569 public File getMavenHome()
570 {
571 return mavenHome;
572 }
573
574 public void setMavenHome( File mavenHome )
575 {
576 this.mavenHome = mavenHome;
577 }
578
579 public File getWorkingDirectory()
580 {
581 return workingDirectory;
582 }
583
584 public void setWorkingDirectory( File workingDirectory )
585 {
586 this.workingDirectory = workingDirectory;
587 }
588
589 }