Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Commit 5c808c1

Browse files
authored
Merge pull request #1169 from ethereum/feature/config-list
Adding ability to uses lists of configs, both with resources and files
2 parents 5474319 + 53f52c0 commit 5c808c1

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ For reference on all existing options, their description and defaults you may re
102102
To override needed options you may use one of the following ways:
103103
* put your options to the `<working dir>/config/ethereumj.conf` file
104104
* put `user.conf` to the root of your classpath (as a resource)
105-
* put your options to any file and supply it via `-Dethereumj.conf.file=<your config>`
105+
* 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>`
106106
* programmatically by using `SystemProperties.CONFIG.override*()`
107107
* programmatically using by overriding Spring `SystemProperties` bean
108108

ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import java.net.Socket;
5353
import java.net.URL;
5454
import java.util.*;
55+
import java.util.function.Function;
5556

5657
import static org.ethereum.crypto.HashUtil.sha3;
5758
import static org.ethereum.util.ByteUtil.toHexString;
@@ -185,8 +186,8 @@ public SystemProperties(Config apiConfig, ClassLoader classLoader) {
185186
Config referenceConfig = ConfigFactory.parseResources("ethereumj.conf");
186187
logger.info("Config (" + (referenceConfig.entrySet().size() > 0 ? " yes " : " no ") + "): default properties from resource 'ethereumj.conf'");
187188
String res = System.getProperty("ethereumj.conf.res");
188-
Config cmdLineConfigRes = res != null ? ConfigFactory.parseResources(res) : ConfigFactory.empty();
189-
logger.info("Config (" + (cmdLineConfigRes.entrySet().size() > 0 ? " yes " : " no ") + "): user properties from -Dethereumj.conf.res resource '" + res + "'");
189+
Config cmdLineConfigRes = mergeConfigs(res, ConfigFactory::parseResources);
190+
logger.info("Config (" + (cmdLineConfigRes.entrySet().size() > 0 ? " yes " : " no ") + "): user properties from -Dethereumj.conf.res resource(s) '" + res + "'");
190191
Config userConfig = ConfigFactory.parseResources("user.conf");
191192
logger.info("Config (" + (userConfig.entrySet().size() > 0 ? " yes " : " no ") + "): user properties from resource 'user.conf'");
192193
File userDirFile = new File(System.getProperty("user.dir"), "/config/ethereumj.conf");
@@ -197,8 +198,8 @@ public SystemProperties(Config apiConfig, ClassLoader classLoader) {
197198
Config testUserConfig = ConfigFactory.parseResources("test-user.conf");
198199
logger.info("Config (" + (testUserConfig.entrySet().size() > 0 ? " yes " : " no ") + "): test properties from resource 'test-user.conf'");
199200
String file = System.getProperty("ethereumj.conf.file");
200-
Config cmdLineConfigFile = file != null ? ConfigFactory.parseFile(new File(file)) : ConfigFactory.empty();
201-
logger.info("Config (" + (cmdLineConfigFile.entrySet().size() > 0 ? " yes " : " no ") + "): user properties from -Dethereumj.conf.file file '" + file + "'");
201+
Config cmdLineConfigFile = mergeConfigs(res, s -> ConfigFactory.parseFile(new File(s)));
202+
logger.info("Config (" + (cmdLineConfigFile.entrySet().size() > 0 ? " yes " : " no ") + "): user properties from -Dethereumj.conf.file file(s) '" + file + "'");
202203
logger.info("Config (" + (apiConfig.entrySet().size() > 0 ? " yes " : " no ") + "): config passed via constructor");
203204
config = apiConfig
204205
.withFallback(cmdLineConfigFile)
@@ -316,6 +317,27 @@ private void validateConfig() {
316317
}
317318
}
318319

320+
/**
321+
* Builds config from the list of config references in string doing following actions:
322+
* 1) Splits input by "," to several strings
323+
* 2) Uses parserFunc to create config from each string reference
324+
* 3) Merges configs, applying them in the same order as in input, so last overrides first
325+
* @param input String with list of config references separated by ",", null or one reference works fine
326+
* @param parserFunc Function to apply to each reference, produces config from it
327+
* @return Merged config
328+
*/
329+
protected Config mergeConfigs(String input, Function<String, Config> parserFunc) {
330+
Config config = ConfigFactory.empty();
331+
if (input != null && !input.isEmpty()) {
332+
String[] list = input.split(",");
333+
for (int i = list.length - 1; i >= 0; --i) {
334+
config = config.withFallback(parserFunc.apply(list[i]));
335+
}
336+
}
337+
338+
return config;
339+
}
340+
319341
public <T> T getProperty(String propName, T defaultValue) {
320342
if (!config.hasPath(propName)) return defaultValue;
321343
String string = config.getString(propName);

ethereumj-core/src/test/java/org/ethereum/config/SystemPropertiesTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,39 @@ public void testDump() {
518518
assertTrue(StringUtils.countOccurrencesOf(dump, "{") > 50);
519519
}
520520

521+
@Test
522+
public void testMergeConfigs1() {
523+
String firstConfig = "";
524+
SystemProperties props = new SystemProperties();
525+
Config config = props.mergeConfigs(firstConfig, ConfigFactory::parseString);
526+
assertFalse(config.hasPath("peer.listen.port"));
527+
}
528+
529+
@Test
530+
public void testMergeConfigs2() {
531+
String firstConfig = "peer.listen.port=30123";
532+
SystemProperties props = new SystemProperties();
533+
Config config = props.mergeConfigs(firstConfig, ConfigFactory::parseString);
534+
assertEquals(30123, config.getInt("peer.listen.port"));
535+
}
536+
537+
@Test
538+
public void testMergeConfigs3() {
539+
String firstConfig = "peer.listen.port=30123,peer.listen.port=30145";
540+
SystemProperties props = new SystemProperties();
541+
Config config = props.mergeConfigs(firstConfig, ConfigFactory::parseString);
542+
assertEquals(30145, config.getInt("peer.listen.port"));
543+
}
544+
545+
@Test
546+
public void testMergeConfigs4() {
547+
String firstConfig = "peer.listen.port=30123,sync.enabled=true";
548+
SystemProperties props = new SystemProperties();
549+
Config config = props.mergeConfigs(firstConfig, ConfigFactory::parseString);
550+
assertEquals(30123, config.getInt("peer.listen.port"));
551+
assertEquals(Boolean.TRUE, config.getBoolean("sync.enabled"));
552+
}
553+
521554
@SuppressWarnings("SameParameterValue")
522555
static class ActivePeer {
523556
boolean asEnodeUrl;

0 commit comments

Comments
 (0)