Fix allow missing for the AnySyntax parse methods, issue gh-1

This fix could in theory go further and Parseable.relativeTo
could return a ParseableNotFound instead of null, but for now
eliminate null from within ConfigImpl at least.
This commit is contained in:
Havoc Pennington 2011-12-07 09:08:43 -05:00
parent 002fd53e8e
commit b13f1fbe88
3 changed files with 99 additions and 25 deletions
config/src
main/java/com/typesafe/config/impl
test/scala/com/typesafe/config/impl

View File

@ -51,36 +51,46 @@ public class ConfigImpl {
ConfigParseable jsonHandle = source.nameToParseable(name + ".json");
ConfigParseable propsHandle = source.nameToParseable(name
+ ".properties");
if (!options.getAllowMissing() && confHandle == null
&& jsonHandle == null && propsHandle == null) {
throw new ConfigException.IO(SimpleConfigOrigin.newSimple(name),
"No config files {.conf,.json,.properties} found");
}
boolean gotSomething = false;
ConfigSyntax syntax = options.getSyntax();
obj = SimpleConfigObject.empty(SimpleConfigOrigin.newSimple(name));
if (confHandle != null
&& (syntax == null || syntax == ConfigSyntax.CONF)) {
obj = confHandle.parse(confHandle.options()
.setAllowMissing(true).setSyntax(ConfigSyntax.CONF));
if (syntax == null || syntax == ConfigSyntax.CONF) {
try {
obj = confHandle.parse(confHandle.options().setAllowMissing(false)
.setSyntax(ConfigSyntax.CONF));
gotSomething = true;
} catch (ConfigException.IO e) {
}
}
if (jsonHandle != null
&& (syntax == null || syntax == ConfigSyntax.JSON)) {
ConfigObject parsed = jsonHandle.parse(jsonHandle
.options().setAllowMissing(true)
.setSyntax(ConfigSyntax.JSON));
obj = obj.withFallback(parsed);
if (syntax == null || syntax == ConfigSyntax.JSON) {
try {
ConfigObject parsed = jsonHandle.parse(jsonHandle.options()
.setAllowMissing(false).setSyntax(ConfigSyntax.JSON));
obj = obj.withFallback(parsed);
gotSomething = true;
} catch (ConfigException.IO e) {
}
}
if (propsHandle != null
&& (syntax == null || syntax == ConfigSyntax.PROPERTIES)) {
ConfigObject parsed = propsHandle.parse(propsHandle.options()
.setAllowMissing(true)
.setSyntax(ConfigSyntax.PROPERTIES));
obj = obj.withFallback(parsed);
if (syntax == null || syntax == ConfigSyntax.PROPERTIES) {
try {
ConfigObject parsed = propsHandle.parse(propsHandle.options()
.setAllowMissing(false).setSyntax(ConfigSyntax.PROPERTIES));
obj = obj.withFallback(parsed);
gotSomething = true;
} catch (ConfigException.IO e) {
}
}
if (!options.getAllowMissing() && !gotSomething) {
throw new ConfigException.IO(SimpleConfigOrigin.newSimple(name), String.format(
"None of %s.conf, %s.json, %s.properties were found", name, name, name));
}
}
@ -269,7 +279,14 @@ public class ConfigImpl {
NameSource source = new NameSource() {
@Override
public ConfigParseable nameToParseable(String name) {
return context.relativeTo(name);
ConfigParseable p = context.relativeTo(name);
if (p == null) {
// avoid returning null
return Parseable.newNotFound(name, "include was not found: '" + name + "'",
ConfigParseOptions.defaults());
} else {
return p;
}
}
};

View File

@ -6,6 +6,7 @@ package com.typesafe.config.impl;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilterReader;
import java.io.IOException;
import java.io.InputStream;
@ -261,6 +262,34 @@ public abstract class Parseable implements ConfigParseable {
return new File(parent, filename);
}
// this is a parseable that doesn't exist and just throws when you try to
// parse it
private final static class ParseableNotFound extends Parseable {
final private String what;
final private String message;
ParseableNotFound(String what, String message, ConfigParseOptions options) {
this.what = what;
this.message = message;
postConstruct(options);
}
@Override
protected Reader reader() throws IOException {
throw new FileNotFoundException(message);
}
@Override
protected ConfigOrigin createOrigin() {
return SimpleConfigOrigin.newSimple(what);
}
}
public static Parseable newNotFound(String whatNotFound, String message,
ConfigParseOptions options) {
return new ParseableNotFound(whatNotFound, message, options);
}
private final static class ParseableReader extends Parseable {
final private Reader reader;

View File

@ -229,15 +229,43 @@ class PublicApiTest extends TestUtils {
assertNull(d.getSyntax())
}
private def assertNotFound(e: ConfigException) {
assertTrue("Message text: " + e.getMessage, e.getMessage.contains("No such") ||
e.getMessage.contains("not found") ||
e.getMessage.contains("were found"))
}
@Test
def allowMissing() {
val e = intercept[ConfigException.IO] {
ConfigFactory.parseFile(resourceFile("nonexistent.conf"), ConfigParseOptions.defaults().setAllowMissing(false))
}
assertTrue(e.getMessage.contains("No such"))
assertNotFound(e)
val conf = ConfigFactory.parseFile(resourceFile("nonexistent.conf"), ConfigParseOptions.defaults().setAllowMissing(true))
assertTrue(conf.isEmpty())
assertTrue("is empty", conf.isEmpty())
}
@Test
def allowMissingFileAnySyntax() {
val e = intercept[ConfigException.IO] {
ConfigFactory.parseFileAnySyntax(resourceFile("nonexistent"), ConfigParseOptions.defaults().setAllowMissing(false))
}
assertNotFound(e)
val conf = ConfigFactory.parseFileAnySyntax(resourceFile("nonexistent"), ConfigParseOptions.defaults().setAllowMissing(true))
assertTrue("is empty", conf.isEmpty())
}
@Test
def allowMissingResourcesAnySyntax() {
val e = intercept[ConfigException.IO] {
ConfigFactory.parseResourcesAnySyntax(classOf[PublicApiTest], "nonexistent", ConfigParseOptions.defaults().setAllowMissing(false))
}
assertNotFound(e)
val conf = ConfigFactory.parseResourcesAnySyntax(classOf[PublicApiTest], "nonexistent", ConfigParseOptions.defaults().setAllowMissing(true))
assertTrue("is empty", conf.isEmpty())
}
@Test