mirror of
https://github.com/lightbend/config.git
synced 2025-02-23 09:41:01 +08:00
Fix code to find includes relative to other includes. Support ParseOptions for load().
This commit is contained in:
parent
d257c3bbd9
commit
6ca952e516
@ -52,6 +52,12 @@ public final class Config {
|
||||
return loadWithoutResolving(rootPath).resolve();
|
||||
}
|
||||
|
||||
public static ConfigRoot load(String rootPath,
|
||||
ConfigParseOptions parseOptions, ConfigResolveOptions resolveOptions) {
|
||||
return loadWithoutResolving(rootPath, parseOptions).resolve(
|
||||
resolveOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like load() but does not resolve the object, so you can go ahead and add
|
||||
* more fallbacks and stuff and have them seen by substitutions when you do
|
||||
@ -61,11 +67,15 @@ public final class Config {
|
||||
* @return
|
||||
*/
|
||||
public static ConfigRoot loadWithoutResolving(String rootPath) {
|
||||
return loadWithoutResolving(rootPath, ConfigParseOptions.defaults());
|
||||
}
|
||||
|
||||
public static ConfigRoot loadWithoutResolving(String rootPath,
|
||||
ConfigParseOptions options) {
|
||||
ConfigRoot system = systemPropertiesRoot(rootPath);
|
||||
|
||||
ConfigValue mainFiles = parse(rootPath, ConfigParseOptions.defaults());
|
||||
ConfigValue referenceFiles = parse(rootPath + ".reference",
|
||||
ConfigParseOptions.defaults());
|
||||
ConfigValue mainFiles = parse(rootPath, options);
|
||||
ConfigValue referenceFiles = parse(rootPath + ".reference", options);
|
||||
|
||||
return system.withFallbacks(mainFiles, referenceFiles);
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ public class ConfigImpl {
|
||||
if (name.endsWith(".conf") || name.endsWith(".json")
|
||||
|| name.endsWith(".properties")) {
|
||||
ConfigParseable p = source.nameToParseable(name);
|
||||
|
||||
if (p != null) {
|
||||
obj = p.parse(p.options().setAllowMissing(
|
||||
options.getAllowMissing()));
|
||||
@ -47,17 +48,30 @@ public class ConfigImpl {
|
||||
"No config files {.conf,.json,.properties} found");
|
||||
}
|
||||
|
||||
ConfigSyntax syntax = options.getSyntax();
|
||||
|
||||
obj = SimpleConfigObject.empty(new SimpleConfigOrigin(name));
|
||||
if (confHandle != null)
|
||||
if (confHandle != null
|
||||
&& (syntax == null || syntax == ConfigSyntax.CONF)) {
|
||||
obj = confHandle.parse(confHandle.options()
|
||||
.setAllowMissing(true).setSyntax(ConfigSyntax.CONF));
|
||||
if (jsonHandle != null)
|
||||
obj = obj.withFallback(jsonHandle.parse(jsonHandle.options()
|
||||
.setAllowMissing(true).setSyntax(ConfigSyntax.JSON)));
|
||||
if (propsHandle != null)
|
||||
obj = obj.withFallback(propsHandle.parse(propsHandle.options()
|
||||
}
|
||||
|
||||
if (jsonHandle != null
|
||||
&& (syntax == null || syntax == ConfigSyntax.JSON)) {
|
||||
ConfigObject parsed = jsonHandle.parse(jsonHandle
|
||||
.options().setAllowMissing(true)
|
||||
.setSyntax(ConfigSyntax.JSON));
|
||||
obj = obj.withFallback(parsed);
|
||||
}
|
||||
|
||||
if (propsHandle != null
|
||||
&& (syntax == null || syntax == ConfigSyntax.PROPERTIES)) {
|
||||
ConfigObject parsed = propsHandle.parse(propsHandle.options()
|
||||
.setAllowMissing(true)
|
||||
.setSyntax(ConfigSyntax.PROPERTIES)));
|
||||
.setSyntax(ConfigSyntax.PROPERTIES));
|
||||
obj = obj.withFallback(parsed);
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
|
@ -200,39 +200,28 @@ public abstract class Parseable implements ConfigParseable {
|
||||
};
|
||||
}
|
||||
|
||||
private static URL urlParent(URL url) {
|
||||
String path = url.getPath();
|
||||
if (path == null)
|
||||
return null;
|
||||
|
||||
File f = new File(path);
|
||||
|
||||
String parent = f.getParent();
|
||||
|
||||
try {
|
||||
return new URL(url.getProtocol(), url.getHost(), url.getPort(),
|
||||
parent);
|
||||
} catch (MalformedURLException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static URL relativeTo(URL url, String filename) {
|
||||
// I'm guessing this completely fails on Windows, help wanted
|
||||
if (new File(filename).isAbsolute())
|
||||
return null;
|
||||
|
||||
URL parentURL = urlParent(url);
|
||||
if (parentURL == null)
|
||||
return null;
|
||||
try {
|
||||
URI parent = parentURL.toURI();
|
||||
URI relative = new URI(null, null, "/" + filename, null);
|
||||
return parent.relativize(relative).toURL();
|
||||
URI siblingURI = url.toURI();
|
||||
URI relative = new URI(filename);
|
||||
|
||||
// this seems wrong, but it's documented that the last
|
||||
// element of the path in siblingURI gets stripped out,
|
||||
// so to get something in the same directory as
|
||||
// siblingURI we just call resolve().
|
||||
URL resolved = siblingURI.resolve(relative).toURL();
|
||||
|
||||
return resolved;
|
||||
} catch (MalformedURLException e) {
|
||||
return null;
|
||||
} catch (URISyntaxException e) {
|
||||
return null;
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,7 +324,10 @@ public abstract class Parseable implements ConfigParseable {
|
||||
|
||||
@Override
|
||||
ConfigParseable relativeTo(String filename) {
|
||||
return newURL(relativeTo(input, filename), options()
|
||||
URL url = relativeTo(input, filename);
|
||||
if (url == null)
|
||||
return null;
|
||||
return newURL(url, options()
|
||||
.setOriginDescription(null));
|
||||
}
|
||||
|
||||
@ -382,8 +374,10 @@ public abstract class Parseable implements ConfigParseable {
|
||||
@Override
|
||||
ConfigParseable relativeTo(String filename) {
|
||||
try {
|
||||
return newURL(relativeTo(input.toURI().toURL(), filename),
|
||||
options().setOriginDescription(null));
|
||||
URL url = relativeTo(input.toURI().toURL(), filename);
|
||||
if (url == null)
|
||||
return null;
|
||||
return newURL(url, options().setOriginDescription(null));
|
||||
} catch (MalformedURLException e) {
|
||||
return null;
|
||||
}
|
||||
|
5
src/test/resources/equiv03/includes.conf
Normal file
5
src/test/resources/equiv03/includes.conf
Normal file
@ -0,0 +1,5 @@
|
||||
letters {
|
||||
include "letters/a.conf"
|
||||
include "letters/b.json"
|
||||
include "letters/c"
|
||||
}
|
6
src/test/resources/equiv03/letters/a.conf
Normal file
6
src/test/resources/equiv03/letters/a.conf
Normal file
@ -0,0 +1,6 @@
|
||||
numbers {
|
||||
include "numbers/1.conf"
|
||||
include "numbers/2"
|
||||
}
|
||||
|
||||
a=ok
|
3
src/test/resources/equiv03/letters/b.json
Normal file
3
src/test/resources/equiv03/letters/b.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"b" : 507
|
||||
}
|
2
src/test/resources/equiv03/letters/c.conf
Normal file
2
src/test/resources/equiv03/letters/c.conf
Normal file
@ -0,0 +1,2 @@
|
||||
c.fromConf=89
|
||||
|
1
src/test/resources/equiv03/letters/c.properties
Normal file
1
src/test/resources/equiv03/letters/c.properties
Normal file
@ -0,0 +1 @@
|
||||
c.fromProp=true
|
1
src/test/resources/equiv03/letters/numbers/1.conf
Normal file
1
src/test/resources/equiv03/letters/numbers/1.conf
Normal file
@ -0,0 +1 @@
|
||||
"1"=1
|
1
src/test/resources/equiv03/letters/numbers/2.properties
Normal file
1
src/test/resources/equiv03/letters/numbers/2.properties
Normal file
@ -0,0 +1 @@
|
||||
2=abcd
|
14
src/test/resources/equiv03/original.json
Normal file
14
src/test/resources/equiv03/original.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"letters" : {
|
||||
"numbers" : {
|
||||
"2" : "abcd",
|
||||
"1" : 1
|
||||
},
|
||||
"a" : "ok",
|
||||
"b" : 507,
|
||||
"c" : {
|
||||
"fromConf" : 89,
|
||||
"fromProp" : true
|
||||
}
|
||||
}
|
||||
}
|
@ -13,5 +13,13 @@
|
||||
|
||||
"equiv01" : {
|
||||
include "equiv01/original.json"
|
||||
},
|
||||
|
||||
# missing includes are supposed to be silently ignored
|
||||
nonexistent {
|
||||
include "nothere"
|
||||
include "nothere.conf"
|
||||
include "nothere.json"
|
||||
include "nothere.properties"
|
||||
}
|
||||
}
|
||||
|
@ -87,8 +87,8 @@ class EquivalentsTest extends TestUtils {
|
||||
|
||||
// This is a little "checksum" to be sure we really tested what we were expecting.
|
||||
// it breaks every time you add a file, so you have to update it.
|
||||
assertEquals(2, dirCount)
|
||||
assertEquals(3, dirCount)
|
||||
// this is the number of files not named original.*
|
||||
assertEquals(12, fileCount)
|
||||
assertEquals(13, fileCount)
|
||||
}
|
||||
}
|
||||
|
74
src/test/scala/com/typesafe/config/impl/PublicApiTest.scala
Normal file
74
src/test/scala/com/typesafe/config/impl/PublicApiTest.scala
Normal file
@ -0,0 +1,74 @@
|
||||
package com.typesafe.config.impl
|
||||
|
||||
import org.junit.Assert._
|
||||
import org.junit._
|
||||
import scala.collection.JavaConverters._
|
||||
import com.typesafe.config._
|
||||
|
||||
class PublicApiTest extends TestUtils {
|
||||
@Test
|
||||
def basicLoadAndGet() {
|
||||
val conf = Config.load("test01")
|
||||
|
||||
val a = conf.getInt("ints.fortyTwo")
|
||||
val obj = conf.getObject("ints")
|
||||
val c = obj.getInt("fortyTwo")
|
||||
val ms = conf.getMilliseconds("durations.halfSecond")
|
||||
|
||||
// should have used system variables
|
||||
if (System.getenv("HOME") != null)
|
||||
assertEquals(System.getenv("HOME"), conf.getString("system.home"))
|
||||
|
||||
assertEquals(System.getProperty("java.version"), conf.getString("system.javaversion"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def noSystemVariables() {
|
||||
// should not have used system variables
|
||||
val conf = Config.load("test01", ConfigParseOptions.defaults(),
|
||||
ConfigResolveOptions.noSystem())
|
||||
|
||||
intercept[ConfigException.Null] {
|
||||
conf.getString("system.home")
|
||||
}
|
||||
intercept[ConfigException.Null] {
|
||||
conf.getString("system.javaversion")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
def canLimitLoadToJson {
|
||||
val options = ConfigParseOptions.defaults().setSyntax(ConfigSyntax.JSON);
|
||||
val conf = Config.load("test01", options, ConfigResolveOptions.defaults())
|
||||
|
||||
assertEquals(1, conf.getInt("fromJson1"))
|
||||
intercept[ConfigException.Missing] {
|
||||
conf.getInt("ints.fortyTwo")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
def canLimitLoadToProperties {
|
||||
val options = ConfigParseOptions.defaults().setSyntax(ConfigSyntax.PROPERTIES);
|
||||
val conf = Config.load("test01", options, ConfigResolveOptions.defaults())
|
||||
|
||||
assertEquals(1, conf.getInt("fromProps.one"))
|
||||
intercept[ConfigException.Missing] {
|
||||
conf.getInt("ints.fortyTwo")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
def canLimitLoadToConf {
|
||||
val options = ConfigParseOptions.defaults().setSyntax(ConfigSyntax.CONF);
|
||||
val conf = Config.load("test01", options, ConfigResolveOptions.defaults())
|
||||
|
||||
assertEquals(42, conf.getInt("ints.fortyTwo"))
|
||||
intercept[ConfigException.Missing] {
|
||||
conf.getInt("fromJson1")
|
||||
}
|
||||
intercept[ConfigException.Missing] {
|
||||
conf.getInt("fromProps.one")
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user