Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding ability to uses lists of configs, both with resources and files #1169

Merged
merged 3 commits into from
Sep 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ For reference on all existing options, their description and defaults you may re
To override needed options you may use one of the following ways:
* put your options to the `<working dir>/config/ethereumj.conf` file
* put `user.conf` to the root of your classpath (as a resource)
* put your options to any file and supply it via `-Dethereumj.conf.file=<your config>`
* put your options to any file and supply it via `-Dethereumj.conf.file=<your config>`, accepts several configs, separated by comma applied in provided order: `-Dethereumj.conf.file=<config1>,<config2>`
* programmatically by using `SystemProperties.CONFIG.override*()`
* programmatically using by overriding Spring `SystemProperties` bean

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import java.net.Socket;
import java.net.URL;
import java.util.*;
import java.util.function.Function;

import static org.ethereum.crypto.HashUtil.sha3;
import static org.ethereum.util.ByteUtil.toHexString;
Expand Down Expand Up @@ -185,8 +186,8 @@ public SystemProperties(Config apiConfig, ClassLoader classLoader) {
Config referenceConfig = ConfigFactory.parseResources("ethereumj.conf");
logger.info("Config (" + (referenceConfig.entrySet().size() > 0 ? " yes " : " no ") + "): default properties from resource 'ethereumj.conf'");
String res = System.getProperty("ethereumj.conf.res");
Config cmdLineConfigRes = res != null ? ConfigFactory.parseResources(res) : ConfigFactory.empty();
logger.info("Config (" + (cmdLineConfigRes.entrySet().size() > 0 ? " yes " : " no ") + "): user properties from -Dethereumj.conf.res resource '" + res + "'");
Config cmdLineConfigRes = mergeConfigs(res, ConfigFactory::parseResources);
logger.info("Config (" + (cmdLineConfigRes.entrySet().size() > 0 ? " yes " : " no ") + "): user properties from -Dethereumj.conf.res resource(s) '" + res + "'");
Config userConfig = ConfigFactory.parseResources("user.conf");
logger.info("Config (" + (userConfig.entrySet().size() > 0 ? " yes " : " no ") + "): user properties from resource 'user.conf'");
File userDirFile = new File(System.getProperty("user.dir"), "/config/ethereumj.conf");
Expand All @@ -197,8 +198,8 @@ public SystemProperties(Config apiConfig, ClassLoader classLoader) {
Config testUserConfig = ConfigFactory.parseResources("test-user.conf");
logger.info("Config (" + (testUserConfig.entrySet().size() > 0 ? " yes " : " no ") + "): test properties from resource 'test-user.conf'");
String file = System.getProperty("ethereumj.conf.file");
Config cmdLineConfigFile = file != null ? ConfigFactory.parseFile(new File(file)) : ConfigFactory.empty();
logger.info("Config (" + (cmdLineConfigFile.entrySet().size() > 0 ? " yes " : " no ") + "): user properties from -Dethereumj.conf.file file '" + file + "'");
Config cmdLineConfigFile = mergeConfigs(res, s -> ConfigFactory.parseFile(new File(s)));
logger.info("Config (" + (cmdLineConfigFile.entrySet().size() > 0 ? " yes " : " no ") + "): user properties from -Dethereumj.conf.file file(s) '" + file + "'");
logger.info("Config (" + (apiConfig.entrySet().size() > 0 ? " yes " : " no ") + "): config passed via constructor");
config = apiConfig
.withFallback(cmdLineConfigFile)
Expand Down Expand Up @@ -316,6 +317,27 @@ private void validateConfig() {
}
}

/**
* Builds config from the list of config references in string doing following actions:
* 1) Splits input by "," to several strings
* 2) Uses parserFunc to create config from each string reference
* 3) Merges configs, applying them in the same order as in input, so last overrides first
* @param input String with list of config references separated by ",", null or one reference works fine
* @param parserFunc Function to apply to each reference, produces config from it
* @return Merged config
*/
protected Config mergeConfigs(String input, Function<String, Config> parserFunc) {
Config config = ConfigFactory.empty();
if (input != null && !input.isEmpty()) {
String[] list = input.split(",");
for (int i = list.length - 1; i >= 0; --i) {
config = config.withFallback(parserFunc.apply(list[i]));
}
}

return config;
}

public <T> T getProperty(String propName, T defaultValue) {
if (!config.hasPath(propName)) return defaultValue;
String string = config.getString(propName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,39 @@ public void testDump() {
assertTrue(StringUtils.countOccurrencesOf(dump, "{") > 50);
}

@Test
public void testMergeConfigs1() {
String firstConfig = "";
SystemProperties props = new SystemProperties();
Config config = props.mergeConfigs(firstConfig, ConfigFactory::parseString);
assertFalse(config.hasPath("peer.listen.port"));
}

@Test
public void testMergeConfigs2() {
String firstConfig = "peer.listen.port=30123";
SystemProperties props = new SystemProperties();
Config config = props.mergeConfigs(firstConfig, ConfigFactory::parseString);
assertEquals(30123, config.getInt("peer.listen.port"));
}

@Test
public void testMergeConfigs3() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It lacks of test case with different properties that are eventually merged into single configuration.

String firstConfig = "peer.listen.port=30123,peer.listen.port=30145";
SystemProperties props = new SystemProperties();
Config config = props.mergeConfigs(firstConfig, ConfigFactory::parseString);
assertEquals(30145, config.getInt("peer.listen.port"));
}

@Test
public void testMergeConfigs4() {
String firstConfig = "peer.listen.port=30123,sync.enabled=true";
SystemProperties props = new SystemProperties();
Config config = props.mergeConfigs(firstConfig, ConfigFactory::parseString);
assertEquals(30123, config.getInt("peer.listen.port"));
assertEquals(Boolean.TRUE, config.getBoolean("sync.enabled"));
}

@SuppressWarnings("SameParameterValue")
static class ActivePeer {
boolean asEnodeUrl;
Expand Down