Merge branch '6.2.x'
This commit is contained in:
commit
eda7af764b
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -173,9 +173,8 @@ final class PlaceholderParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private SimplePlaceholderPart createSimplePlaceholderPart(String text) {
|
private SimplePlaceholderPart createSimplePlaceholderPart(String text) {
|
||||||
String[] keyAndDefault = splitKeyAndDefault(text);
|
ParsedSection section = parseSection(text);
|
||||||
return ((keyAndDefault != null) ? new SimplePlaceholderPart(text, keyAndDefault[0], keyAndDefault[1]) :
|
return new SimplePlaceholderPart(text, section.key(), section.fallback());
|
||||||
new SimplePlaceholderPart(text, text, null));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private NestedPlaceholderPart createNestedPlaceholderPart(String text, List<Part> parts) {
|
private NestedPlaceholderPart createNestedPlaceholderPart(String text, List<Part> parts) {
|
||||||
|
@ -191,27 +190,32 @@ final class PlaceholderParser {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
String candidate = part.text();
|
String candidate = part.text();
|
||||||
String[] keyAndDefault = splitKeyAndDefault(candidate);
|
ParsedSection section = parseSection(candidate);
|
||||||
if (keyAndDefault != null) {
|
keyParts.add(new TextPart(section.key()));
|
||||||
keyParts.add(new TextPart(keyAndDefault[0]));
|
if (section.fallback() != null) {
|
||||||
if (keyAndDefault[1] != null) {
|
defaultParts.add(new TextPart(section.fallback()));
|
||||||
defaultParts.add(new TextPart(keyAndDefault[1]));
|
|
||||||
}
|
|
||||||
defaultParts.addAll(parts.subList(i + 1, parts.size()));
|
defaultParts.addAll(parts.subList(i + 1, parts.size()));
|
||||||
return new NestedPlaceholderPart(text, keyParts, defaultParts);
|
return new NestedPlaceholderPart(text, keyParts, defaultParts);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
keyParts.add(part);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return new NestedPlaceholderPart(text, keyParts, null);
|
||||||
// No separator found
|
|
||||||
return new NestedPlaceholderPart(text, parts, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String @Nullable [] splitKeyAndDefault(String value) {
|
/**
|
||||||
|
* Parse an input value that may contain a separator character and return a
|
||||||
|
* {@link ParsedValue}. If a valid separator character has been identified, the
|
||||||
|
* given {@code value} is split between a {@code key} and a {@code fallback}. If not,
|
||||||
|
* only the {@code key} is set.
|
||||||
|
* <p>
|
||||||
|
* The returned key may be different from the original value as escaped
|
||||||
|
* separators, if any, are resolved.
|
||||||
|
* @param value the value to parse
|
||||||
|
* @return the parsed section
|
||||||
|
*/
|
||||||
|
private ParsedSection parseSection(String value) {
|
||||||
if (this.separator == null || !value.contains(this.separator)) {
|
if (this.separator == null || !value.contains(this.separator)) {
|
||||||
return null;
|
return new ParsedSection(value, null);
|
||||||
}
|
}
|
||||||
int position = 0;
|
int position = 0;
|
||||||
int index = value.indexOf(this.separator, position);
|
int index = value.indexOf(this.separator, position);
|
||||||
|
@ -228,11 +232,11 @@ final class PlaceholderParser {
|
||||||
buffer.append(value, position, index);
|
buffer.append(value, position, index);
|
||||||
String key = buffer.toString();
|
String key = buffer.toString();
|
||||||
String fallback = value.substring(index + this.separator.length());
|
String fallback = value.substring(index + this.separator.length());
|
||||||
return new String[] { key, fallback };
|
return new ParsedSection(key, fallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer.append(value, position, value.length());
|
buffer.append(value, position, value.length());
|
||||||
return new String[] { buffer.toString(), null };
|
return new ParsedSection(buffer.toString(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addText(String value, int start, int end, LinkedList<Part> parts) {
|
private static void addText(String value, int start, int end, LinkedList<Part> parts) {
|
||||||
|
@ -290,6 +294,10 @@ final class PlaceholderParser {
|
||||||
return (this.escape != null && index > 0 && value.charAt(index - 1) == this.escape);
|
return (this.escape != null && index > 0 && value.charAt(index - 1) == this.escape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
record ParsedSection(String key, @Nullable String fallback) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide the necessary context to handle and resolve underlying placeholders.
|
* Provide the necessary context to handle and resolve underlying placeholders.
|
||||||
|
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -278,6 +278,26 @@ class PlaceholderParserTests {
|
||||||
|
|
||||||
private final PlaceholderParser parser = new PlaceholderParser("${", "}", ":", '\\', true);
|
private final PlaceholderParser parser = new PlaceholderParser("${", "}", ":", '\\', true);
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "{0} -> {1}")
|
||||||
|
@MethodSource("escapedInNestedPlaceholders")
|
||||||
|
void escapedSeparatorInNestedPlaceholder(String text, String expected) {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.setProperty("app.environment", "qa");
|
||||||
|
properties.setProperty("app.service", "protocol");
|
||||||
|
properties.setProperty("protocol://host/qa/name", "protocol://example.com/qa/name");
|
||||||
|
properties.setProperty("service/host/qa/name", "https://example.com/qa/name");
|
||||||
|
properties.setProperty("service/host/qa/name:value", "https://example.com/qa/name-value");
|
||||||
|
assertThat(this.parser.replacePlaceholders(text, properties::getProperty)).isEqualTo(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Stream<Arguments> escapedInNestedPlaceholders() {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of("${protocol\\://host/${app.environment}/name}", "protocol://example.com/qa/name"),
|
||||||
|
Arguments.of("${${app.service}\\://host/${app.environment}/name}", "protocol://example.com/qa/name"),
|
||||||
|
Arguments.of("${service/host/${app.environment}/name:\\value}", "https://example.com/qa/name"),
|
||||||
|
Arguments.of("${service/host/${name\\:value}/}", "${service/host/${name:value}/}"));
|
||||||
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "{0} -> {1}")
|
@ParameterizedTest(name = "{0} -> {1}")
|
||||||
@MethodSource("escapedPlaceholders")
|
@MethodSource("escapedPlaceholders")
|
||||||
void escapedPlaceholderIsNotReplaced(String text, String expected) {
|
void escapedPlaceholderIsNotReplaced(String text, String expected) {
|
||||||
|
|
Loading…
Reference in New Issue