diff --git a/inject/src/main/java/io/micronaut/context/env/EnvironmentPropertySource.java b/inject/src/main/java/io/micronaut/context/env/EnvironmentPropertySource.java index 6f5464a4eea..8c7220ccceb 100644 --- a/inject/src/main/java/io/micronaut/context/env/EnvironmentPropertySource.java +++ b/inject/src/main/java/io/micronaut/context/env/EnvironmentPropertySource.java @@ -17,9 +17,10 @@ import io.micronaut.core.annotation.Nullable; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; /** * Loads properties from environment variables via {@link System#getenv()}. @@ -28,6 +29,10 @@ * @since 1.0 */ public class EnvironmentPropertySource extends MapPropertySource { + /** + * Converts list elements defined as _0 or _0_ into names that the resolver can understand; i.e., [0]. + */ + private static final Pattern LIST_CONVERTER_REGEX = Pattern.compile("_([0-9]{1,2})(?:_|$)"); /** * The position of the loader. @@ -77,20 +82,21 @@ static Map getEnv(@Nullable List includes, @Nullable List exclud } static Map getEnv(Map env, @Nullable List includes, @Nullable List excludes) { - if (includes != null || excludes != null) { - Map result = new HashMap<>(); - for (Map.Entry entry : env.entrySet()) { - String envVar = entry.getKey(); - if (excludes != null && excludes.contains(envVar)) { - continue; - } - if (includes != null && !includes.contains(envVar)) { - continue; - } - result.put(envVar, entry.getValue()); + Map result = new LinkedHashMap<>(); + for (Map.Entry entry : env.entrySet()) { + String envVar = entry.getKey(); + if (excludes != null && excludes.contains(envVar)) { + continue; + } + if (includes != null && !includes.contains(envVar)) { + continue; } - return result; + + String convertedEnvVar = LIST_CONVERTER_REGEX.matcher(envVar).replaceAll("[$1]"); + + result.put(convertedEnvVar, entry.getValue()); } - return env; + + return result; } } diff --git a/inject/src/test/groovy/io/micronaut/context/env/EnvironmentPropertySourceSpec.groovy b/inject/src/test/groovy/io/micronaut/context/env/EnvironmentPropertySourceSpec.groovy index 642a2dc5002..b0a29502475 100644 --- a/inject/src/test/groovy/io/micronaut/context/env/EnvironmentPropertySourceSpec.groovy +++ b/inject/src/test/groovy/io/micronaut/context/env/EnvironmentPropertySourceSpec.groovy @@ -88,5 +88,25 @@ class EnvironmentPropertySourceSpec extends Specification { cleanup: context.close() } - + + void "test environment variable list conversion scenarios"() { + def envs = SystemLambda.withEnvironmentVariable("A_0", "valueA") + .and("A_0__B", "nestedValueB") + .and("A_0__C_0", "multipleArraysC") + + ApplicationContext context = envs.execute(() -> ApplicationContext.builder().start()) + + expect: + context.getProperty("a[0]", String).isPresent() + context.getRequiredProperty("a[0]", String) == "valueA" + + context.getProperty("a[0].b", String).isPresent() + context.getRequiredProperty("a[0].b", String) == "nestedValueB" + + context.getProperty("a[0].c[0]", String).isPresent() + context.getRequiredProperty("a[0].c[0]", String) == "multipleArraysC" + + cleanup: + context.close() + } }