1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.cling.invoker.mvn;
20
21 import java.util.Arrays;
22 import java.util.List;
23 import java.util.ListIterator;
24 import java.util.Optional;
25 import java.util.function.UnaryOperator;
26
27 import org.apache.commons.cli.CommandLine;
28 import org.apache.commons.cli.Option;
29 import org.apache.commons.cli.ParseException;
30 import org.apache.maven.api.cli.mvn.MavenOptions;
31 import org.apache.maven.api.services.Interpolator;
32 import org.apache.maven.api.services.InterpolatorException;
33 import org.apache.maven.cling.invoker.CommonsCliOptions;
34
35 import static org.apache.maven.cling.invoker.Utils.createInterpolator;
36
37 public class CommonsCliMavenOptions extends CommonsCliOptions implements MavenOptions {
38 public static CommonsCliMavenOptions parse(String source, String[] args) throws ParseException {
39 CLIManager cliManager = new CLIManager();
40 return new CommonsCliMavenOptions(source, cliManager, cliManager.parse(args));
41 }
42
43 protected CommonsCliMavenOptions(String source, CLIManager cliManager, CommandLine commandLine) {
44 super(source, cliManager, commandLine);
45 }
46
47 private static CommonsCliMavenOptions interpolate(CommonsCliMavenOptions options, UnaryOperator<String> callback) {
48 try {
49
50 Interpolator interpolator = createInterpolator();
51 CommandLine.Builder commandLineBuilder = new CommandLine.Builder();
52 commandLineBuilder.setDeprecatedHandler(o -> {});
53 for (Option option : options.commandLine.getOptions()) {
54 if (!CLIManager.USER_PROPERTY.equals(option.getOpt())) {
55 List<String> values = option.getValuesList();
56 for (ListIterator<String> it = values.listIterator(); it.hasNext(); ) {
57 it.set(interpolator.interpolate(it.next(), callback));
58 }
59 }
60 commandLineBuilder.addOption(option);
61 }
62 for (String arg : options.commandLine.getArgList()) {
63 commandLineBuilder.addArg(interpolator.interpolate(arg, callback));
64 }
65 return new CommonsCliMavenOptions(
66 options.source, (CLIManager) options.cliManager, commandLineBuilder.build());
67 } catch (InterpolatorException e) {
68 throw new IllegalArgumentException("Could not interpolate CommonsCliOptions", e);
69 }
70 }
71
72 @Override
73 public Optional<String> alternatePomFile() {
74 if (commandLine.hasOption(CLIManager.ALTERNATE_POM_FILE)) {
75 return Optional.of(commandLine.getOptionValue(CLIManager.ALTERNATE_POM_FILE));
76 }
77 return Optional.empty();
78 }
79
80 @Override
81 public Optional<Boolean> nonRecursive() {
82 if (commandLine.hasOption(CLIManager.NON_RECURSIVE)) {
83 return Optional.of(Boolean.TRUE);
84 }
85 return Optional.empty();
86 }
87
88 @Override
89 public Optional<Boolean> updateSnapshots() {
90 if (commandLine.hasOption(CLIManager.UPDATE_SNAPSHOTS)) {
91 return Optional.of(Boolean.TRUE);
92 }
93 return Optional.empty();
94 }
95
96 @Override
97 public Optional<List<String>> activatedProfiles() {
98 if (commandLine.hasOption(CLIManager.ACTIVATE_PROFILES)) {
99 return Optional.of(Arrays.asList(commandLine.getOptionValues(CLIManager.ACTIVATE_PROFILES)));
100 }
101 return Optional.empty();
102 }
103
104 @Override
105 public Optional<Boolean> suppressSnapshotUpdates() {
106 if (commandLine.hasOption(CLIManager.SUPPRESS_SNAPSHOT_UPDATES)) {
107 return Optional.of(Boolean.TRUE);
108 }
109 return Optional.empty();
110 }
111
112 @Override
113 public Optional<Boolean> strictChecksums() {
114 if (commandLine.hasOption(CLIManager.CHECKSUM_FAILURE_POLICY)) {
115 return Optional.of(Boolean.TRUE);
116 }
117 return Optional.empty();
118 }
119
120 @Override
121 public Optional<Boolean> relaxedChecksums() {
122 if (commandLine.hasOption(CLIManager.CHECKSUM_WARNING_POLICY)) {
123 return Optional.of(Boolean.TRUE);
124 }
125 return Optional.empty();
126 }
127
128 @Override
129 public Optional<Boolean> failFast() {
130 if (commandLine.hasOption(CLIManager.FAIL_FAST)) {
131 return Optional.of(Boolean.TRUE);
132 }
133 return Optional.empty();
134 }
135
136 @Override
137 public Optional<Boolean> failAtEnd() {
138 if (commandLine.hasOption(CLIManager.FAIL_AT_END)) {
139 return Optional.of(Boolean.TRUE);
140 }
141 return Optional.empty();
142 }
143
144 @Override
145 public Optional<Boolean> failNever() {
146 if (commandLine.hasOption(CLIManager.FAIL_NEVER)) {
147 return Optional.of(Boolean.TRUE);
148 }
149 return Optional.empty();
150 }
151
152 @Override
153 public Optional<Boolean> resume() {
154 if (commandLine.hasOption(CLIManager.RESUME)) {
155 return Optional.of(Boolean.TRUE);
156 }
157 return Optional.empty();
158 }
159
160 @Override
161 public Optional<String> resumeFrom() {
162 if (commandLine.hasOption(CLIManager.RESUME_FROM)) {
163 return Optional.of(commandLine.getOptionValue(CLIManager.RESUME_FROM));
164 }
165 return Optional.empty();
166 }
167
168 @Override
169 public Optional<List<String>> projects() {
170 if (commandLine.hasOption(CLIManager.PROJECT_LIST)) {
171 return Optional.of(Arrays.asList(commandLine.getOptionValues(CLIManager.PROJECT_LIST)));
172 }
173 return Optional.empty();
174 }
175
176 @Override
177 public Optional<Boolean> alsoMake() {
178 if (commandLine.hasOption(CLIManager.ALSO_MAKE)) {
179 return Optional.of(Boolean.TRUE);
180 }
181 return Optional.empty();
182 }
183
184 @Override
185 public Optional<Boolean> alsoMakeDependents() {
186 if (commandLine.hasOption(CLIManager.ALSO_MAKE_DEPENDENTS)) {
187 return Optional.of(Boolean.TRUE);
188 }
189 return Optional.empty();
190 }
191
192 @Override
193 public Optional<String> threads() {
194 if (commandLine.hasOption(CLIManager.THREADS)) {
195 return Optional.of(commandLine.getOptionValue(CLIManager.THREADS));
196 }
197 return Optional.empty();
198 }
199
200 @Override
201 public Optional<String> builder() {
202 if (commandLine.hasOption(CLIManager.BUILDER)) {
203 return Optional.of(commandLine.getOptionValue(CLIManager.BUILDER));
204 }
205 return Optional.empty();
206 }
207
208 @Override
209 public Optional<Boolean> noTransferProgress() {
210 if (commandLine.hasOption(CLIManager.NO_TRANSFER_PROGRESS)) {
211 return Optional.of(Boolean.TRUE);
212 }
213 return Optional.empty();
214 }
215
216 @Override
217 public Optional<Boolean> cacheArtifactNotFound() {
218 if (commandLine.hasOption(CLIManager.CACHE_ARTIFACT_NOT_FOUND)) {
219 return Optional.of(Boolean.parseBoolean(commandLine.getOptionValue(CLIManager.CACHE_ARTIFACT_NOT_FOUND)));
220 }
221 return Optional.empty();
222 }
223
224 @Override
225 public Optional<Boolean> strictArtifactDescriptorPolicy() {
226 if (commandLine.hasOption(CLIManager.STRICT_ARTIFACT_DESCRIPTOR_POLICY)) {
227 return Optional.of(
228 Boolean.parseBoolean(commandLine.getOptionValue(CLIManager.STRICT_ARTIFACT_DESCRIPTOR_POLICY)));
229 }
230 return Optional.empty();
231 }
232
233 @Override
234 public Optional<Boolean> ignoreTransitiveRepositories() {
235 if (commandLine.hasOption(CLIManager.IGNORE_TRANSITIVE_REPOSITORIES)) {
236 return Optional.of(Boolean.TRUE);
237 }
238 return Optional.empty();
239 }
240
241 @Override
242 public Optional<String> atFile() {
243 if (commandLine.hasOption(CLIManager.AT_FILE)) {
244 return Optional.of(commandLine.getOptionValue(CLIManager.AT_FILE));
245 }
246 return Optional.empty();
247 }
248
249 @Override
250 public Optional<List<String>> goals() {
251 if (!commandLine.getArgList().isEmpty()) {
252 return Optional.of(commandLine.getArgList());
253 }
254 return Optional.empty();
255 }
256
257 @Override
258 public MavenOptions interpolate(UnaryOperator<String> callback) {
259 return interpolate(this, callback);
260 }
261
262 protected static class CLIManager extends CommonsCliOptions.CLIManager {
263 public static final String ALTERNATE_POM_FILE = "f";
264 public static final String NON_RECURSIVE = "N";
265 public static final String UPDATE_SNAPSHOTS = "U";
266 public static final String ACTIVATE_PROFILES = "P";
267 public static final String SUPPRESS_SNAPSHOT_UPDATES = "nsu";
268 public static final String CHECKSUM_FAILURE_POLICY = "C";
269 public static final String CHECKSUM_WARNING_POLICY = "c";
270 public static final String FAIL_FAST = "ff";
271 public static final String FAIL_AT_END = "fae";
272 public static final String FAIL_NEVER = "fn";
273 public static final String RESUME = "r";
274 public static final String RESUME_FROM = "rf";
275 public static final String PROJECT_LIST = "pl";
276 public static final String ALSO_MAKE = "am";
277 public static final String ALSO_MAKE_DEPENDENTS = "amd";
278 public static final String THREADS = "T";
279 public static final String BUILDER = "b";
280 public static final String NO_TRANSFER_PROGRESS = "ntp";
281 public static final String CACHE_ARTIFACT_NOT_FOUND = "canf";
282 public static final String STRICT_ARTIFACT_DESCRIPTOR_POLICY = "sadp";
283 public static final String IGNORE_TRANSITIVE_REPOSITORIES = "itr";
284 public static final String AT_FILE = "af";
285
286 @Override
287 protected void prepareOptions(org.apache.commons.cli.Options options) {
288 super.prepareOptions(options);
289 options.addOption(Option.builder(ALTERNATE_POM_FILE)
290 .longOpt("file")
291 .hasArg()
292 .desc("Force the use of an alternate POM file (or directory with pom.xml)")
293 .build());
294 options.addOption(Option.builder(NON_RECURSIVE)
295 .longOpt("non-recursive")
296 .desc(
297 "Do not recurse into sub-projects. When used together with -pl, do not recurse into sub-projects of selected aggregators")
298 .build());
299 options.addOption(Option.builder(UPDATE_SNAPSHOTS)
300 .longOpt("update-snapshots")
301 .desc("Forces a check for missing releases and updated snapshots on remote repositories")
302 .build());
303 options.addOption(Option.builder(ACTIVATE_PROFILES)
304 .longOpt("activate-profiles")
305 .desc(
306 "Comma-delimited list of profiles to activate. Prefixing a profile with ! excludes it, and ? marks it as optional")
307 .hasArg()
308 .build());
309 options.addOption(Option.builder(SUPPRESS_SNAPSHOT_UPDATES)
310 .longOpt("no-snapshot-updates")
311 .desc("Suppress SNAPSHOT updates")
312 .build());
313 options.addOption(Option.builder(CHECKSUM_FAILURE_POLICY)
314 .longOpt("strict-checksums")
315 .desc("Fail the build if checksums don't match")
316 .build());
317 options.addOption(Option.builder(CHECKSUM_WARNING_POLICY)
318 .longOpt("lax-checksums")
319 .desc("Warn if checksums don't match")
320 .build());
321 options.addOption(Option.builder(FAIL_FAST)
322 .longOpt("fail-fast")
323 .desc("Stop at first failure in reactorized builds")
324 .build());
325 options.addOption(Option.builder(FAIL_AT_END)
326 .longOpt("fail-at-end")
327 .desc("Only fail the build afterwards; allow all non-impacted builds to continue")
328 .build());
329 options.addOption(Option.builder(FAIL_NEVER)
330 .longOpt("fail-never")
331 .desc("NEVER fail the build, regardless of project result")
332 .build());
333 options.addOption(Option.builder(RESUME)
334 .longOpt("resume")
335 .desc(
336 "Resume reactor from the last failed project, using the resume.properties file in the build directory")
337 .build());
338 options.addOption(Option.builder(RESUME_FROM)
339 .longOpt("resume-from")
340 .hasArg()
341 .desc("Resume reactor from specified project")
342 .build());
343 options.addOption(Option.builder(PROJECT_LIST)
344 .longOpt("projects")
345 .desc(
346 "Comma-delimited list of specified reactor projects to build instead of all projects. A project can be specified by [groupId]:artifactId or by its relative path. Prefixing a project with ! excludes it, and ? marks it as optional")
347 .hasArg()
348 .build());
349 options.addOption(Option.builder(ALSO_MAKE)
350 .longOpt("also-make")
351 .desc("If project list is specified, also build projects required by the list")
352 .build());
353 options.addOption(Option.builder(ALSO_MAKE_DEPENDENTS)
354 .longOpt("also-make-dependents")
355 .desc("If project list is specified, also build projects that depend on projects on the list")
356 .build());
357 options.addOption(Option.builder(THREADS)
358 .longOpt("threads")
359 .hasArg()
360 .desc("Thread count, for instance 4 (int) or 2C/2.5C (int/float) where C is core multiplied")
361 .build());
362 options.addOption(Option.builder(BUILDER)
363 .longOpt("builder")
364 .hasArg()
365 .desc("The id of the build strategy to use")
366 .build());
367 options.addOption(Option.builder(NO_TRANSFER_PROGRESS)
368 .longOpt("no-transfer-progress")
369 .desc("Do not display transfer progress when downloading or uploading")
370 .build());
371 options.addOption(Option.builder(CACHE_ARTIFACT_NOT_FOUND)
372 .longOpt("cache-artifact-not-found")
373 .hasArg()
374 .desc(
375 "Defines caching behaviour for 'not found' artifacts. Supported values are 'true' (default), 'false'.")
376 .build());
377 options.addOption(Option.builder(STRICT_ARTIFACT_DESCRIPTOR_POLICY)
378 .longOpt("strict-artifact-descriptor-policy")
379 .hasArg()
380 .desc(
381 "Defines 'strict' artifact descriptor policy. Supported values are 'true', 'false' (default).")
382 .build());
383 options.addOption(Option.builder(IGNORE_TRANSITIVE_REPOSITORIES)
384 .longOpt("ignore-transitive-repositories")
385 .desc("If set, Maven will ignore remote repositories introduced by transitive dependencies.")
386 .build());
387 options.addOption(Option.builder(AT_FILE)
388 .longOpt("at-file")
389 .hasArg()
390 .desc(
391 "If set, Maven will load command line options from the specified file and merge with CLI specified ones.")
392 .build());
393 }
394 }
395 }