${foo.bar} syntax, see
* If no paths are specified in checkValid()'s parameter list,
* validation is for the entire config.
- *
+ *
*
* If you specify paths that are not in the reference config, those paths
* are ignored. (There's nothing to validate.)
@@ -465,7 +462,7 @@ public interface Config extends ConfigMergeable {
List extends Object> getAnyRefList(String path);
- List
- * To be aware of: using
- * {@link ConfigResolveOptions#setUseSystemProperties(boolean)
- * setUseSystemProperties(false)} with this method has no meaningful effect,
- * because the system properties are merged into the config as overrides
- * anyway.
- * To be aware of: using
- * {@link ConfigResolveOptions#setUseSystemProperties(boolean)
- * setUseSystemProperties(false)} with this method has no meaningful effect,
- * because the system properties are merged into the config as overrides
- * anyway.
* This method may return a cached singleton.
+ *
+ * If the system properties
+ * If no system properties are set to change the location of the default
+ * configuration,
* This object is immutable, so the "setters" return a new object.
- *
*
* Here is an example of creating a custom {@code ConfigResolveOptions}:
- *
*
* In addition to {@link ConfigResolveOptions#defaults}, there's a prebuilt
* {@link ConfigResolveOptions#noSystem} which avoids looking at any system
- * properties or environment variables.
+ * environment variables or other external system information. (Right now,
+ * environment variables are the only example.)
*/
public final class ConfigResolveOptions {
- private final boolean useSystemProperties;
private final boolean useSystemEnvironment;
- private ConfigResolveOptions(boolean useSystemProperties,
- boolean useSystemEnvironment) {
- this.useSystemProperties = useSystemProperties;
+ private ConfigResolveOptions(boolean useSystemEnvironment) {
this.useSystemEnvironment = useSystemEnvironment;
}
@@ -41,31 +34,17 @@ public final class ConfigResolveOptions {
* @return the default resolve options
*/
public static ConfigResolveOptions defaults() {
- return new ConfigResolveOptions(true, true);
+ return new ConfigResolveOptions(true);
}
/**
* Returns resolve options that disable any reference to "system" data
- * (system properties or environment variables).
+ * (currently, this means environment variables).
*
- * @return the resolve options with system properties and env variables
- * disabled
+ * @return the resolve options with env variables disabled
*/
public static ConfigResolveOptions noSystem() {
- return defaults().setUseSystemEnvironment(false).setUseSystemProperties(false);
- }
-
- /**
- * Returns options with use of Java system properties set to the given
- * value.
- *
- * @param value
- * true to resolve substitutions falling back to Java system
- * properties.
- * @return options with requested setting for use of system properties
- */
- public ConfigResolveOptions setUseSystemProperties(boolean value) {
- return new ConfigResolveOptions(value, useSystemEnvironment);
+ return defaults().setUseSystemEnvironment(false);
}
/**
@@ -76,18 +55,9 @@ public final class ConfigResolveOptions {
* variables.
* @return options with requested setting for use of environment variables
*/
+ @SuppressWarnings("static-method")
public ConfigResolveOptions setUseSystemEnvironment(boolean value) {
- return new ConfigResolveOptions(useSystemProperties, value);
- }
-
- /**
- * Returns whether the options enable use of system properties. This method
- * is mostly used by the config lib internally, not by applications.
- *
- * @return true if system properties should be used
- */
- public boolean getUseSystemProperties() {
- return useSystemProperties;
+ return new ConfigResolveOptions(value);
}
/**
diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/AbstractConfigObject.java b/akka-actor/src/main/java/com/typesafe/config/impl/AbstractConfigObject.java
index 3f7cc0edf1..428a7b2b3f 100644
--- a/akka-actor/src/main/java/com/typesafe/config/impl/AbstractConfigObject.java
+++ b/akka-actor/src/main/java/com/typesafe/config/impl/AbstractConfigObject.java
@@ -35,6 +35,11 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements
return config;
}
+ @Override
+ public AbstractConfigObject toFallbackValue() {
+ return this;
+ }
+
/**
* This looks up the key with no transformation or type conversion of any
* kind, and returns null if the key is not present.
@@ -135,6 +140,7 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements
if (ignoresFallbacks())
throw new ConfigException.BugOrBroken("should not be reached");
+ boolean changed = false;
boolean allResolved = true;
MapcheckValid() includes a list of problems encountered.
+ */
public static class ValidationProblem {
final private String path;
@@ -279,19 +289,31 @@ public class ConfigException extends RuntimeException {
this.problem = problem;
}
+ /** Returns the config setting causing the problem. */
public String path() {
return path;
}
+ /**
+ * Returns where the problem occurred (origin may include info on the
+ * file, line number, etc.).
+ */
public ConfigOrigin origin() {
return origin;
}
+ /** Returns a description of the problem. */
public String problem() {
return problem;
}
}
+ /**
+ * Exception indicating that {@link Config#checkValid} found validity
+ * problems. The problems are available via the {@link #problems()} method.
+ * The getMessage() of this exception is a potentially very
+ * long string listing all the problems found.
+ */
public static class ValidationFailed extends ConfigException {
private static final long serialVersionUID = 1L;
@@ -321,4 +343,20 @@ public class ConfigException extends RuntimeException {
return sb.toString();
}
}
+
+ /**
+ * Exception that doesn't fall into any other category.
+ */
+ public static class Generic extends ConfigException {
+ private static final long serialVersionUID = 1L;
+
+ public Generic(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public Generic(String message) {
+ this(message, null);
+ }
+ }
+
}
diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java b/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java
index 36ad5c54b4..9251b3fb45 100644
--- a/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java
+++ b/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java
@@ -5,11 +5,13 @@ package com.typesafe.config;
import java.io.File;
import java.io.Reader;
+import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.Properties;
import com.typesafe.config.impl.ConfigImpl;
+import com.typesafe.config.impl.ConfigUtil;
import com.typesafe.config.impl.Parseable;
/**
@@ -57,16 +59,6 @@ public final class ConfigFactory {
/**
* Like {@link #load(String)} but allows you to specify parse and resolve
* options.
- *
- * setUseSystemProperties affects whether to fall back
- * to system properties when they are not found in the config, but with
- * load(), they will be in the config.
- *
* @param resourceBasename
* the classpath resource name with optional extension
* @param parseOptions
@@ -100,15 +92,6 @@ public final class ConfigFactory {
* Like {@link #load(Config)} but allows you to specify
* {@link ConfigResolveOptions}.
*
- * setUseSystemProperties affects whether to fall back
- * to system properties when they are not found in the config, but with
- * load(), they will be in the config.
- *
* @param config
* the application's portion of the configuration
* @param resolveOptions
@@ -121,20 +104,83 @@ public final class ConfigFactory {
}
private static class DefaultConfigHolder {
- static final Config defaultConfig = load("application");
+
+ private static Config loadDefaultConfig() {
+ int specified = 0;
+
+ // override application.conf with config.file, config.resource,
+ // config.url if requested.
+ String resource = System.getProperty("config.resource");
+ if (resource != null)
+ specified += 1;
+ String file = System.getProperty("config.file");
+ if (file != null)
+ specified += 1;
+ String url = System.getProperty("config.url");
+ if (url != null)
+ specified += 1;
+
+ if (specified == 0) {
+ return load("application");
+ } else if (specified > 1) {
+ throw new ConfigException.Generic("You set more than one of config.file='" + file
+ + "', config.url='" + url + "', config.resource='" + resource
+ + "'; don't know which one to use!");
+ } else {
+ if (resource != null) {
+ // this deliberately does not parseResourcesAnySyntax; if
+ // people want that they can use an include statement.
+ return load(parseResources(ConfigFactory.class, resource));
+ } else if (file != null) {
+ return load(parseFile(new File(file)));
+ } else {
+ try {
+ return load(parseURL(new URL(url)));
+ } catch (MalformedURLException e) {
+ throw new ConfigException.Generic(
+ "Bad URL in config.url system property: '" + url + "': "
+ + e.getMessage(), e);
+ }
+ }
+ }
+ }
+
+ static final Config defaultConfig = loadDefaultConfig();
}
/**
* Loads a default configuration, equivalent to {@link #load(String)
- * load("application")}. This configuration should be used by libraries and
- * frameworks unless an application provides a different one.
+ * load("application")} in most cases. This configuration should be used by
+ * libraries and frameworks unless an application provides a different one.
* config.resource,
+ * config.file, or config.url are set, then the
+ * classpath resource, file, or URL specified in those properties will be
+ * used rather than the default
+ * application.{conf,json,properties} classpath resources.
+ * These system properties should not be set in code (after all, you can
+ * just parse whatever you want manually and then use {@link #load(Config)
+ * if you don't want to use application.conf}). The properties
+ * are intended for use by the person or script launching the application.
+ * For example someone might have a production.conf that
+ * include application.conf but then change a couple of values.
+ * When launching the app they could specify
+ * -Dconfig.resource=production.conf to get production mode.
+ * ConfigFactory.load() is equivalent to
+ * ConfigFactory.load("application").
*
* @return configuration for an application
*/
public static Config load() {
- return DefaultConfigHolder.defaultConfig;
+ try {
+ return DefaultConfigHolder.defaultConfig;
+ } catch (ExceptionInInitializerError e) {
+ throw ConfigUtil.extractInitializerError(e);
+ }
}
/**
diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigMergeable.java b/akka-actor/src/main/java/com/typesafe/config/ConfigMergeable.java
index 356f89021b..c4280e93ea 100644
--- a/akka-actor/src/main/java/com/typesafe/config/ConfigMergeable.java
+++ b/akka-actor/src/main/java/com/typesafe/config/ConfigMergeable.java
@@ -17,15 +17,6 @@ package com.typesafe.config;
* implementations will break.
*/
public interface ConfigMergeable {
- /**
- * Converts this instance to a {@link ConfigValue}. If called on a
- * {@code ConfigValue} it returns {@code this}, if called on a
- * {@link Config} it's equivalent to {@link Config#root()}.
- *
- * @return this instance as a {@code ConfigValue}
- */
- ConfigValue toValue();
-
/**
* Returns a new value computed by merging this value with another, with
* keys in this value "winning" over the other one. Only
diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigResolveOptions.java b/akka-actor/src/main/java/com/typesafe/config/ConfigResolveOptions.java
index 8ed11c4bba..37c7b36d5b 100644
--- a/akka-actor/src/main/java/com/typesafe/config/ConfigResolveOptions.java
+++ b/akka-actor/src/main/java/com/typesafe/config/ConfigResolveOptions.java
@@ -7,31 +7,24 @@ package com.typesafe.config;
* A set of options related to resolving substitutions. Substitutions use the
* ${foo.bar} syntax and are documented in the HOCON spec.
- *
*
* ConfigResolveOptions options = ConfigResolveOptions.defaults()
- * .setUseSystemProperties(false)
* .setUseSystemEnvironment(false)
*
- *
*