mirror of
https://github.com/lightbend/config.git
synced 2025-01-15 23:01:05 +08:00
move some stuff from ConfigImpl to a new class Loader
This is just to make ConfigImpl less of a random jumble.
This commit is contained in:
parent
99d3c17fd0
commit
ecad3b31f0
@ -1,20 +1,13 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.typesafe.config.ConfigConfig;
|
||||
import com.typesafe.config.ConfigException;
|
||||
import com.typesafe.config.ConfigObject;
|
||||
import com.typesafe.config.ConfigOrigin;
|
||||
|
||||
/** This is public but is only supposed to be used by the "config" package */
|
||||
public class ConfigImpl {
|
||||
@ -32,10 +25,7 @@ public class ConfigImpl {
|
||||
if (system != null)
|
||||
stack.add(system);
|
||||
|
||||
// now try to load a resource for each extension
|
||||
addResource(configConfig.rootPath() + ".conf", stack);
|
||||
addResource(configConfig.rootPath() + ".json", stack);
|
||||
addResource(configConfig.rootPath() + ".properties", stack);
|
||||
stack.add(Loader.load(configConfig.rootPath()));
|
||||
|
||||
ConfigTransformer transformer = withExtraTransformer(null);
|
||||
|
||||
@ -49,14 +39,6 @@ public class ConfigImpl {
|
||||
return (AbstractConfigObject) resolved;
|
||||
}
|
||||
|
||||
private static void addResource(String name,
|
||||
List<AbstractConfigObject> stack) {
|
||||
URL url = ConfigImpl.class.getResource("/" + name);
|
||||
if (url != null) {
|
||||
stack.add(loadURL(url));
|
||||
}
|
||||
}
|
||||
|
||||
static ConfigObject getEnvironmentAsConfig() {
|
||||
// This should not need to create a new config object
|
||||
// as long as the transformer is just the default transformer.
|
||||
@ -71,39 +53,6 @@ public class ConfigImpl {
|
||||
withExtraTransformer(null));
|
||||
}
|
||||
|
||||
static AbstractConfigObject loadURL(URL url) {
|
||||
if (url.getPath().endsWith(".properties")) {
|
||||
ConfigOrigin origin = new SimpleConfigOrigin(url.toExternalForm());
|
||||
Properties props = new Properties();
|
||||
InputStream stream = null;
|
||||
try {
|
||||
stream = url.openStream();
|
||||
props.load(stream);
|
||||
} catch (IOException e) {
|
||||
throw new ConfigException.IO(origin, "failed to open url", e);
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return fromProperties(url.toExternalForm(), props);
|
||||
} else {
|
||||
return forceParsedToObject(Parser.parse(url));
|
||||
}
|
||||
}
|
||||
|
||||
static AbstractConfigObject forceParsedToObject(AbstractConfigValue value) {
|
||||
if (value instanceof AbstractConfigObject) {
|
||||
return (AbstractConfigObject) value;
|
||||
} else {
|
||||
throw new ConfigException.WrongType(value.origin(), "",
|
||||
"object at file root", value.valueType().name());
|
||||
}
|
||||
}
|
||||
|
||||
private static ConfigTransformer withExtraTransformer(
|
||||
ConfigTransformer extraTransformer) {
|
||||
// idea is to avoid creating a new, unique transformer if there's no
|
||||
@ -120,7 +69,7 @@ public class ConfigImpl {
|
||||
|
||||
private static ConfigTransformer defaultTransformer = null;
|
||||
|
||||
private synchronized static ConfigTransformer defaultConfigTransformer() {
|
||||
synchronized static ConfigTransformer defaultConfigTransformer() {
|
||||
if (defaultTransformer == null) {
|
||||
defaultTransformer = new DefaultTransformer();
|
||||
}
|
||||
@ -137,8 +86,7 @@ public class ConfigImpl {
|
||||
}
|
||||
|
||||
private static AbstractConfigObject loadSystemProperties() {
|
||||
return fromProperties("system property", System.getProperties());
|
||||
|
||||
return Loader.fromProperties("system property", System.getProperties());
|
||||
}
|
||||
|
||||
// this is a hack to let us set system props in the test suite
|
||||
@ -146,75 +94,6 @@ public class ConfigImpl {
|
||||
systemProperties = null;
|
||||
}
|
||||
|
||||
private static AbstractConfigObject fromProperties(String originPrefix,
|
||||
Properties props) {
|
||||
Map<String, Map<String, AbstractConfigValue>> scopes = new HashMap<String, Map<String, AbstractConfigValue>>();
|
||||
Enumeration<?> i = props.propertyNames();
|
||||
while (i.hasMoreElements()) {
|
||||
Object o = i.nextElement();
|
||||
if (o instanceof String) {
|
||||
try {
|
||||
String path = (String) o;
|
||||
String last = ConfigUtil.lastElement(path);
|
||||
String exceptLast = ConfigUtil.exceptLastElement(path);
|
||||
if (exceptLast == null)
|
||||
exceptLast = "";
|
||||
Map<String, AbstractConfigValue> scope = scopes
|
||||
.get(exceptLast);
|
||||
if (scope == null) {
|
||||
scope = new HashMap<String, AbstractConfigValue>();
|
||||
scopes.put(exceptLast, scope);
|
||||
}
|
||||
String value = props.getProperty(path);
|
||||
scope.put(last, new ConfigString(new SimpleConfigOrigin(
|
||||
originPrefix + " " + path), value));
|
||||
} catch (ConfigException.BadPath e) {
|
||||
// just skip this one (log it?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pull out the list of objects that go inside other objects
|
||||
List<String> childPaths = new ArrayList<String>();
|
||||
for (String path : scopes.keySet()) {
|
||||
if (path != "")
|
||||
childPaths.add(path);
|
||||
}
|
||||
|
||||
// put everything in its parent, ensuring all parents exist
|
||||
for (String path : childPaths) {
|
||||
String parentPath = ConfigUtil.exceptLastElement(path);
|
||||
if (parentPath == null)
|
||||
parentPath = "";
|
||||
|
||||
Map<String, AbstractConfigValue> parent = scopes.get(parentPath);
|
||||
if (parent == null) {
|
||||
parent = new HashMap<String, AbstractConfigValue>();
|
||||
scopes.put(parentPath, parent);
|
||||
}
|
||||
// NOTE: we are evil and cheating, we mutate the map we
|
||||
// provide to SimpleConfigObject, which is not allowed by
|
||||
// its contract, but since we know nobody has a ref to this
|
||||
// SimpleConfigObject yet we can get away with it.
|
||||
AbstractConfigObject o = new SimpleConfigObject(
|
||||
new SimpleConfigOrigin(
|
||||
originPrefix + " " + path), null, scopes.get(path));
|
||||
String basename = ConfigUtil.lastElement(path);
|
||||
parent.put(basename, o);
|
||||
}
|
||||
|
||||
Map<String, AbstractConfigValue> root = scopes.get("");
|
||||
if (root == null) {
|
||||
// this would happen only if you had no properties at all
|
||||
// in "props"
|
||||
root = Collections.<String, AbstractConfigValue> emptyMap();
|
||||
}
|
||||
|
||||
// return root config object
|
||||
return new SimpleConfigObject(new SimpleConfigOrigin(originPrefix),
|
||||
null, root);
|
||||
}
|
||||
|
||||
private static AbstractConfigObject envVariables = null;
|
||||
|
||||
synchronized static AbstractConfigObject envVariablesConfig() {
|
||||
|
150
src/main/java/com/typesafe/config/impl/Loader.java
Normal file
150
src/main/java/com/typesafe/config/impl/Loader.java
Normal file
@ -0,0 +1,150 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.typesafe.config.ConfigException;
|
||||
import com.typesafe.config.ConfigOrigin;
|
||||
|
||||
final class Loader {
|
||||
static AbstractConfigObject load(String name) {
|
||||
List<AbstractConfigObject> stack = new ArrayList<AbstractConfigObject>();
|
||||
|
||||
// if name has an extension, only use that; otherwise merge all three
|
||||
if (name.endsWith(".conf") || name.endsWith(".json")
|
||||
|| name.endsWith(".properties")) {
|
||||
addResource(name, stack);
|
||||
} else {
|
||||
// .conf wins over .json wins over .properties;
|
||||
// arbitrary, but deterministic
|
||||
addResource(name + ".conf", stack);
|
||||
addResource(name + ".json", stack);
|
||||
addResource(name + ".properties", stack);
|
||||
}
|
||||
|
||||
AbstractConfigObject merged = AbstractConfigObject.merge(
|
||||
new SimpleConfigOrigin("config for " + name), stack,
|
||||
ConfigImpl.defaultConfigTransformer());
|
||||
|
||||
return merged;
|
||||
}
|
||||
|
||||
private static void addResource(String name,
|
||||
List<AbstractConfigObject> stack) {
|
||||
URL url = ConfigImpl.class.getResource("/" + name);
|
||||
if (url != null) {
|
||||
stack.add(loadURL(url));
|
||||
}
|
||||
}
|
||||
|
||||
private static AbstractConfigObject loadURL(URL url) {
|
||||
if (url.getPath().endsWith(".properties")) {
|
||||
ConfigOrigin origin = new SimpleConfigOrigin(url.toExternalForm());
|
||||
Properties props = new Properties();
|
||||
InputStream stream = null;
|
||||
try {
|
||||
stream = url.openStream();
|
||||
props.load(stream);
|
||||
} catch (IOException e) {
|
||||
throw new ConfigException.IO(origin, "failed to open url", e);
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return fromProperties(url.toExternalForm(), props);
|
||||
} else {
|
||||
return forceParsedToObject(Parser.parse(url));
|
||||
}
|
||||
}
|
||||
|
||||
private static AbstractConfigObject forceParsedToObject(
|
||||
AbstractConfigValue value) {
|
||||
if (value instanceof AbstractConfigObject) {
|
||||
return (AbstractConfigObject) value;
|
||||
} else {
|
||||
throw new ConfigException.WrongType(value.origin(), "",
|
||||
"object at file root", value.valueType().name());
|
||||
}
|
||||
}
|
||||
|
||||
static AbstractConfigObject fromProperties(String originPrefix,
|
||||
Properties props) {
|
||||
Map<String, Map<String, AbstractConfigValue>> scopes = new HashMap<String, Map<String, AbstractConfigValue>>();
|
||||
Enumeration<?> i = props.propertyNames();
|
||||
while (i.hasMoreElements()) {
|
||||
Object o = i.nextElement();
|
||||
if (o instanceof String) {
|
||||
try {
|
||||
String path = (String) o;
|
||||
String last = ConfigUtil.lastElement(path);
|
||||
String exceptLast = ConfigUtil.exceptLastElement(path);
|
||||
if (exceptLast == null)
|
||||
exceptLast = "";
|
||||
Map<String, AbstractConfigValue> scope = scopes
|
||||
.get(exceptLast);
|
||||
if (scope == null) {
|
||||
scope = new HashMap<String, AbstractConfigValue>();
|
||||
scopes.put(exceptLast, scope);
|
||||
}
|
||||
String value = props.getProperty(path);
|
||||
scope.put(last, new ConfigString(new SimpleConfigOrigin(
|
||||
originPrefix + " " + path), value));
|
||||
} catch (ConfigException.BadPath e) {
|
||||
// just skip this one (log it?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pull out the list of objects that go inside other objects
|
||||
List<String> childPaths = new ArrayList<String>();
|
||||
for (String path : scopes.keySet()) {
|
||||
if (path != "")
|
||||
childPaths.add(path);
|
||||
}
|
||||
|
||||
// put everything in its parent, ensuring all parents exist
|
||||
for (String path : childPaths) {
|
||||
String parentPath = ConfigUtil.exceptLastElement(path);
|
||||
if (parentPath == null)
|
||||
parentPath = "";
|
||||
|
||||
Map<String, AbstractConfigValue> parent = scopes.get(parentPath);
|
||||
if (parent == null) {
|
||||
parent = new HashMap<String, AbstractConfigValue>();
|
||||
scopes.put(parentPath, parent);
|
||||
}
|
||||
// NOTE: we are evil and cheating, we mutate the map we
|
||||
// provide to SimpleConfigObject, which is not allowed by
|
||||
// its contract, but since we know nobody has a ref to this
|
||||
// SimpleConfigObject yet we can get away with it.
|
||||
AbstractConfigObject o = new SimpleConfigObject(
|
||||
new SimpleConfigOrigin(originPrefix + " " + path), null,
|
||||
scopes.get(path));
|
||||
String basename = ConfigUtil.lastElement(path);
|
||||
parent.put(basename, o);
|
||||
}
|
||||
|
||||
Map<String, AbstractConfigValue> root = scopes.get("");
|
||||
if (root == null) {
|
||||
// this would happen only if you had no properties at all
|
||||
// in "props"
|
||||
root = Collections.<String, AbstractConfigValue> emptyMap();
|
||||
}
|
||||
|
||||
// return root config object
|
||||
return new SimpleConfigObject(new SimpleConfigOrigin(originPrefix),
|
||||
null, root);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user