-
Notifications
You must be signed in to change notification settings - Fork 117
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
#Fixed 198 - Add interceptor to expand expressions in Config Values.
- Loading branch information
Showing
5 changed files
with
190 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
implementation/src/main/java/io/smallrye/config/ExpressionConfigSourceInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package io.smallrye.config; | ||
|
||
import static io.smallrye.common.expression.Expression.Flag.LENIENT_SYNTAX; | ||
import static io.smallrye.common.expression.Expression.Flag.NO_TRIM; | ||
|
||
import java.util.NoSuchElementException; | ||
|
||
import javax.annotation.Priority; | ||
|
||
import io.smallrye.common.expression.Expression; | ||
|
||
@Priority(500) | ||
public class ExpressionConfigSourceInterceptor implements ConfigSourceInterceptor { | ||
private static final ThreadLocal<Boolean> ENABLE = ThreadLocal.withInitial(() -> Boolean.TRUE); | ||
|
||
@Override | ||
public ConfigValue getValue(final ConfigSourceInterceptorContext context, final String name) { | ||
final ConfigValue configValue = context.proceed(name); | ||
|
||
if (!ENABLE.get()) { | ||
return configValue; | ||
} | ||
|
||
if (configValue == null) { | ||
return null; | ||
} | ||
|
||
final Expression expression = Expression.compile(configValue.getValue(), LENIENT_SYNTAX, NO_TRIM); | ||
final String expanded = expression.evaluate((resolveContext, stringBuilder) -> { | ||
final ConfigValue resolve = context.proceed(resolveContext.getKey()); | ||
if (resolve != null) { | ||
stringBuilder.append(resolve.getValue()); | ||
} else if (resolveContext.hasDefault()) { | ||
resolveContext.expandDefault(); | ||
} else { | ||
throw new NoSuchElementException( | ||
"Could not expand value " + resolveContext.getKey() + " in property " + configValue.getName()); | ||
} | ||
}); | ||
|
||
return configValue.withValue(expanded); | ||
} | ||
|
||
static boolean enable() { | ||
try { | ||
return ENABLE.get() == Boolean.FALSE; | ||
} finally { | ||
ENABLE.set(Boolean.TRUE); | ||
} | ||
} | ||
|
||
static boolean disable() { | ||
try { | ||
return ENABLE.get() == Boolean.TRUE; | ||
} finally { | ||
ENABLE.set(Boolean.FALSE); | ||
} | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
implementation/src/main/java/io/smallrye/config/Expressions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package io.smallrye.config; | ||
|
||
import static io.smallrye.config.ExpressionConfigSourceInterceptor.disable; | ||
import static io.smallrye.config.ExpressionConfigSourceInterceptor.enable; | ||
|
||
public class Expressions { | ||
public static void withoutExpansion(final Runnable action) { | ||
if (disable()) { | ||
try { | ||
action.run(); | ||
} finally { | ||
enable(); | ||
} | ||
} else { | ||
action.run(); | ||
} | ||
} | ||
} |
100 changes: 100 additions & 0 deletions
100
implementation/src/test/java/io/smallrye/config/ExpressionConfigSourceInterceptorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package io.smallrye.config; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertThrows; | ||
|
||
import java.util.NoSuchElementException; | ||
|
||
import org.eclipse.microprofile.config.Config; | ||
import org.junit.Test; | ||
|
||
public class ExpressionConfigSourceInterceptorTest { | ||
@Test | ||
public void simpleExpression() { | ||
SmallRyeConfig config = (SmallRyeConfig) buildConfig("my.prop", "1234", "expression", "${my.prop}"); | ||
|
||
assertEquals("1234", config.getValue("expression", String.class)); | ||
} | ||
|
||
@Test | ||
public void multipleExpressions() { | ||
SmallRyeConfig config = (SmallRyeConfig) buildConfig("my.prop", "1234", "expression", "${my.prop}${my.prop}"); | ||
|
||
assertEquals("12341234", config.getValue("expression", String.class)); | ||
} | ||
|
||
@Test | ||
public void composedExpressions() { | ||
SmallRyeConfig config = (SmallRyeConfig) buildConfig("my.prop", "1234", "expression", "${${compose}}", "compose", | ||
"my.prop"); | ||
|
||
assertEquals("1234", config.getValue("expression", String.class)); | ||
} | ||
|
||
@Test | ||
public void defaultExpression() { | ||
SmallRyeConfig config = (SmallRyeConfig) buildConfig("expression", "${my.prop:1234}"); | ||
|
||
assertEquals("1234", config.getValue("expression", String.class)); | ||
} | ||
|
||
@Test | ||
public void defaultExpressionEmpty() { | ||
SmallRyeConfig config = (SmallRyeConfig) buildConfig("expression", "12${my.prop:}34"); | ||
|
||
assertEquals("1234", config.getValue("expression", String.class)); | ||
} | ||
|
||
@Test | ||
public void defaultExpressionComposed() { | ||
SmallRyeConfig config = (SmallRyeConfig) buildConfig("expression", "${my.prop:${compose}}", "compose", "1234"); | ||
|
||
assertEquals("1234", config.getValue("expression", String.class)); | ||
} | ||
|
||
@Test | ||
public void defaultExpressionComposedEmpty() { | ||
SmallRyeConfig config = (SmallRyeConfig) buildConfig("expression", "${my.prop:${compose:}}", "my.prop", "1234"); | ||
|
||
assertEquals("1234", config.getValue("expression", String.class)); | ||
} | ||
|
||
@Test | ||
public void noExpression() { | ||
SmallRyeConfig config = (SmallRyeConfig) buildConfig("expression", "${my.prop}"); | ||
|
||
final NoSuchElementException exception = assertThrows(NoSuchElementException.class, | ||
() -> config.getValue("expression", String.class)); | ||
assertEquals("Could not expand value my.prop in property expression", exception.getMessage()); | ||
} | ||
|
||
@Test | ||
public void noExpressionComposed() { | ||
SmallRyeConfig config = (SmallRyeConfig) buildConfig("expression", "${my.prop${compose}}"); | ||
|
||
final NoSuchElementException exception = assertThrows(NoSuchElementException.class, | ||
() -> config.getValue("expression", String.class)); | ||
assertEquals("Could not expand value compose in property expression", exception.getMessage()); | ||
} | ||
|
||
@Test | ||
public void withoutExpansion() { | ||
SmallRyeConfig config = (SmallRyeConfig) buildConfig("my.prop", "1234", "expression", "${my.prop}"); | ||
|
||
assertEquals("1234", config.getValue("expression", String.class)); | ||
|
||
Expressions.withoutExpansion(() -> assertEquals("${my.prop}", config.getValue("expression", String.class))); | ||
Expressions.withoutExpansion(() -> assertEquals("${my.prop}", config.getValue("expression", String.class))); | ||
Expressions.withoutExpansion(() -> assertEquals("${my.prop}", config.getValue("expression", String.class))); | ||
|
||
assertEquals("1234", config.getValue("expression", String.class)); | ||
} | ||
|
||
private static Config buildConfig(String... keyValues) { | ||
return new SmallRyeConfigBuilder() | ||
.addDefaultSources() | ||
.withSources(KeyValuesConfigSource.config(keyValues)) | ||
.withInterceptors(new ExpressionConfigSourceInterceptor()) | ||
.build(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters