From 233ef67a04df803434316cb86f449db8fb655514 Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Tue, 23 May 2017 14:04:41 -0700 Subject: [PATCH] Allow nested square brackets in map key when binding Fixes gh-3202 --- .../source/ConfigurationPropertyName.java | 23 ++++++++++++------- .../properties/bind/MapBinderTests.java | 9 ++++++++ .../ConfigurationPropertyNameTests.java | 15 ++++++++++++ 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertyName.java b/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertyName.java index a11e0d6a59..b35c3c4ab9 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertyName.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertyName.java @@ -513,17 +513,24 @@ public final class ConfigurationPropertyName int start = 0; boolean indexed = false; int length = name.length(); + int openBracketCount = 0; for (int i = 0; i < length; i++) { char ch = name.charAt(i); - if (indexed && ch == ']') { - processElement(processor, name, start, i + 1, indexed); - start = i + 1; - indexed = false; + if (ch == ']') { + openBracketCount--; + if (openBracketCount == 0) { + processElement(processor, name, start, i + 1, indexed); + start = i + 1; + indexed = false; + } } - else if (!indexed && ch == '[') { - processElement(processor, name, start, i, indexed); - start = i; - indexed = true; + else if (ch == '[') { + openBracketCount++; + if (!indexed) { + processElement(processor, name, start, i, indexed); + start = i; + indexed = true; + } } else if (!indexed && ch == separator) { processElement(processor, name, start, i, indexed); diff --git a/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java b/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java index 5e728cc33a..cd4c216d3c 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java @@ -503,6 +503,15 @@ public class MapBinderTests { assertThat(map.get(0)).containsExactly(8, 9); } + @Test + public void bindingWithSquareBracketMap() throws Exception { + MockConfigurationPropertySource source = new MockConfigurationPropertySource(); + source.put("foo.[x [B] y]", "[ball]"); + this.sources.add(source); + Map map = this.binder.bind("foo", STRING_STRING_MAP).get(); + assertThat(map).containsEntry("x [B] y", "[ball]"); + } + private Bindable> getMapBindable(Class keyGeneric, ResolvableType valueType) { ResolvableType keyType = ResolvableType.forClass(keyGeneric); return Bindable.of(ResolvableType.forClassWithGenerics(Map.class, keyType, valueType)); diff --git a/spring-boot/src/test/java/org/springframework/boot/context/properties/source/ConfigurationPropertyNameTests.java b/spring-boot/src/test/java/org/springframework/boot/context/properties/source/ConfigurationPropertyNameTests.java index 101ae06b72..ced7e6c421 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/properties/source/ConfigurationPropertyNameTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/properties/source/ConfigurationPropertyNameTests.java @@ -175,6 +175,21 @@ public class ConfigurationPropertyNameTests { ConfigurationPropertyName.of("bar]"); } + @Test + public void ofNameWhenMultipleMismatchedBrackets() throws Exception { + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("is not valid"); + ConfigurationPropertyName.of("[a[[[b]ar]"); + } + + @Test + public void ofNameWhenNestedBrackets() throws Exception { + ConfigurationPropertyName name = ConfigurationPropertyName.of("foo[a[c][[b]ar]]"); + assertThat(name.toString()).isEqualTo("foo[a[c][[b]ar]]"); + assertThat(name.getElement(0, Form.ORIGINAL)).isEqualTo("foo"); + assertThat(name.getElement(1, Form.ORIGINAL)).isEqualTo("a[c][[b]ar]"); + } + @Test public void ofNameWithWhitespaceInName() throws Exception { this.thrown.expect(IllegalArgumentException.class);