From 9b44709c8989d74283130fe15e5fa49d3ad937ac Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 30 Nov 2011 01:51:36 -0500 Subject: [PATCH] support -Dconfig.resource, -Dconfig.file, -Dconfig.url system props These override application.{conf,json,properties} for ConfigFactory.load() --- README.md | 19 ++++++ .../com/typesafe/config/ConfigFactory.java | 66 +++++++++++++++++-- 2 files changed, 81 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9b2d8091..9225aa4d 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,25 @@ to provide a custom `Config` object to be used instead of the default, in case the application needs multiple configurations in one JVM or wants to load extra config files from somewhere. +For applications using `application.{conf,json,properties}`, +system properties can be used to force a different config source: + + - `config.resource` specifies a resource name - not a + basename, i.e. `application.conf` not `application` + - `config.file` specifies a filesystem path, again + it should include the extension, not be a basename + - `config.url` specifies a URL + +These system properties specify a _replacement_ for +`application.{conf,json,properties}`, not an addition. They only +affect apps using the default `ConfigFactory.load()` +configuration. In the replacement config file, you can use +`include "application"` to include the original default config +file; after the include statement you could go on to override +certain settings. (Caveat: right now includes are relative to the +including entity, so `include "application"` would only work from +another classpath resource, not from a file or URL.) + ## JSON Superset Tentatively called "Human-Optimized Config Object Notation" or diff --git a/config/src/main/java/com/typesafe/config/ConfigFactory.java b/config/src/main/java/com/typesafe/config/ConfigFactory.java index bb6716fb..c3012db0 100644 --- a/config/src/main/java/com/typesafe/config/ConfigFactory.java +++ b/config/src/main/java/com/typesafe/config/ConfigFactory.java @@ -5,6 +5,7 @@ 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; @@ -89,7 +90,7 @@ public final class ConfigFactory { /** * Like {@link #load(Config)} but allows you to specify * {@link ConfigResolveOptions}. - * + * * @param config * the application's portion of the configuration * @param resolveOptions @@ -102,15 +103,72 @@ 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( + "You set more than one system property from config.file, config.url, config.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("Bad URL in config.url system property: '" + url + + "'", 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. *

* This method may return a cached singleton. + *

+ * If the system properties 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. + *

+ * If no system properties are set to change the location of the default + * configuration, ConfigFactory.load() is equivalent to + * ConfigFactory.load("application"). * * @return configuration for an application */