Support optional command line arguments with empty values

Spring Framework provides two implementations of the
CommandLinePropertySource API: SimpleCommandLinePropertySource and
JOptCommandLinePropertySource.

Prior to this commit, JOptCommandLinePropertySource supported empty
values for optional arguments; whereas, SimpleCommandLinePropertySource
did not.

This commit modifies the implementation of SimpleCommandLinePropertySource
to allow empty values for optional arguments.

Closes gh-24464
This commit is contained in:
Sam Brannen
2020-02-03 15:03:43 +01:00
parent 8dfacbc210
commit d77a28aac3
5 changed files with 85 additions and 55 deletions

View File

@@ -21,15 +21,20 @@ package org.springframework.core.env;
* {@link CommandLineArgs} object.
*
* <h3>Working with option arguments</h3>
* Option arguments must adhere to the exact syntax:
* <p>Option arguments must adhere to the exact syntax:
*
* <pre class="code">--optName[=optValue]</pre>
* That is, options must be prefixed with "{@code --}", and may or may not specify a value.
* If a value is specified, the name and value must be separated <em>without spaces</em>
* by an equals sign ("=").
*
* <p>That is, options must be prefixed with "{@code --}" and may or may not
* specify a value. If a value is specified, the name and value must be separated
* <em>without spaces</em> by an equals sign ("="). The value may optionally be
* an empty string.
*
* <h4>Valid examples of option arguments</h4>
* <pre class="code">
* --foo
* --foo=
* --foo=""
* --foo=bar
* --foo="bar then baz"
* --foo=bar,baz,biz</pre>
@@ -42,11 +47,12 @@ package org.springframework.core.env;
* --foo=bar --foo=baz --foo=biz</pre>
*
* <h3>Working with non-option arguments</h3>
* Any and all arguments specified at the command line without the "{@code --}" option
* prefix will be considered as "non-option arguments" and made available through the
* {@link CommandLineArgs#getNonOptionArgs()} method.
* <p>Any and all arguments specified at the command line without the "{@code --}"
* option prefix will be considered as "non-option arguments" and made available
* through the {@link CommandLineArgs#getNonOptionArgs()} method.
*
* @author Chris Beams
* @author Sam Brannen
* @since 3.1
*/
class SimpleCommandLineArgsParser {
@@ -61,17 +67,18 @@ class SimpleCommandLineArgsParser {
CommandLineArgs commandLineArgs = new CommandLineArgs();
for (String arg : args) {
if (arg.startsWith("--")) {
String optionText = arg.substring(2, arg.length());
String optionText = arg.substring(2);
String optionName;
String optionValue = null;
if (optionText.contains("=")) {
optionName = optionText.substring(0, optionText.indexOf('='));
optionValue = optionText.substring(optionText.indexOf('=') + 1, optionText.length());
int indexOfEqualsSign = optionText.indexOf('=');
if (indexOfEqualsSign > -1) {
optionName = optionText.substring(0, indexOfEqualsSign);
optionValue = optionText.substring(indexOfEqualsSign + 1);
}
else {
optionName = optionText;
}
if (optionName.isEmpty() || (optionValue != null && optionValue.isEmpty())) {
if (optionName.isEmpty()) {
throw new IllegalArgumentException("Invalid argument syntax: " + arg);
}
commandLineArgs.addOptionArg(optionName, optionValue);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,22 +25,28 @@ import org.springframework.util.StringUtils;
* {@link CommandLinePropertySource} implementation backed by a simple String array.
*
* <h3>Purpose</h3>
* This {@code CommandLinePropertySource} implementation aims to provide the simplest
* possible approach to parsing command line arguments. As with all {@code
* <p>This {@code CommandLinePropertySource} implementation aims to provide the simplest
* possible approach to parsing command line arguments. As with all {@code
* CommandLinePropertySource} implementations, command line arguments are broken into two
* distinct groups: <em>option arguments</em> and <em>non-option arguments</em>, as
* described below <em>(some sections copied from Javadoc for {@link SimpleCommandLineArgsParser})</em>:
* described below <em>(some sections copied from Javadoc for
* {@link SimpleCommandLineArgsParser})</em>:
*
* <h3>Working with option arguments</h3>
* Option arguments must adhere to the exact syntax:
* <p>Option arguments must adhere to the exact syntax:
*
* <pre class="code">--optName[=optValue]</pre>
* That is, options must be prefixed with "{@code --}", and may or may not specify a value.
* If a value is specified, the name and value must be separated <em>without spaces</em>
* by an equals sign ("=").
*
* <p>That is, options must be prefixed with "{@code --}" and may or may not
* specify a value. If a value is specified, the name and value must be separated
* <em>without spaces</em> by an equals sign ("="). The value may optionally be
* an empty string.
*
* <h4>Valid examples of option arguments</h4>
* <pre class="code">
* --foo
* --foo=
* --foo=""
* --foo=bar
* --foo="bar then baz"
* --foo=bar,baz,biz</pre>
@@ -53,11 +59,11 @@ import org.springframework.util.StringUtils;
* --foo=bar --foo=baz --foo=biz</pre>
*
* <h3>Working with non-option arguments</h3>
* Any and all arguments specified at the command line without the "{@code --}" option
* prefix will be considered as "non-option arguments" and made available through the
* {@link #getNonOptionArgs()} method.
* <p>Any and all arguments specified at the command line without the "{@code --}"
* option prefix will be considered as "non-option arguments" and made available
* through the {@link CommandLineArgs#getNonOptionArgs()} method.
*
* <h2>Typical usage</h2>
* <h3>Typical usage</h3>
* <pre class="code">
* public static void main(String[] args) {
* PropertySource<?> ps = new SimpleCommandLinePropertySource(args);
@@ -71,7 +77,7 @@ import org.springframework.util.StringUtils;
* <p>When more fully-featured command line parsing is necessary, consider using
* the provided {@link JOptCommandLinePropertySource}, or implement your own
* {@code CommandLinePropertySource} against the command line parsing library of your
* choice!
* choice.
*
* @author Chris Beams
* @since 3.1