diff --git a/spring-core/src/main/java/org/springframework/core/env/CommandLinePropertySource.java b/spring-core/src/main/java/org/springframework/core/env/CommandLinePropertySource.java index a49d3e93d89..20bcc1a95c2 100644 --- a/spring-core/src/main/java/org/springframework/core/env/CommandLinePropertySource.java +++ b/spring-core/src/main/java/org/springframework/core/env/CommandLinePropertySource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 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,8 +25,7 @@ import org.springframework.util.StringUtils; /** * Abstract base class for {@link PropertySource} implementations backed by command line * arguments. The parameterized type {@code T} represents the underlying source of command - * line options. For instance, {@link SimpleCommandLinePropertySource} uses a String - * array. + * line options. * *
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 * without spaces by an equals sign ("="). The value may optionally be - * an empty string. if the option is present and has multiple values (e. g. "--foo=bar --foo=baz"), -* the values are parsed as a collection. + * an empty string. If an option is present multiple times with different values + * — for example, {@code --foo=bar --foo=baz} — all supplied values + * will be stored for the option. * *
diff --git a/spring-core/src/main/java/org/springframework/core/env/SimpleCommandLinePropertySource.java b/spring-core/src/main/java/org/springframework/core/env/SimpleCommandLinePropertySource.java
index 17121c29734..1c4591f3dff 100644
--- a/spring-core/src/main/java/org/springframework/core/env/SimpleCommandLinePropertySource.java
+++ b/spring-core/src/main/java/org/springframework/core/env/SimpleCommandLinePropertySource.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -22,7 +22,8 @@ import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
- * {@link CommandLinePropertySource} implementation backed by a simple String array.
+ * {@link CommandLinePropertySource} implementation backed by an instance of
+ * {@link CommandLineArgs}.
*
* Purpose
* This {@code CommandLinePropertySource} implementation aims to provide the simplest
@@ -40,8 +41,9 @@ import org.springframework.util.StringUtils;
*
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
* without spaces by an equals sign ("="). The value may optionally be
- * an empty string. if the option is present and has multiple values (e. g. "--foo=bar --foo=baz"),
- * the values are parsed as a collection.
+ * an empty string. If an option is present multiple times with different values
+ * — for example, {@code --foo=bar --foo=baz} — all supplied values
+ * will be stored for the option.
*
*
Valid examples of option arguments
*
diff --git a/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLineArgsParserTests.java b/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLineArgsParserTests.java
index 180dfa8fbce..e7dad041c18 100644
--- a/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLineArgsParserTests.java
+++ b/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLineArgsParserTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -46,7 +46,7 @@ class SimpleCommandLineArgsParserTests {
void withSingleOptionAndNoValue() {
CommandLineArgs args = parser.parse("--o1");
assertThat(args.containsOption("o1")).isTrue();
- assertThat(args.getOptionValues("o1")).isEqualTo(Collections.EMPTY_LIST);
+ assertThat(args.getOptionValues("o1")).isEmpty();
}
@Test
@@ -56,6 +56,20 @@ class SimpleCommandLineArgsParserTests {
assertThat(args.getOptionValues("o1")).containsExactly("v1");
}
+ @Test
+ void withRepeatedOptionAndSameValues() {
+ CommandLineArgs args = parser.parse("--o1=v1", "--o1=v1", "--o1=v1");
+ assertThat(args.containsOption("o1")).isTrue();
+ assertThat(args.getOptionValues("o1")).containsExactly("v1", "v1", "v1");
+ }
+
+ @Test
+ void withRepeatedOptionAndDifferentValues() {
+ CommandLineArgs args = parser.parse("--o1=v1", "--o1=v2", "--o1=v3");
+ assertThat(args.containsOption("o1")).isTrue();
+ assertThat(args.getOptionValues("o1")).containsExactly("v1", "v2", "v3");
+ }
+
@Test
void withMixOfOptionsHavingValueAndOptionsHavingNoValue() {
CommandLineArgs args = parser.parse("--o1=v1", "--o2");
@@ -95,17 +109,17 @@ class SimpleCommandLineArgsParserTests {
}
@Test
- void assertOptionNamesIsUnmodifiable() {
+ void optionNamesSetIsUnmodifiable() {
CommandLineArgs args = new SimpleCommandLineArgsParser().parse();
- assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() ->
- args.getOptionNames().add("bogus"));
+ assertThatExceptionOfType(UnsupportedOperationException.class)
+ .isThrownBy(() -> args.getOptionNames().add("bogus"));
}
@Test
- void assertNonOptionArgsIsUnmodifiable() {
+ void nonOptionArgsListIsUnmodifiable() {
CommandLineArgs args = new SimpleCommandLineArgsParser().parse();
- assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() ->
- args.getNonOptionArgs().add("foo"));
+ assertThatExceptionOfType(UnsupportedOperationException.class)
+ .isThrownBy(() -> args.getNonOptionArgs().add("foo"));
}
@Test
diff --git a/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLinePropertySourceTests.java b/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLinePropertySourceTests.java
index 86923da26ea..9d6d4979e35 100644
--- a/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLinePropertySourceTests.java
+++ b/spring-core/src/test/java/org/springframework/core/env/SimpleCommandLinePropertySourceTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -61,6 +61,15 @@ class SimpleCommandLinePropertySourceTests {
assertThat(ps.getProperty("o3")).isNull();
}
+ @Test // gh-34282
+ void withRepeatedOptionArgs() {
+ CommandLinePropertySource> ps = new SimpleCommandLinePropertySource("--o1=v1", "--o1=v2", "--o1=v3");
+ assertThat(ps.containsProperty("o1")).isTrue();
+ assertThat(ps.containsProperty("o2")).isFalse();
+ assertThat(ps.getProperty("o1")).isEqualTo("v1,v2,v3");
+ assertThat(ps.getProperty("o2")).isNull();
+ }
+
@Test // gh-24464
void withOptionalArg_andArgIsEmpty() {
EnumerablePropertySource> ps = new SimpleCommandLinePropertySource("--foo=");