Skip to content

Commit e6c96bf

Browse files
committed
Avoid NullPointerException in CommandLine.getOptionValues(Option|String)
1 parent 95e3a60 commit e6c96bf

4 files changed

Lines changed: 30 additions & 9 deletions

File tree

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<action type="fix" issue="CLI-325" dev="ggregory" due-to="Claude Warren">Properties from multiple arguments with value separator. #237.</action>
3131
<action type="fix" issue="CLI-327" dev="ggregory" due-to="Claude Warren, Gary Gregory">Fix for expected textual date values. #244.</action>
3232
<action type="fix" dev="ggregory" due-to="Gary Gregory">Option.Builder.option("") should throw IllegalArgumentException instead of ArrayIndexOutOfBoundsException.</action>
33+
<action type="fix" dev="ggregory" due-to="Gary Gregory">Avoid NullPointerException in CommandLine.getOptionValues(Option|String).</action>
3334
<!-- ADD -->
3435
<action type="add" issue="CLI-321" dev="ggregory" due-to="Claude Warren, Gary Gregory">Add and use a Converter interface and implementations without using BeanUtils #216.</action>
3536
<action type="add" dev="ggregory" due-to="Gary Gregory">Add Maven property project.build.outputTimestamp for build reproducibility.</action>

src/main/java/org/apache/commons/cli/CommandLine.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ protected void addOption(final Option opt) {
179179
}
180180
}
181181

182+
private <T> T get(final Supplier<T> supplier) {
183+
return supplier == null ? null : supplier.get();
184+
}
185+
182186
/**
183187
* Gets any left-over non-recognized options and arguments
184188
*
@@ -317,9 +321,6 @@ public String getOptionValue(final char opt, final Supplier<String> defaultValue
317321
* @since 1.5.0
318322
*/
319323
public String getOptionValue(final Option option) {
320-
if (option == null) {
321-
return null;
322-
}
323324
final String[] values = getOptionValues(option);
324325
return values == null ? null : values[0];
325326
}
@@ -346,7 +347,7 @@ public String getOptionValue(final Option option, final String defaultValue) {
346347
*/
347348
public String getOptionValue(final Option option, final Supplier<String> defaultValue) {
348349
final String answer = getOptionValue(option);
349-
return answer != null ? answer : defaultValue.get();
350+
return answer != null ? answer : get(defaultValue);
350351
}
351352

352353
/**
@@ -382,6 +383,7 @@ public String getOptionValue(final String opt, final Supplier<String> defaultVal
382383
return getOptionValue(resolveOption(opt), defaultValue);
383384
}
384385

386+
385387
/**
386388
* Gets the array of values, if any, of an option.
387389
*
@@ -392,7 +394,6 @@ public String[] getOptionValues(final char opt) {
392394
return getOptionValues(String.valueOf(opt));
393395
}
394396

395-
396397
/**
397398
* Gets the array of values, if any, of an option.
398399
*
@@ -401,6 +402,9 @@ public String[] getOptionValues(final char opt) {
401402
* @since 1.5.0
402403
*/
403404
public String[] getOptionValues(final Option option) {
405+
if (option == null) {
406+
return null;
407+
}
404408
final List<String> values = new ArrayList<>();
405409
for (final Option processedOption : options) {
406410
if (processedOption.equals(option)) {
@@ -491,10 +495,13 @@ public <T> T getParsedOptionValue(final Option option) throws ParseException {
491495
*/
492496
@SuppressWarnings("unchecked")
493497
public <T> T getParsedOptionValue(final Option option, final Supplier<T> defaultValue) throws ParseException {
494-
final String res = option == null ? null : getOptionValue(option);
498+
if (option == null) {
499+
return get(defaultValue);
500+
}
501+
final String res = getOptionValue(option);
495502
try {
496503
if (res == null) {
497-
return defaultValue == null ? null : defaultValue.get();
504+
return get(defaultValue);
498505
}
499506
return (T) option.getConverter().apply(res);
500507
} catch (final Throwable e) {

src/main/java/org/apache/commons/cli/HelpFormatter.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ Licensed to the Apache Software Foundation (ASF) under one or more
1919

2020
import java.io.BufferedReader;
2121
import java.io.IOException;
22-
import java.io.PrintStream;
2322
import java.io.PrintWriter;
2423
import java.io.Serializable;
2524
import java.io.StringReader;

src/test/java/org/apache/commons/cli/ValueTest.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ Licensed to the Apache Software Foundation (ASF) under one or more
2727

2828
@SuppressWarnings("deprecation") // tests some deprecated classes
2929
public class ValueTest {
30-
private CommandLine cl;
30+
31+
private static final Option NULL_OPTION = null;
32+
private static final String NULL_STRING = null;
33+
3134
private final Options opts = new Options();
35+
private CommandLine cl;
3236

3337
@BeforeEach
3438
public void setUp() throws Exception {
@@ -78,6 +82,8 @@ public void testLongOptionalArgValues() throws Exception {
7882

7983
final Parser parser = new PosixParser();
8084
final CommandLine cmd = parser.parse(opts, args);
85+
assertNull(cmd.getOptionValues(NULL_OPTION));
86+
assertNull(cmd.getOptionValues(NULL_STRING));
8187
assertTrue(cmd.hasOption("gravy"));
8288
assertEquals("gold", cmd.getOptionValue("gravy"));
8389
assertEquals("gold", cmd.getOptionValues("gravy")[0]);
@@ -91,6 +97,8 @@ public void testLongOptionalArgValuesWithOption() throws Exception {
9197

9298
final Parser parser = new PosixParser();
9399
final CommandLine cmd = parser.parse(opts, args);
100+
assertNull(cmd.getOptionValues(NULL_OPTION));
101+
assertNull(cmd.getOptionValues(NULL_STRING));
94102
assertTrue(cmd.hasOption(opts.getOption("gravy")));
95103
assertEquals("gold", cmd.getOptionValue(opts.getOption("gravy")));
96104
assertEquals("gold", cmd.getOptionValues(opts.getOption("gravy"))[0]);
@@ -130,6 +138,8 @@ public void testLongOptionalNArgValuesWithOption() throws Exception {
130138
final Parser parser = new PosixParser();
131139

132140
final CommandLine cmd = parser.parse(opts, args);
141+
assertNull(cmd.getOptionValues(NULL_OPTION));
142+
assertNull(cmd.getOptionValues(NULL_STRING));
133143
assertTrue(cmd.hasOption(opts.getOption("hide")));
134144
assertEquals("house", cmd.getOptionValue(opts.getOption("hide")));
135145
assertEquals("house", cmd.getOptionValues(opts.getOption("hide"))[0]);
@@ -233,6 +243,8 @@ public void testShortOptionalArgValuesWithOption() throws Exception {
233243

234244
final Parser parser = new PosixParser();
235245
final CommandLine cmd = parser.parse(opts, args);
246+
assertNull(cmd.getOptionValues(NULL_OPTION));
247+
assertNull(cmd.getOptionValues(NULL_STRING));
236248
assertTrue(cmd.hasOption(opts.getOption("j")));
237249
assertEquals("ink", cmd.getOptionValue(opts.getOption("j")));
238250
assertEquals("ink", cmd.getOptionValues(opts.getOption("j"))[0]);
@@ -271,6 +283,8 @@ public void testShortOptionalNArgValuesWithOption() throws Exception {
271283

272284
final Parser parser = new PosixParser();
273285
final CommandLine cmd = parser.parse(opts, args);
286+
assertNull(cmd.getOptionValues(NULL_OPTION));
287+
assertNull(cmd.getOptionValues(NULL_STRING));
274288
assertTrue(cmd.hasOption("i"));
275289
assertEquals("ink", cmd.getOptionValue(opts.getOption("i")));
276290
assertEquals("ink", cmd.getOptionValues(opts.getOption("i"))[0]);

0 commit comments

Comments
 (0)