mirror of
https://github.com/lightbend/config.git
synced 2025-02-22 09:10:32 +08:00
Add ConfigResolveOptions.allowUnresolved
This allows Config.resolve() to do a partial resolve. Fixes #100
This commit is contained in:
parent
a48edce4b4
commit
8c0afc58d9
@ -9,6 +9,9 @@ package com.typesafe.config;
|
||||
* href="https://github.com/typesafehub/config/blob/master/HOCON.md">HOCON</a>
|
||||
* spec.
|
||||
* <p>
|
||||
* Typically this class would be used with the method
|
||||
* {@link Config#resolve(ConfigResolveOptions)}.
|
||||
* <p>
|
||||
* This object is immutable, so the "setters" return a new object.
|
||||
* <p>
|
||||
* Here is an example of creating a custom {@code ConfigResolveOptions}:
|
||||
@ -25,18 +28,21 @@ package com.typesafe.config;
|
||||
*/
|
||||
public final class ConfigResolveOptions {
|
||||
private final boolean useSystemEnvironment;
|
||||
private final boolean allowUnresolved;
|
||||
|
||||
private ConfigResolveOptions(boolean useSystemEnvironment) {
|
||||
private ConfigResolveOptions(boolean useSystemEnvironment, boolean allowUnresolved) {
|
||||
this.useSystemEnvironment = useSystemEnvironment;
|
||||
this.allowUnresolved = allowUnresolved;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default resolve options.
|
||||
*
|
||||
* Returns the default resolve options. By default the system environment
|
||||
* will be used and unresolved substitutions are not allowed.
|
||||
*
|
||||
* @return the default resolve options
|
||||
*/
|
||||
public static ConfigResolveOptions defaults() {
|
||||
return new ConfigResolveOptions(true);
|
||||
return new ConfigResolveOptions(true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,9 +63,8 @@ public final class ConfigResolveOptions {
|
||||
* variables.
|
||||
* @return options with requested setting for use of environment variables
|
||||
*/
|
||||
@SuppressWarnings("static-method")
|
||||
public ConfigResolveOptions setUseSystemEnvironment(boolean value) {
|
||||
return new ConfigResolveOptions(value);
|
||||
return new ConfigResolveOptions(value, allowUnresolved);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,4 +77,29 @@ public final class ConfigResolveOptions {
|
||||
public boolean getUseSystemEnvironment() {
|
||||
return useSystemEnvironment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns options with "allow unresolved" set to the given value. By
|
||||
* default, unresolved substitutions are an error. If unresolved
|
||||
* substitutions are allowed, then a future attempt to use the unresolved
|
||||
* value may fail, but {@link Config#resolve(ConfigResolveOptions)} itself
|
||||
* will now throw.
|
||||
*
|
||||
* @param value
|
||||
* true to silently ignore unresolved substitutions.
|
||||
* @return options with requested setting for whether to allow substitutions
|
||||
*/
|
||||
public ConfigResolveOptions setAllowUnresolved(boolean value) {
|
||||
return new ConfigResolveOptions(useSystemEnvironment, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the options allow unresolved substitutions. This method
|
||||
* is mostly used by the config lib internally, not by applications.
|
||||
*
|
||||
* @return true if unresolved substitutions are allowed
|
||||
*/
|
||||
public boolean getAllowUnresolved() {
|
||||
return allowUnresolved;
|
||||
}
|
||||
}
|
||||
|
@ -81,9 +81,13 @@ final class ConfigReference extends AbstractConfigValue implements Unmergeable {
|
||||
}
|
||||
|
||||
if (v == null && !expr.optional()) {
|
||||
throw new ConfigException.UnresolvedSubstitution(origin(), expr.toString());
|
||||
if (context.options().getAllowUnresolved())
|
||||
return this;
|
||||
else
|
||||
throw new ConfigException.UnresolvedSubstitution(origin(), expr.toString());
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
return v;
|
||||
} finally {
|
||||
context.source().unreplace(this);
|
||||
}
|
||||
|
@ -121,14 +121,16 @@ final class ResolveContext {
|
||||
memos.put(fullKey, resolved);
|
||||
} else {
|
||||
// if we have an unresolved object then either we did a
|
||||
// partial resolve restricted to a certain child, or it's
|
||||
// a bug.
|
||||
// partial resolve restricted to a certain child, or we are
|
||||
// allowing incomplete resolution, or it's a bug.
|
||||
if (isRestrictedToChild()) {
|
||||
if (restrictedKey == null) {
|
||||
throw new ConfigException.BugOrBroken(
|
||||
"restrictedKey should not be null here");
|
||||
}
|
||||
memos.put(restrictedKey, resolved);
|
||||
} else if (options().getAllowUnresolved()) {
|
||||
memos.put(fullKey, resolved);
|
||||
} else {
|
||||
throw new ConfigException.BugOrBroken(
|
||||
"resolveSubstitutions() did not give us a resolved object");
|
||||
|
@ -1103,4 +1103,30 @@ class ConfigTest extends TestUtils {
|
||||
checkSerializable(resolved)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
def allowUnresolvedDoesAllowUnresolved() {
|
||||
val values = ConfigFactory.parseString("{ foo = 1, bar = 2, m = 3, n = 4}")
|
||||
val unresolved = ConfigFactory.parseString("a = ${foo}, b = ${bar}, c { x = ${m}, y = ${n} }, alwaysResolveable=${alwaysValue}, alwaysValue=42")
|
||||
// resolve() by default throws with unresolveable substs
|
||||
intercept[ConfigException.UnresolvedSubstitution] {
|
||||
unresolved.resolve(ConfigResolveOptions.defaults())
|
||||
}
|
||||
// we shouldn't be able to get a value without resolving it
|
||||
intercept[ConfigException.NotResolved] {
|
||||
unresolved.getInt("alwaysResolveable")
|
||||
}
|
||||
val allowedUnresolved = unresolved.resolve(ConfigResolveOptions.defaults().setAllowUnresolved(true))
|
||||
// when we partially-resolve we should still resolve what we can
|
||||
assertEquals("we resolved the resolveable", 42, allowedUnresolved.getInt("alwaysResolveable"))
|
||||
// but unresolved should still all throw
|
||||
for (k <- Seq("a", "b", "c.x", "c.y")) {
|
||||
intercept[ConfigException.NotResolved] { allowedUnresolved.getInt(k) }
|
||||
}
|
||||
// and given the values for the resolve, we should be able to
|
||||
val resolved = allowedUnresolved.withFallback(values).resolve()
|
||||
for (kv <- Seq("a" -> 1, "b" -> 2, "c.x" -> 3, "c.y" -> 4)) {
|
||||
assertEquals(kv._2, resolved.getInt(kv._1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user