Skip to content

Commit

Permalink
Move env mangling to ConfigImplUtil
Browse files Browse the repository at this point in the history
  • Loading branch information
andreaTP committed Mar 21, 2019
1 parent 90e2465 commit 4937ee4
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 32 deletions.
36 changes: 4 additions & 32 deletions config/src/main/java/com/typesafe/config/impl/ConfigImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -361,43 +361,15 @@ public static void reloadEnvVariablesConfig() {
EnvVariablesHolder.envVariables = loadEnvVariables();
}



private static AbstractConfigObject loadEnvVariablesOverrides() {
Map<String, String> env = new HashMap(System.getenv());
Map<String, String> result = new HashMap(System.getenv());
// Rationale on name mangling:
//
// Most shells (e.g. bash, sh, etc.) doesn't support any character other
// than alphanumeric and `_` in environment variables names.
// In HOCON the default separator is `.` so it is directly translated to a
// single `_` for convenience; `-` and `_` are less often present in config
// keys but they have to be representable and the only possible mapping is
// `_` repeated.

for (String key : env.keySet()) {
if (key.startsWith(ENV_VAR_OVERRIDE_PREFIX)) {
StringBuilder builder = new StringBuilder();

String strippedPrefix = key.substring(ENV_VAR_OVERRIDE_PREFIX.length(), key.length());

int underscores = 0;
for (char c : strippedPrefix.toCharArray()) {
if (c == '_') {
underscores++;
} else {
switch (underscores) {
case 1: builder.append('.');
break;
case 2: builder.append('-');
break;
case 3: builder.append('_');
break;
}
underscores = 0;
builder.append(c);
}
}

String propertyKey = builder.toString();
result.put(propertyKey, env.get(key));
result.put(ConfigImplUtil.envVariableAsProperty(key, ENV_VAR_OVERRIDE_PREFIX), env.get(key));
}
}

Expand Down
46 changes: 46 additions & 0 deletions config/src/main/java/com/typesafe/config/impl/ConfigImplUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,52 @@ static String toCamelCase(String originalName) {
return nameBuilder.toString();
}

private static char underscoreMappings(int num) {
// Rationale on name mangling:
//
// Most shells (e.g. bash, sh, etc.) doesn't support any character other
// than alphanumeric and `_` in environment variables names.
// In HOCON the default separator is `.` so it is directly translated to a
// single `_` for convenience; `-` and `_` are less often present in config
// keys but they have to be representable and the only possible mapping is
// `_` repeated.
switch (num) {
case 1: return '.';
case 2: return '-';
case 3: return '_';
default: return 0;
}
}

static String envVariableAsProperty(String variable, String prefix) throws ConfigException {
StringBuilder builder = new StringBuilder();

String strippedPrefix = variable.substring(prefix.length(), variable.length());

int underscores = 0;
for (char c : strippedPrefix.toCharArray()) {
if (c == '_') {
underscores++;
} else {
if (underscores > 0 && underscores < 4) {
builder.append(underscoreMappings(underscores));
} else if (underscores > 3) {
throw new ConfigException.BadPath(variable, "Environment variable contains an un-mapped number of underscores.");
}
underscores = 0;
builder.append(c);
}
}

if (underscores > 0 && underscores < 4) {
builder.append(underscoreMappings(underscores));
} else if (underscores > 3) {
throw new ConfigException.BadPath(variable, "Environment variable contains an un-mapped number of underscores.");
}

return builder.toString();
}

/**
* Guess configuration syntax from given filename.
*
Expand Down
16 changes: 16 additions & 0 deletions config/src/test/scala/com/typesafe/config/impl/ConfigTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,22 @@ class ConfigTest extends TestUtils {
assertEquals(10, resolved.getInt("bar.nested.a.q"))
}

@Test
def testEnvVariablesNameMangling() {
assertEquals("a", ConfigImplUtil.envVariableAsProperty("prefix_a", "prefix_"))
assertEquals("a.b", ConfigImplUtil.envVariableAsProperty("prefix_a_b", "prefix_"))
assertEquals("a.b.c", ConfigImplUtil.envVariableAsProperty("prefix_a_b_c", "prefix_"))
assertEquals("a.b-c-d", ConfigImplUtil.envVariableAsProperty("prefix_a_b__c__d", "prefix_"))
assertEquals("a.b_c_d", ConfigImplUtil.envVariableAsProperty("prefix_a_b___c___d", "prefix_"))

intercept[ConfigException.BadPath] {
ConfigImplUtil.envVariableAsProperty("prefix_____", "prefix_")
}
intercept[ConfigException.BadPath] {
ConfigImplUtil.envVariableAsProperty("prefix_a_b___c____d", "prefix_")
}
}

@Test
def testLoadWithEnvSubstitutions() {
System.setProperty("config.override_with_env_vars", "true")
Expand Down

0 comments on commit 4937ee4

Please sign in to comment.