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;
|
package com.typesafe.config.impl;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import com.typesafe.config.ConfigConfig;
|
import com.typesafe.config.ConfigConfig;
|
||||||
import com.typesafe.config.ConfigException;
|
import com.typesafe.config.ConfigException;
|
||||||
import com.typesafe.config.ConfigObject;
|
import com.typesafe.config.ConfigObject;
|
||||||
import com.typesafe.config.ConfigOrigin;
|
|
||||||
|
|
||||||
/** This is public but is only supposed to be used by the "config" package */
|
/** This is public but is only supposed to be used by the "config" package */
|
||||||
public class ConfigImpl {
|
public class ConfigImpl {
|
||||||
@ -32,10 +25,7 @@ public class ConfigImpl {
|
|||||||
if (system != null)
|
if (system != null)
|
||||||
stack.add(system);
|
stack.add(system);
|
||||||
|
|
||||||
// now try to load a resource for each extension
|
stack.add(Loader.load(configConfig.rootPath()));
|
||||||
addResource(configConfig.rootPath() + ".conf", stack);
|
|
||||||
addResource(configConfig.rootPath() + ".json", stack);
|
|
||||||
addResource(configConfig.rootPath() + ".properties", stack);
|
|
||||||
|
|
||||||
ConfigTransformer transformer = withExtraTransformer(null);
|
ConfigTransformer transformer = withExtraTransformer(null);
|
||||||
|
|
||||||
@ -49,14 +39,6 @@ public class ConfigImpl {
|
|||||||
return (AbstractConfigObject) resolved;
|
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() {
|
static ConfigObject getEnvironmentAsConfig() {
|
||||||
// This should not need to create a new config object
|
// This should not need to create a new config object
|
||||||
// as long as the transformer is just the default transformer.
|
// as long as the transformer is just the default transformer.
|
||||||
@ -71,39 +53,6 @@ public class ConfigImpl {
|
|||||||
withExtraTransformer(null));
|
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(
|
private static ConfigTransformer withExtraTransformer(
|
||||||
ConfigTransformer extraTransformer) {
|
ConfigTransformer extraTransformer) {
|
||||||
// idea is to avoid creating a new, unique transformer if there's no
|
// 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 static ConfigTransformer defaultTransformer = null;
|
||||||
|
|
||||||
private synchronized static ConfigTransformer defaultConfigTransformer() {
|
synchronized static ConfigTransformer defaultConfigTransformer() {
|
||||||
if (defaultTransformer == null) {
|
if (defaultTransformer == null) {
|
||||||
defaultTransformer = new DefaultTransformer();
|
defaultTransformer = new DefaultTransformer();
|
||||||
}
|
}
|
||||||
@ -137,8 +86,7 @@ public class ConfigImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static AbstractConfigObject loadSystemProperties() {
|
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
|
// this is a hack to let us set system props in the test suite
|
||||||
@ -146,75 +94,6 @@ public class ConfigImpl {
|
|||||||
systemProperties = null;
|
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;
|
private static AbstractConfigObject envVariables = null;
|
||||||
|
|
||||||
synchronized static AbstractConfigObject envVariablesConfig() {
|
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