Browse Source

Merge branch '6.2.x'

pull/34977/head
Sam Brannen 10 months ago
parent
commit
680094d74e
  1. 8
      framework-docs/modules/ROOT/pages/appendix.adoc
  2. 7
      framework-docs/modules/ROOT/pages/core/beans/annotation-config/value-annotations.adoc
  3. 15
      framework-docs/modules/ROOT/pages/core/beans/factory-extension.adoc
  4. 11
      framework-docs/modules/ROOT/pages/languages/kotlin/spring-projects-in.adoc
  5. 15
      spring-beans/src/main/java/org/springframework/beans/factory/config/PlaceholderConfigurerSupport.java
  6. 110
      spring-context/src/test/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurerTests.java
  7. 102
      spring-core/src/main/java/org/springframework/core/env/AbstractPropertyResolver.java
  8. 120
      spring-core/src/test/java/org/springframework/core/env/AbstractPropertyResolverTests.java

8
framework-docs/modules/ROOT/pages/appendix.adoc

@ -103,6 +103,14 @@ for details. @@ -103,6 +103,14 @@ for details.
{spring-framework-api}++/objenesis/SpringObjenesis.html#IGNORE_OBJENESIS_PROPERTY_NAME++[`SpringObjenesis`]
for details.
| `spring.placeholder.escapeCharacter.default`
| The default escape character for property placeholder support. If not set, `'\'` will
be used. Can be set to a custom escape character or an empty string to disable support
for an escape character. The default escape character be explicitly overridden in
`PropertySourcesPlaceholderConfigurer` and subclasses of `AbstractPropertyResolver`. See
{spring-framework-api}++/core/env/AbstractPropertyResolver.html#DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME++[`AbstractPropertyResolver`]
for details.
| `spring.test.aot.processing.failOnError`
| A boolean flag that controls whether errors encountered during AOT processing in the
_Spring TestContext Framework_ should result in an exception that fails the overall process.

7
framework-docs/modules/ROOT/pages/core/beans/annotation-config/value-annotations.adoc

@ -101,8 +101,11 @@ NOTE: When configuring a `PropertySourcesPlaceholderConfigurer` using JavaConfig @@ -101,8 +101,11 @@ NOTE: When configuring a `PropertySourcesPlaceholderConfigurer` using JavaConfig
Using the above configuration ensures Spring initialization failure if any `${}`
placeholder could not be resolved. It is also possible to use methods like
`setPlaceholderPrefix`, `setPlaceholderSuffix`, `setValueSeparator`, or
`setEscapeCharacter` to customize placeholders.
`setPlaceholderPrefix()`, `setPlaceholderSuffix()`, `setValueSeparator()`, or
`setEscapeCharacter()` to customize the placeholder syntax. In addition, the default
escape character can be changed or disabled globally by setting the
`spring.placeholder.escapeCharacter.default` property via a JVM system property (or via
the xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism).
NOTE: Spring Boot configures by default a `PropertySourcesPlaceholderConfigurer` bean that
will get properties from `application.properties` and `application.yml` files.

15
framework-docs/modules/ROOT/pages/core/beans/factory-extension.adoc

@ -314,7 +314,7 @@ Thus, marking it for lazy initialization will be ignored, and the @@ -314,7 +314,7 @@ Thus, marking it for lazy initialization will be ignored, and the
[[beans-factory-placeholderconfigurer]]
=== Example: The Class Name Substitution `PropertySourcesPlaceholderConfigurer`
=== Example: Property Placeholder Substitution with `PropertySourcesPlaceholderConfigurer`
You can use the `PropertySourcesPlaceholderConfigurer` to externalize property values
from a bean definition in a separate file by using the standard Java `Properties` format.
@ -341,7 +341,7 @@ with placeholder values is defined: @@ -341,7 +341,7 @@ with placeholder values is defined:
The example shows properties configured from an external `Properties` file. At runtime,
a `PropertySourcesPlaceholderConfigurer` is applied to the metadata that replaces some
properties of the DataSource. The values to replace are specified as placeholders of the
properties of the `DataSource`. The values to replace are specified as placeholders of the
form pass:q[`${property-name}`], which follows the Ant, log4j, and JSP EL style.
The actual values come from another file in the standard Java `Properties` format:
@ -355,10 +355,13 @@ jdbc.password=root @@ -355,10 +355,13 @@ jdbc.password=root
----
Therefore, the `${jdbc.username}` string is replaced at runtime with the value, 'sa', and
the same applies for other placeholder values that match keys in the properties file.
The `PropertySourcesPlaceholderConfigurer` checks for placeholders in most properties and
attributes of a bean definition. Furthermore, you can customize the placeholder prefix, suffix,
default value separator, and escape character.
the same applies for other placeholder values that match keys in the properties file. The
`PropertySourcesPlaceholderConfigurer` checks for placeholders in most properties and
attributes of a bean definition. Furthermore, you can customize the placeholder prefix,
suffix, default value separator, and escape character. In addition, the default escape
character can be changed or disabled globally by setting the
`spring.placeholder.escapeCharacter.default` property via a JVM system property (or via
the xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism).
With the `context` namespace, you can configure property placeholders
with a dedicated configuration element. You can provide one or more locations as a

11
framework-docs/modules/ROOT/pages/languages/kotlin/spring-projects-in.adoc

@ -190,7 +190,7 @@ NOTE: If you use Spring Boot, you should probably use @@ -190,7 +190,7 @@ NOTE: If you use Spring Boot, you should probably use
instead of `@Value` annotations.
As an alternative, you can customize the property placeholder prefix by declaring the
following configuration bean:
following `PropertySourcesPlaceholderConfigurer` bean:
[source,kotlin,indent=0]
----
@ -200,8 +200,10 @@ following configuration bean: @@ -200,8 +200,10 @@ following configuration bean:
}
----
You can customize existing code (such as Spring Boot actuators or `@LocalServerPort`)
that uses the `${...}` syntax, with configuration beans, as the following example shows:
You can support components (such as Spring Boot actuators or `@LocalServerPort`) that use
the standard `${...}` syntax alongside components that use the custom `%{...}` syntax by
declaring multiple `PropertySourcesPlaceholderConfigurer` beans, as the following example
shows:
[source,kotlin,indent=0]
----
@ -215,6 +217,9 @@ that uses the `${...}` syntax, with configuration beans, as the following exampl @@ -215,6 +217,9 @@ that uses the `${...}` syntax, with configuration beans, as the following exampl
fun defaultPropertyConfigurer() = PropertySourcesPlaceholderConfigurer()
----
In addition, the default escape character can be changed or disabled globally by setting
the `spring.placeholder.escapeCharacter.default` property via a JVM system property (or
via the xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism).
[[checked-exceptions]]

15
spring-beans/src/main/java/org/springframework/beans/factory/config/PlaceholderConfigurerSupport.java

@ -22,6 +22,7 @@ import org.springframework.beans.factory.BeanDefinitionStoreException; @@ -22,6 +22,7 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.core.env.AbstractPropertyResolver;
import org.springframework.util.StringValueResolver;
import org.springframework.util.SystemPropertyUtils;
@ -86,6 +87,7 @@ import org.springframework.util.SystemPropertyUtils; @@ -86,6 +87,7 @@ import org.springframework.util.SystemPropertyUtils;
*
* @author Chris Beams
* @author Juergen Hoeller
* @author Sam Brannen
* @since 3.1
* @see PropertyPlaceholderConfigurer
* @see org.springframework.context.support.PropertySourcesPlaceholderConfigurer
@ -102,7 +104,11 @@ public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfi @@ -102,7 +104,11 @@ public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfi
/** Default value separator: {@value}. */
public static final String DEFAULT_VALUE_SEPARATOR = SystemPropertyUtils.VALUE_SEPARATOR;
/** Default escape character: {@code '\'}. */
/**
* Default escape character: {@code '\'}.
* @since 6.2
* @see AbstractPropertyResolver#getDefaultEscapeCharacter()
*/
public static final Character DEFAULT_ESCAPE_CHARACTER = SystemPropertyUtils.ESCAPE_CHARACTER;
@ -115,8 +121,10 @@ public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfi @@ -115,8 +121,10 @@ public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfi
/** Defaults to {@value #DEFAULT_VALUE_SEPARATOR}. */
protected @Nullable String valueSeparator = DEFAULT_VALUE_SEPARATOR;
/** Defaults to {@link #DEFAULT_ESCAPE_CHARACTER}. */
protected @Nullable Character escapeCharacter = DEFAULT_ESCAPE_CHARACTER;
/**
* The default is determined by {@link AbstractPropertyResolver#getDefaultEscapeCharacter()}.
*/
protected @Nullable Character escapeCharacter = AbstractPropertyResolver.getDefaultEscapeCharacter();
protected boolean trimValues = false;
@ -160,6 +168,7 @@ public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfi @@ -160,6 +168,7 @@ public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfi
* {@linkplain #setPlaceholderPrefix(String) placeholder prefix} and the
* {@linkplain #setValueSeparator(String) value separator}, or {@code null}
* if no escaping should take place.
* <p>The default is determined by {@link AbstractPropertyResolver#getDefaultEscapeCharacter()}.
* @since 6.2
*/
public void setEscapeCharacter(@Nullable Character escapeCharacter) {

110
spring-context/src/test/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurerTests.java

@ -16,12 +16,15 @@ @@ -16,12 +16,15 @@
package org.springframework.context.support;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
@ -37,7 +40,9 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext @@ -37,7 +40,9 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.SpringProperties;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.env.AbstractPropertyResolver;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
@ -47,12 +52,15 @@ import org.springframework.core.io.Resource; @@ -47,12 +52,15 @@ import org.springframework.core.io.Resource;
import org.springframework.core.testfixture.env.MockPropertySource;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.util.PlaceholderResolutionException;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
import static org.springframework.core.env.AbstractPropertyResolver.DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME;
/**
* Tests for {@link PropertySourcesPlaceholderConfigurer}.
@ -667,6 +675,108 @@ class PropertySourcesPlaceholderConfigurerTests { @@ -667,6 +675,108 @@ class PropertySourcesPlaceholderConfigurerTests {
}
/**
* Tests that globally set the default escape character (or disable it) and
* rely on nested placeholder resolution.
*/
@Nested
class GlobalDefaultEscapeCharacterTests {
private static final Field defaultEscapeCharacterField =
ReflectionUtils.findField(AbstractPropertyResolver.class, "defaultEscapeCharacter");
static {
ReflectionUtils.makeAccessible(defaultEscapeCharacterField);
}
@BeforeEach
void resetStateBeforeEachTest() {
resetState();
}
@AfterAll
static void resetState() {
ReflectionUtils.setField(defaultEscapeCharacterField, null, Character.MIN_VALUE);
setSpringProperty(null);
}
@Test // gh-34865
void defaultEscapeCharacterSetToXyz() {
setSpringProperty("XYZ");
assertThatIllegalArgumentException()
.isThrownBy(PropertySourcesPlaceholderConfigurer::new)
.withMessage("Value [XYZ] for property [%s] must be a single character or an empty string",
DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME);
}
@Test // gh-34865
void defaultEscapeCharacterDisabled() {
setSpringProperty("");
MockEnvironment env = new MockEnvironment()
.withProperty("user.home", "admin")
.withProperty("my.property", "\\DOMAIN\\${user.home}");
DefaultListableBeanFactory bf = createBeanFactory();
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
ppc.setEnvironment(env);
ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName()).isEqualTo("\\DOMAIN\\admin");
}
@Test // gh-34865
void defaultEscapeCharacterSetToBackslash() {
setSpringProperty("\\");
MockEnvironment env = new MockEnvironment()
.withProperty("user.home", "admin")
.withProperty("my.property", "\\DOMAIN\\${user.home}");
DefaultListableBeanFactory bf = createBeanFactory();
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
ppc.setEnvironment(env);
ppc.postProcessBeanFactory(bf);
// \DOMAIN\${user.home} resolves to \DOMAIN${user.home} instead of \DOMAIN\admin
assertThat(bf.getBean(TestBean.class).getName()).isEqualTo("\\DOMAIN${user.home}");
}
@Test // gh-34865
void defaultEscapeCharacterSetToTilde() {
setSpringProperty("~");
MockEnvironment env = new MockEnvironment()
.withProperty("user.home", "admin\\~${nested}")
.withProperty("my.property", "DOMAIN\\${user.home}\\~${enigma}");
DefaultListableBeanFactory bf = createBeanFactory();
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
ppc.setEnvironment(env);
ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName()).isEqualTo("DOMAIN\\admin\\${nested}\\${enigma}");
}
private static void setSpringProperty(String value) {
SpringProperties.setProperty(DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME, value);
}
private static DefaultListableBeanFactory createBeanFactory() {
BeanDefinition beanDefinition = genericBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.property}")
.getBeanDefinition();
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean",beanDefinition);
return bf;
}
}
private static class OptionalTestBean {
private Optional<String> name;

102
spring-core/src/main/java/org/springframework/core/env/AbstractPropertyResolver.java vendored

@ -24,6 +24,7 @@ import org.apache.commons.logging.Log; @@ -24,6 +24,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.SpringProperties;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
@ -37,10 +38,51 @@ import org.springframework.util.SystemPropertyUtils; @@ -37,10 +38,51 @@ import org.springframework.util.SystemPropertyUtils;
*
* @author Chris Beams
* @author Juergen Hoeller
* @author Sam Brannen
* @since 3.1
*/
public abstract class AbstractPropertyResolver implements ConfigurablePropertyResolver {
/**
* JVM system property used to change the <em>default</em> escape character
* for property placeholder support: {@value}.
* <p>To configure a custom escape character, supply a string containing a
* single character (other than {@link Character#MIN_VALUE}). For example,
* supplying the following JVM system property via the command line sets the
* default escape character to {@code '@'}.
* <pre style="code">-Dspring.placeholder.escapeCharacter.default=@</pre>
* <p>To disable escape character support, set the value to an empty string
* &mdash; for example, by supplying the following JVM system property via
* the command line.
* <pre style="code">-Dspring.placeholder.escapeCharacter.default=</pre>
* <p>If the property is not set, {@code '\'} will be used as the default
* escape character.
* <p>May alternatively be configured via a
* {@link org.springframework.core.SpringProperties spring.properties} file
* in the root of the classpath.
* @since 6.2.7
* @see #getDefaultEscapeCharacter()
*/
public static final String DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME =
"spring.placeholder.escapeCharacter.default";
/**
* Since {@code null} is a valid value for {@link #defaultEscapeCharacter},
* this constant provides a way to represent an undefined (or not yet set)
* value. Consequently, {@link #getDefaultEscapeCharacter()} prevents the use
* of {@link Character#MIN_VALUE} as the actual escape character.
* @since 6.2.7
*/
static final Character UNDEFINED_ESCAPE_CHARACTER = Character.MIN_VALUE;
/**
* Cached value for the default escape character.
* @since 6.2.7
*/
static volatile @Nullable Character defaultEscapeCharacter = UNDEFINED_ESCAPE_CHARACTER;
protected final Log logger = LogFactory.getLog(getClass());
private volatile @Nullable ConfigurableConversionService conversionService;
@ -57,7 +99,7 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe @@ -57,7 +99,7 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
private @Nullable String valueSeparator = SystemPropertyUtils.VALUE_SEPARATOR;
private @Nullable Character escapeCharacter = SystemPropertyUtils.ESCAPE_CHARACTER;
private @Nullable Character escapeCharacter = getDefaultEscapeCharacter();
private final Set<String> requiredProperties = new LinkedHashSet<>();
@ -119,9 +161,8 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe @@ -119,9 +161,8 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
/**
* {@inheritDoc}
* <p>The default is {@code '\'}.
* <p>The default is determined by {@link #getDefaultEscapeCharacter()}.
* @since 6.2
* @see SystemPropertyUtils#ESCAPE_CHARACTER
*/
@Override
public void setEscapeCharacter(@Nullable Character escapeCharacter) {
@ -279,4 +320,59 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe @@ -279,4 +320,59 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
*/
protected abstract @Nullable String getPropertyAsRawString(String key);
/**
* Get the default {@linkplain #setEscapeCharacter(Character) escape character}
* to use when parsing strings for property placeholder resolution.
* <p>This method attempts to retrieve the default escape character configured
* via the {@value #DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME} JVM system
* property or Spring property.
* <p>Falls back to {@code '\'} if the property has not been set.
* @return the configured default escape character, {@code null} if escape character
* support has been disabled, or {@code '\'} if the property has not been set
* @throws IllegalArgumentException if the property is configured with an
* invalid value, such as {@link Character#MIN_VALUE} or a string containing
* more than one character
* @since 6.2.7
* @see #DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME
* @see SystemPropertyUtils#ESCAPE_CHARACTER
* @see SpringProperties
*/
public static @Nullable Character getDefaultEscapeCharacter() throws IllegalArgumentException {
Character escapeCharacter = defaultEscapeCharacter;
if (UNDEFINED_ESCAPE_CHARACTER.equals(escapeCharacter)) {
String value = SpringProperties.getProperty(DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME);
if (value != null) {
if (value.isEmpty()) {
// Disable escape character support by default.
escapeCharacter = null;
}
else if (value.length() == 1) {
try {
// Use custom default escape character.
escapeCharacter = value.charAt(0);
}
catch (Exception ex) {
throw new IllegalArgumentException("Failed to process value [%s] for property [%s]: %s"
.formatted(value, DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME, ex.getMessage()), ex);
}
Assert.isTrue(!escapeCharacter.equals(Character.MIN_VALUE),
() -> "Value for property [%s] must not be Character.MIN_VALUE"
.formatted(DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME));
}
else {
throw new IllegalArgumentException(
"Value [%s] for property [%s] must be a single character or an empty string"
.formatted(value, DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME));
}
}
else {
// Use standard default value for the escape character.
escapeCharacter = SystemPropertyUtils.ESCAPE_CHARACTER;
}
defaultEscapeCharacter = escapeCharacter;
}
return escapeCharacter;
}
}

120
spring-core/src/test/java/org/springframework/core/env/AbstractPropertyResolverTests.java vendored

@ -0,0 +1,120 @@ @@ -0,0 +1,120 @@
/*
* 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.env;
import java.util.stream.IntStream;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.core.SpringProperties;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.springframework.core.env.AbstractPropertyResolver.DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME;
import static org.springframework.core.env.AbstractPropertyResolver.UNDEFINED_ESCAPE_CHARACTER;
/**
* Unit tests for {@link AbstractPropertyResolver}.
*
* @author Sam Brannen
* @since 6.2.7
*/
class AbstractPropertyResolverTests {
@BeforeEach
void resetStateBeforeEachTest() {
resetState();
}
@AfterAll
static void resetState() {
AbstractPropertyResolver.defaultEscapeCharacter = UNDEFINED_ESCAPE_CHARACTER;
setSpringProperty(null);
}
@Test
void getDefaultEscapeCharacterWithSpringPropertySetToCharacterMinValue() {
setSpringProperty("" + Character.MIN_VALUE);
assertThatIllegalArgumentException()
.isThrownBy(AbstractPropertyResolver::getDefaultEscapeCharacter)
.withMessage("Value for property [%s] must not be Character.MIN_VALUE",
DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME);
assertThat(AbstractPropertyResolver.defaultEscapeCharacter).isEqualTo(UNDEFINED_ESCAPE_CHARACTER);
}
@Test
void getDefaultEscapeCharacterWithSpringPropertySetToXyz() {
setSpringProperty("XYZ");
assertThatIllegalArgumentException()
.isThrownBy(AbstractPropertyResolver::getDefaultEscapeCharacter)
.withMessage("Value [XYZ] for property [%s] must be a single character or an empty string",
DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME);
assertThat(AbstractPropertyResolver.defaultEscapeCharacter).isEqualTo(UNDEFINED_ESCAPE_CHARACTER);
}
@Test
void getDefaultEscapeCharacterWithSpringPropertySetToEmptyString() {
setSpringProperty("");
assertEscapeCharacter(null);
}
@Test
void getDefaultEscapeCharacterWithoutSpringPropertySet() {
assertEscapeCharacter('\\');
}
@Test
void getDefaultEscapeCharacterWithSpringPropertySetToBackslash() {
setSpringProperty("\\");
assertEscapeCharacter('\\');
}
@Test
void getDefaultEscapeCharacterWithSpringPropertySetToTilde() {
setSpringProperty("~");
assertEscapeCharacter('~');
}
@Test
void getDefaultEscapeCharacterFromMultipleThreads() {
setSpringProperty("~");
IntStream.range(1, 32).parallel().forEach(__ ->
assertThat(AbstractPropertyResolver.getDefaultEscapeCharacter()).isEqualTo('~'));
assertThat(AbstractPropertyResolver.defaultEscapeCharacter).isEqualTo('~');
}
private static void setSpringProperty(String value) {
SpringProperties.setProperty(DEFAULT_PLACEHOLDER_ESCAPE_CHARACTER_PROPERTY_NAME, value);
}
private static void assertEscapeCharacter(@Nullable Character expected) {
assertThat(AbstractPropertyResolver.getDefaultEscapeCharacter()).isEqualTo(expected);
assertThat(AbstractPropertyResolver.defaultEscapeCharacter).isEqualTo(expected);
}
}
Loading…
Cancel
Save