From 5a7bfa9decfa9ed6473399daf3d8c318c4edbb50 Mon Sep 17 00:00:00 2001 From: Yanming Zhou Date: Thu, 23 May 2024 09:48:05 +0800 Subject: [PATCH 1/2] Extend nested placeholders resolution to any CharSequence See gh-32876 --- .../env/PropertySourcesPropertyResolver.java | 7 ++-- .../PropertySourcesPropertyResolverTests.java | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/env/PropertySourcesPropertyResolver.java b/spring-core/src/main/java/org/springframework/core/env/PropertySourcesPropertyResolver.java index b97fad87484..c008e8088ce 100644 --- a/spring-core/src/main/java/org/springframework/core/env/PropertySourcesPropertyResolver.java +++ b/spring-core/src/main/java/org/springframework/core/env/PropertySourcesPropertyResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2024 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. @@ -24,6 +24,7 @@ import org.springframework.lang.Nullable; * * @author Chris Beams * @author Juergen Hoeller + * @author Yanming Zhou * @since 3.1 * @see PropertySource * @see PropertySources @@ -84,8 +85,8 @@ public class PropertySourcesPropertyResolver extends AbstractPropertyResolver { } Object value = propertySource.getProperty(key); if (value != null) { - if (resolveNestedPlaceholders && value instanceof String string) { - value = resolveNestedPlaceholders(string); + if (resolveNestedPlaceholders && value instanceof CharSequence cs) { + value = resolveNestedPlaceholders(cs.toString()); } logKeyFound(key, propertySource, value); return convertValueIfNecessary(value, targetValueType); diff --git a/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java b/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java index d442f6a0cb7..dcaa4dd6d92 100644 --- a/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java +++ b/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java @@ -34,6 +34,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; /** * @author Chris Beams + * @author Yanming Zhou * @since 3.1 */ class PropertySourcesPropertyResolverTests { @@ -300,6 +301,43 @@ class PropertySourcesPropertyResolverTests { .withMessageContaining("Circular"); } + @Test + void resolveNestedPlaceholdersIfValueIsCharSequence() { + MutablePropertySources ps = new MutablePropertySources(); + ps.addFirst(new MockPropertySource() + .withProperty("p1", "v1") + .withProperty("p2", "v2") + .withProperty("p3", new CharSequence() { + + static final String underlying = "${p1}:${p2}"; + + @Override + public int length() { + return underlying.length(); + } + + @Override + public char charAt(int index) { + return underlying.charAt(index); + } + + @Override + public CharSequence subSequence(int start, int end) { + return underlying.subSequence(start, end); + } + + @Override + public String toString() { + return underlying; + } + }) + ); + ConfigurablePropertyResolver pr = new PropertySourcesPropertyResolver(ps); + assertThat(pr.getProperty("p1")).isEqualTo("v1"); + assertThat(pr.getProperty("p2")).isEqualTo("v2"); + assertThat(pr.getProperty("p3")).isEqualTo("v1:v2"); + } + @Test void ignoreUnresolvableNestedPlaceholdersIsConfigurable() { MutablePropertySources ps = new MutablePropertySources(); From 79b5ee75d3a0a504884280242048f5ba38ab4730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Thu, 23 May 2024 08:36:34 +0200 Subject: [PATCH 2/2] Polish "Extend nested placeholders resolution to any CharSequence" See gh-32876 --- .../env/PropertySourcesPropertyResolver.java | 1 - .../PropertySourcesPropertyResolverTests.java | 27 +------------------ 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/env/PropertySourcesPropertyResolver.java b/spring-core/src/main/java/org/springframework/core/env/PropertySourcesPropertyResolver.java index c008e8088ce..5ab89cf9027 100644 --- a/spring-core/src/main/java/org/springframework/core/env/PropertySourcesPropertyResolver.java +++ b/spring-core/src/main/java/org/springframework/core/env/PropertySourcesPropertyResolver.java @@ -24,7 +24,6 @@ import org.springframework.lang.Nullable; * * @author Chris Beams * @author Juergen Hoeller - * @author Yanming Zhou * @since 3.1 * @see PropertySource * @see PropertySources diff --git a/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java b/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java index dcaa4dd6d92..a6344b10585 100644 --- a/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java +++ b/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java @@ -34,7 +34,6 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; /** * @author Chris Beams - * @author Yanming Zhou * @since 3.1 */ class PropertySourcesPropertyResolverTests { @@ -307,31 +306,7 @@ class PropertySourcesPropertyResolverTests { ps.addFirst(new MockPropertySource() .withProperty("p1", "v1") .withProperty("p2", "v2") - .withProperty("p3", new CharSequence() { - - static final String underlying = "${p1}:${p2}"; - - @Override - public int length() { - return underlying.length(); - } - - @Override - public char charAt(int index) { - return underlying.charAt(index); - } - - @Override - public CharSequence subSequence(int start, int end) { - return underlying.subSequence(start, end); - } - - @Override - public String toString() { - return underlying; - } - }) - ); + .withProperty("p3", new StringBuilder("${p1}:${p2}"))); ConfigurablePropertyResolver pr = new PropertySourcesPropertyResolver(ps); assertThat(pr.getProperty("p1")).isEqualTo("v1"); assertThat(pr.getProperty("p2")).isEqualTo("v2");