Skip to content

Commit

Permalink
Merge pull request #266 from radcortez/#198
Browse files Browse the repository at this point in the history
#Fixed 198 - Add interceptor to expand expressions in Config Values.
  • Loading branch information
radcortez authored Mar 20, 2020
2 parents c99dab1 + 7821aee commit 56a511c
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 0 deletions.
5 changes: 5 additions & 0 deletions implementation/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@
<groupId>io.smallrye.config</groupId>
<artifactId>smallrye-config-common</artifactId>
</dependency>
<dependency>
<groupId>io.smallrye.common</groupId>
<artifactId>smallrye-common-expression</artifactId>
</dependency>

<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
Expand Down
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 implementation/src/main/java/io/smallrye/config/Expressions.java
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();
}
}
}
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();
}
}
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

<properties>
<version.eclipse.microprofile.config>1.4</version.eclipse.microprofile.config>
<version.smallrye.common>1.0.0</version.smallrye.common>

<!-- Sonar settings -->
<sonar.projectName>SmallRye Config</sonar.projectName>
Expand Down Expand Up @@ -106,6 +107,13 @@
</exclusions>
</dependency>

<!-- External SmallRye Dependencies -->
<dependency>
<groupId>io.smallrye.common</groupId>
<artifactId>smallrye-common-expression</artifactId>
<version>${version.smallrye.common}</version>
</dependency>

<!-- Dependencies provided by the project -->
<dependency>
<groupId>io.smallrye.config</groupId>
Expand Down

0 comments on commit 56a511c

Please sign in to comment.