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