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