diff --git a/src/main/java/com/typesafe/config/ConfigFactory.java b/src/main/java/com/typesafe/config/ConfigFactory.java index 3eaca956..cd82e3fa 100644 --- a/src/main/java/com/typesafe/config/ConfigFactory.java +++ b/src/main/java/com/typesafe/config/ConfigFactory.java @@ -141,12 +141,45 @@ public final class ConfigFactory { return Parseable.newFile(file, options).parse().toConfig(); } + /** + * Parses a file. If the fileBasename already ends in a known extension, + * just parses it according to that extension. If the fileBasename does not + * end in an extension, then parse all known extensions and merge whatever + * is found. If options force a specific syntax, only parse files with an + * extension matching that syntax. If options.getAllowMissing() is true, + * then no files have to exist; if false, then at least one file has to + * exist. + * + * @param fileBasename + * @param options + * @return + */ + public static Config parseFileAnySyntax(File fileBasename, + ConfigParseOptions options) { + return ConfigImpl.parseFileAnySyntax(fileBasename, options).toConfig(); + } + public static Config parseResource(Class klass, String resource, ConfigParseOptions options) { return Parseable.newResource(klass, resource, options).parse() .toConfig(); } + /** + * Same behavior as parseFileAnySyntax() but for classpath resources + * instead. + * + * @param klass + * @param resourceBasename + * @param options + * @return + */ + public static Config parseResourceAnySyntax(Class klass, String resourceBasename, + ConfigParseOptions options) { + return ConfigImpl.parseResourceAnySyntax(klass, resourceBasename, + options).toConfig(); + } + public static Config parseString(String s, ConfigParseOptions options) { return Parseable.newString(s, options).parse().toConfig(); } diff --git a/src/main/java/com/typesafe/config/impl/ConfigImpl.java b/src/main/java/com/typesafe/config/impl/ConfigImpl.java index d8606e75..9f45cb37 100644 --- a/src/main/java/com/typesafe/config/impl/ConfigImpl.java +++ b/src/main/java/com/typesafe/config/impl/ConfigImpl.java @@ -1,5 +1,6 @@ package com.typesafe.config.impl; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -55,9 +56,10 @@ public class ConfigImpl { ConfigParseable nameToParseable(String name); } - // this function is a little tricky because there are two places we're - // trying to use it; for 'include "basename"' in a .conf file, and for - // loading app.{conf,json,properties} from classpath. + // this function is a little tricky because there are three places we're + // trying to use it; for 'include "basename"' in a .conf file, for + // loading app.{conf,json,properties} from classpath, and for + // loading app.{conf,json,properties} from the filesystem. private static ConfigObject fromBasename(NameSource source, String name, ConfigParseOptions options) { ConfigObject obj; @@ -136,14 +138,31 @@ public class ConfigImpl { final ConfigParseOptions baseOptions) { Path path = Parser.parsePath(expression); String basename = makeResourceBasename(path); + return parseResourceAnySyntax(ConfigImpl.class, basename, baseOptions); + } + + /** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */ + public static ConfigObject parseResourceAnySyntax(final Class klass, + String resourceBasename, final ConfigParseOptions baseOptions) { NameSource source = new NameSource() { @Override public ConfigParseable nameToParseable(String name) { - return Parseable.newResource(ConfigImpl.class, name, - baseOptions); + return Parseable.newResource(klass, name, baseOptions); } }; - return fromBasename(source, basename, baseOptions); + return fromBasename(source, resourceBasename, baseOptions); + } + + /** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */ + public static ConfigObject parseFileAnySyntax(final File basename, + final ConfigParseOptions baseOptions) { + NameSource source = new NameSource() { + @Override + public ConfigParseable nameToParseable(String name) { + return Parseable.newFile(new File(name), baseOptions); + } + }; + return fromBasename(source, basename.getPath(), baseOptions); } /** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */ diff --git a/src/test/scala/com/typesafe/config/impl/PublicApiTest.scala b/src/test/scala/com/typesafe/config/impl/PublicApiTest.scala index b915b466..f457d365 100644 --- a/src/test/scala/com/typesafe/config/impl/PublicApiTest.scala +++ b/src/test/scala/com/typesafe/config/impl/PublicApiTest.scala @@ -321,4 +321,33 @@ class PublicApiTest extends TestUtils { assertEquals(List("letters/a.conf", "numbers/1.conf", "numbers/2", "letters/b.json", "letters/c"), included.map(_.name)) } + + @Test + def anySyntax() { + // test01 has all three syntaxes; first load with basename + val conf = ConfigFactory.parseFileAnySyntax(resourceFile("test01"), ConfigParseOptions.defaults()) + assertEquals(42, conf.getInt("ints.fortyTwo")) + assertEquals("A", conf.getString("fromJsonA")) + assertEquals("true", conf.getString("fromProps.bool")) + + // now include a suffix, should only load one of them + val onlyProps = ConfigFactory.parseFileAnySyntax(resourceFile("test01.properties"), ConfigParseOptions.defaults()) + assertFalse(onlyProps.hasPath("ints.fortyTwo")) + assertFalse(onlyProps.hasPath("fromJsonA")) + assertEquals("true", onlyProps.getString("fromProps.bool")) + + // force only one syntax via options + val onlyPropsViaOptions = ConfigFactory.parseFileAnySyntax(resourceFile("test01.properties"), + ConfigParseOptions.defaults().setSyntax(ConfigSyntax.PROPERTIES)) + assertFalse(onlyPropsViaOptions.hasPath("ints.fortyTwo")) + assertFalse(onlyPropsViaOptions.hasPath("fromJsonA")) + assertEquals("true", onlyPropsViaOptions.getString("fromProps.bool")) + + // make sure it works with resources too + val fromResources = ConfigFactory.parseResourceAnySyntax(classOf[PublicApiTest], "/test01", + ConfigParseOptions.defaults()) + assertEquals(42, fromResources.getInt("ints.fortyTwo")) + assertEquals("A", fromResources.getString("fromJsonA")) + assertEquals("true", fromResources.getString("fromProps.bool")) + } }