From 867112ce5ebc46f91e09ed4f9cd250ad33740e58 Mon Sep 17 00:00:00 2001 From: Oleksiy Lukin Date: Wed, 3 Mar 2021 12:59:39 +0200 Subject: [PATCH 1/9] legacy code removed --- .../apl/core/utils/LegacyDbUtil.java | 27 -------- .../aplwallet/apl/exec/Apollo.java | 66 +++++++++---------- .../apl/exec/CustomDirLocations.java | 57 ---------------- .../dirprovider/PredefinedDirLocations.java | 9 ++- .../dirprovider/DirProviderFactoryTest.java | 3 +- .../PredefinedDirLocationsTest.java | 3 +- 6 files changed, 44 insertions(+), 121 deletions(-) delete mode 100644 apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/utils/LegacyDbUtil.java delete mode 100644 apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/CustomDirLocations.java diff --git a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/utils/LegacyDbUtil.java b/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/utils/LegacyDbUtil.java deleted file mode 100644 index b412054d31..0000000000 --- a/apl-core/src/main/java/com/apollocurrency/aplwallet/apl/core/utils/LegacyDbUtil.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright © 2018-2021 Apollo Foundation - */ - -package com.apollocurrency.aplwallet.apl.core.utils; - -import com.apollocurrency.aplwallet.apl.util.env.RuntimeEnvironment; -import com.apollocurrency.aplwallet.apl.util.env.dirprovider.DirProvider; - -import java.nio.file.Path; -import java.nio.file.Paths; - -public class LegacyDbUtil { - public static Path getLegacyHomeDir() { - Path homeDirPath; - if (!RuntimeEnvironment.getInstance().isServiceMode()) { - if (RuntimeEnvironment.getInstance().isWindowsRuntime()) { - homeDirPath = Paths.get(System.getProperty("user.home"), "AppData", "Roaming", "APOLLO"); - } else { - homeDirPath = Paths.get(System.getProperty("user.home"), ".apollo"); - } - } else { - homeDirPath = DirProvider.getBinDir(); - } - return homeDirPath; - } -} diff --git a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java index cf290c8a5f..0f4de5258d 100644 --- a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java +++ b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java @@ -10,7 +10,6 @@ import com.apollocurrency.aplwallet.apl.core.chainid.BlockchainConfig; import com.apollocurrency.aplwallet.apl.core.chainid.BlockchainConfigUpdater; import com.apollocurrency.aplwallet.apl.core.db.DbConfig; -import com.apollocurrency.aplwallet.apl.core.utils.LegacyDbUtil; import com.apollocurrency.aplwallet.apl.core.service.appdata.SecureStorageService; import com.apollocurrency.aplwallet.apl.udpater.intfce.UpdaterCore; import com.apollocurrency.aplwallet.apl.updater.core.UpdaterCoreImpl; @@ -137,18 +136,34 @@ public static boolean saveStartParams(String[] argv, String pidPath, ConfigDirPr return res; } - public static PredefinedDirLocations merge(CmdLineArgs args, EnvironmentVariables vars, CustomDirLocations customDirLocations) { - return new PredefinedDirLocations( - customDirLocations.getDbDir().isEmpty() ? StringUtils.isBlank(args.dbDir) ? vars.dbDir : args.dbDir : customDirLocations.getDbDir().get(), - StringUtils.isBlank(args.logDir) ? vars.logDir : args.logDir, - customDirLocations.getKeystoreDir().isEmpty() ? StringUtils.isBlank(args.vaultKeystoreDir) ? vars.vaultKeystoreDir : args.vaultKeystoreDir : customDirLocations.getKeystoreDir().get(), - StringUtils.isBlank(args.pidFile) ? vars.pidFile : args.pidFile, - StringUtils.isBlank(args.twoFactorAuthDir) ? vars.twoFactorAuthDir : args.twoFactorAuthDir, - StringUtils.isBlank(args.dataExportDir) ? vars.dataExportDir : args.dataExportDir, - StringUtils.isBlank(args.dexKeystoreDir) ? vars.dexKeystoreDir : args.dexKeystoreDir - ); +// public static PredefinedDirLocations merge(CmdLineArgs args, EnvironmentVariables vars, CustomDirLocations customDirLocations) { +// return new PredefinedDirLocations( +// customDirLocations.getDbDir().isEmpty() ? StringUtils.isBlank(args.dbDir) ? vars.dbDir : args.dbDir : customDirLocations.getDbDir().get(), +// StringUtils.isBlank(args.logDir) ? vars.logDir : args.logDir, +// customDirLocations.getKeystoreDir().isEmpty() ? StringUtils.isBlank(args.vaultKeystoreDir) ? vars.vaultKeystoreDir : args.vaultKeystoreDir : customDirLocations.getKeystoreDir().get(), +// StringUtils.isBlank(args.pidFile) ? vars.pidFile : args.pidFile, +// StringUtils.isBlank(args.twoFactorAuthDir) ? vars.twoFactorAuthDir : args.twoFactorAuthDir, +// StringUtils.isBlank(args.dataExportDir) ? vars.dataExportDir : args.dataExportDir, +// StringUtils.isBlank(args.dexKeystoreDir) ? vars.dexKeystoreDir : args.dexKeystoreDir +// ); +// } +// + +/** + * Merge command line argumentsm environment variables and properties from config files + * into one set of properties. Precedence: command line, environment vars, configs. + * It means that command line can overwrite env vars and configs + * @param args parsed command line arguments + * @param vars parsed environment variables + * @param props parsed application config files + * @return properties, reqady to use in the application + */ + public static Properties merge(CmdLineArgs args, EnvironmentVariables vars, Properties props){ + //TODO: implement + return props; } + //TODO: check this piece of art public static void setSystemProperties(CmdLineArgs args){ System.setProperty("apl.runtime.mode", args.serviceMode ? "service" : "user"); System.setProperty("javax.net.ssl.trustStore", "cacerts"); @@ -156,17 +171,6 @@ public static void setSystemProperties(CmdLineArgs args){ System.setProperty("javax.net.ssl.trustStoreType", "JKS"); } - private static String getCustomDbPath(UUID chainId, Properties properties) { //maybe better to set dbUrl or add to dirProvider - String customDbDir = properties.getProperty(CustomDirLocations.DB_DIR_PROPERTY_NAME); - if (customDbDir != null) { - Path legacyHomeDir = LegacyDbUtil.getLegacyHomeDir(); - Path customDbPath = legacyHomeDir.resolve(customDbDir).resolve(chainId.toString().substring(0, 6)).normalize(); - System.out.println("Using custom db path " + customDbPath.toAbsolutePath().toString()); - return customDbPath.toAbsolutePath().toString(); - } - return null; - } - private void initUpdater(String attachmentFilePath, boolean debug, PropertiesHolder propertiesHolder) { if (!propertiesHolder.getBooleanProperty("apl.allowUpdates", false)) { return; @@ -296,17 +300,13 @@ public static void main(String[] argv) { if (args.noShardCreate != null) { applicationProperties.setProperty("apl.noshardcreate", "" + args.noShardCreate); } -//TODO: check this piece of art - CustomDirLocations customDirLocations = new CustomDirLocations( - getCustomDbPath(chainId, applicationProperties), - applicationProperties.getProperty(CustomDirLocations.KEYSTORE_DIR_PROPERTY_NAME) - ); - - DirProviderFactory.setup(args.serviceMode, - chainId, - Constants.APPLICATION_DIR_NAME, - merge(args, envVars, customDirLocations) - ); + + DirProviderFactory.setup( args.serviceMode, + chainId, + Constants.APPLICATION_DIR_NAME, + new PredefinedDirLocations(merge(args,envVars,applicationProperties)) + ); + dirProvider = DirProviderFactory.getProvider(); RuntimeEnvironment.getInstance().setDirProvider(dirProvider); diff --git a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/CustomDirLocations.java b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/CustomDirLocations.java deleted file mode 100644 index 715a4a4203..0000000000 --- a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/CustomDirLocations.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright © 2018-2019 Apollo Foundation - */ - -package com.apollocurrency.aplwallet.apl.exec; - -import java.util.Objects; -import java.util.Optional; -import java.util.Properties; - -public class CustomDirLocations { - public static final String DB_DIR_PROPERTY_NAME = "apl.customDbDir"; - public static final String KEYSTORE_DIR_PROPERTY_NAME = "apl.customVaultKeystoreDir"; - private String dbDir; - private String keystoreDir; - - public CustomDirLocations(String dbDir, String keystoreDir) { - this.dbDir = dbDir; - this.keystoreDir = keystoreDir; - } - - public CustomDirLocations(Properties properties) { - Objects.requireNonNull(properties, "Properties should not be null"); - this.dbDir = properties.getProperty(DB_DIR_PROPERTY_NAME); - this.keystoreDir = properties.getProperty(KEYSTORE_DIR_PROPERTY_NAME); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof CustomDirLocations)) return false; - CustomDirLocations that = (CustomDirLocations) o; - return Objects.equals(dbDir, that.dbDir) && - Objects.equals(keystoreDir, that.keystoreDir); - } - - @Override - public int hashCode() { - return Objects.hash(dbDir, keystoreDir); - } - - public Optional getDbDir() { - return Optional.ofNullable(dbDir); - } - - public void setDbDir(String dbDir) { - this.dbDir = dbDir; - } - - public Optional getKeystoreDir() { - return Optional.ofNullable(keystoreDir); - } - - public void setKeystoreDir(String keystoreDir) { - this.keystoreDir = keystoreDir; - } -} diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/PredefinedDirLocations.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/PredefinedDirLocations.java index cf5ae9bffb..b96fc37d39 100644 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/PredefinedDirLocations.java +++ b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/PredefinedDirLocations.java @@ -9,6 +9,7 @@ import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Properties; public class PredefinedDirLocations { @@ -20,9 +21,13 @@ public class PredefinedDirLocations { private Path twoFactorAuthDir; private Path dataExportDir; // path to keep exported CSV files - public PredefinedDirLocations() { - this(null, null, null, null, null, null, null); + public PredefinedDirLocations(Properties properties){ + } + +// public PredefinedDirLocations() { +// this(null, null, null, null, null, null, null); +// } public PredefinedDirLocations(String dbDir, String logsDir, String vaultKeystoreDir, String pidFilePath, String twoFactorAuthDir, String dataExportDir, String dexStorage) { diff --git a/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/DirProviderFactoryTest.java b/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/DirProviderFactoryTest.java index dcb24b0476..68e642cdc6 100644 --- a/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/DirProviderFactoryTest.java +++ b/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/DirProviderFactoryTest.java @@ -5,6 +5,7 @@ package com.apollocurrency.aplwallet.apl.util.env.dirprovider; import com.apollocurrency.aplwallet.apl.util.env.RuntimeEnvironment; +import java.util.Properties; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -42,7 +43,7 @@ void getInstance() { @Test void getInstance2() { - PredefinedDirLocations dirLocations = new PredefinedDirLocations(); + PredefinedDirLocations dirLocations = new PredefinedDirLocations(new Properties()); DirProviderFactory.setup(true, UUID.randomUUID(), "Default", dirLocations); DirProvider df = DirProviderFactory.getProvider(); assertNotNull(df.getAppBaseDir()); diff --git a/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/PredefinedDirLocationsTest.java b/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/PredefinedDirLocationsTest.java index 48fc396796..bfb00b02da 100644 --- a/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/PredefinedDirLocationsTest.java +++ b/apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/env/dirprovider/PredefinedDirLocationsTest.java @@ -4,6 +4,7 @@ package com.apollocurrency.aplwallet.apl.util.env.dirprovider; +import java.util.Properties; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -13,7 +14,7 @@ class PredefinedDirLocationsTest { @Test void createWithNulls() { - PredefinedDirLocations locations = new PredefinedDirLocations(); + PredefinedDirLocations locations = new PredefinedDirLocations(new Properties()); assertNull(locations.getDbDir()); assertNull(locations.getLogsDir()); assertNull(locations.getPidFilePath()); From 850a82e3a2bae1cd8637925a82c560298865c5ba Mon Sep 17 00:00:00 2001 From: Oleksiy Lukin Date: Thu, 4 Mar 2021 14:34:12 +0200 Subject: [PATCH 2/9] Properties, command line and env vars proper ordering: work in progress --- apl-conf/pom.xml | 10 ++ .../aplwallet/apl/conf/ConfPlaceholder.java | 7 +- .../aplwallet/apl/conf/KnownProperties.java | 130 ++++++++++++++++++ .../aplwallet/apl/conf/PropertyRecord.java | 23 ++++ .../aplwallet/apl/exec/Apollo.java | 11 +- .../aplwallet/apl/util/StringUtils.java | 17 +++ .../dirprovider/PredefinedDirLocations.java | 80 +++++------ 7 files changed, 230 insertions(+), 48 deletions(-) create mode 100644 apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/KnownProperties.java create mode 100644 apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/PropertyRecord.java diff --git a/apl-conf/pom.xml b/apl-conf/pom.xml index ff630b724a..87e9cf1c68 100644 --- a/apl-conf/pom.xml +++ b/apl-conf/pom.xml @@ -16,6 +16,16 @@ org.slf4j slf4j-api + + org.projectlombok + lombok + provided + + + com.apollocurrency + apl-utils + ${project.version} + org.junit.platform diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfPlaceholder.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfPlaceholder.java index 96099bb98a..3e7612ad49 100644 --- a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfPlaceholder.java +++ b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfPlaceholder.java @@ -1,3 +1,6 @@ +/* + * Copyright © 2018-2021 Apollo Foundation + */ package com.apollocurrency.aplwallet.apl.conf; /** @@ -5,5 +8,7 @@ * @author al */ public class ConfPlaceholder { - + public KnownProperties getKnownProperties(){ + return KnownProperties.create(); + } } diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/KnownProperties.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/KnownProperties.java new file mode 100644 index 0000000000..04bf4123ff --- /dev/null +++ b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/KnownProperties.java @@ -0,0 +1,130 @@ +/* + * Copyright © 2018-2021 Apollo Foundation + */ +package com.apollocurrency.aplwallet.apl.conf; + + +import com.apollocurrency.aplwallet.apl.util.Version; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** + * Config Properies known by Apollo application + * @author Oleksiy Lukin alukin@gmail.com + */ +@Slf4j +public class KnownProperties { + private final static String FIRST_RELEASE = "1.0.0"; + private final static String DEX_RELEASE = "1.35.0"; + private final static String SHARDING_RELEASE = "1.36.0"; + private final static String MARIADB_RELEASE = "1.36.0"; + + private KnownProperties() { + } + + /** + * propery nanme mapoped to parameters + */ + @Getter + private Map knownProps; + + public boolean isSupported(String propName){ + PropertyRecord rec = knownProps.get(propName); + return rec!=null; + } + + public PropertyRecord get(String propName){ + return knownProps.get(propName); + } + + private void put(String name, PropertyRecord pr){ + pr.name = name; + knownProps.put(name, pr); + } + + public List listDeprecated(Version currVersion){ + List res = new ArrayList<>(); + knownProps.values().stream().filter(pr -> (pr.deprecatedSince.lessThan(currVersion))).forEachOrdered(pr -> { + res.add(pr); + }); + return res; + } + + public List listNewAfter(Version ver){ + List res = new ArrayList<>(); + knownProps.values().stream().filter(pr -> (pr.sinceRelease.greaterThan(ver))).forEachOrdered(pr -> { + res.add(pr); + }); + return res; + } + + public void dumpToPropertiesFile(Path pathToDump){ + //TODO: implement + } + + public static KnownProperties create(){ + KnownProperties kp = new KnownProperties(); + + kp.put("apl.shareMyAddress", + PropertyRecord.builder() + .defaultValue("true") + .description("Announce my IP address/hostname to peers and allow them to share it with other peers. If disabled, peer networking servlet will not be started at all.") + .sinceRelease(new Version(FIRST_RELEASE)) + .build() + ); + + //TODO: hardcode all known properties with ddescription from properies in resources + kp.put("apl.customDbDir", + PropertyRecord.builder() + .defaultValue("") + .description("Directory where database is located. Default location is $HOME/.apl-blockchain/apl-blockchain-db. Could be overrided by env vars and cmd args") + .sinceRelease(new Version(MARIADB_RELEASE)) + .build() + ); + + kp.put("apl.customVaultKeystoreDir", + PropertyRecord.builder() + .defaultValue("") + .description("Absolute path to custom keystore dir. Could be overrided by env vars and cmd args") + .sinceRelease(new Version(DEX_RELEASE)) + .build() + ); + + kp.put("apl.customPidFile", + PropertyRecord.builder() + .defaultValue("") + .description("Absolute path to PID file. Could be overrided by env vars and cmd args") + .sinceRelease(new Version(MARIADB_RELEASE)) + .build() + ); + + kp.put("apl.dir2FA", + PropertyRecord.builder() + .defaultValue("") + .description("Absolute path to 2FAdata dir. Could be overrided by env vars and cmd args") + .sinceRelease(new Version(DEX_RELEASE)) + .build() + ); + + kp.put("apl.customDataExportDir", + PropertyRecord.builder() + .defaultValue("") + .description("Absolute path to custom data export dir (shard files and other data). Could be overrided by env vars and cmd args") + .sinceRelease(new Version(SHARDING_RELEASE)) + .build() + ); + + kp.put("apl.customDexStorageDir", + PropertyRecord.builder() + .defaultValue("") + .description("Absolute path to custom DEX storage. Could be overrided by env vars and cmd args") + .sinceRelease(new Version(DEX_RELEASE)) + .build() + ); + return kp; + } +} diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/PropertyRecord.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/PropertyRecord.java new file mode 100644 index 0000000000..a0f6ed2613 --- /dev/null +++ b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/PropertyRecord.java @@ -0,0 +1,23 @@ +/* + * Copyright © 2018-2021 Apollo Foundation + */ +package com.apollocurrency.aplwallet.apl.conf; + +import com.apollocurrency.aplwallet.apl.util.Version; +import lombok.Builder; +import lombok.Builder.Default; + +/** + * + * @author Oleksiy Lukin alukin@gmail.com + */ +@Builder +public class PropertyRecord { + public String name; + public String defaultValue; + public String description; + public Version sinceRelease; + public Version deprecatedSince; + @Default + public boolean isRequired = false; +} diff --git a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java index efede9ca5d..d58a029909 100644 --- a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java +++ b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java @@ -157,9 +157,16 @@ public static boolean saveStartParams(String[] argv, String pidPath, ConfigDirPr * @param vars parsed environment variables * @param props parsed application config files * @return properties, reqady to use in the application - */ + */ public static Properties merge(CmdLineArgs args, EnvironmentVariables vars, Properties props){ - //TODO: implement + + String logDir = StringUtils.byPrecednce(args.logDir, vars.logDir, (String)props.get("apl.customLogDir")); + props.setProperty("apl.customLogDir",logDir); + + String dbDir = StringUtils.byPrecednce(args.dbDir, vars.dbDir, (String)props.get("apl.customDbDir")); + props.setProperty("apl.customDbDir", dbDir); + //TPDO: all command line params + return props; } diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/StringUtils.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/StringUtils.java index c7f7e40f9b..d0802f6ccc 100644 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/StringUtils.java +++ b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/StringUtils.java @@ -34,4 +34,21 @@ public static boolean equalsIgnoreCase(String str, List l) { } return false; } + + /** + * Takes first not-empty value and ignores the rest of values + * @param values strings or nulls + * @return first not-empty value + */ + public static String byPrecednce(String ...values){ + String res =""; + String[] va = values; + for (int i = 0; i Date: Fri, 5 Mar 2021 12:53:28 +0200 Subject: [PATCH 3/9] Properties, command line and env vars proper ordering implemented --- .../aplwallet/apl/conf/ConfPlaceholder.java | 14 ---- ...{PropertyRecord.java => ConfigRecord.java} | 12 ++- ...ownProperties.java => ConfigVerifier.java} | 74 +++++++++++++------ .../aplwallet/apl/exec/Apollo.java | 65 ++++++++-------- 4 files changed, 95 insertions(+), 70 deletions(-) delete mode 100644 apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfPlaceholder.java rename apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/{PropertyRecord.java => ConfigRecord.java} (64%) rename apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/{KnownProperties.java => ConfigVerifier.java} (65%) diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfPlaceholder.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfPlaceholder.java deleted file mode 100644 index 3e7612ad49..0000000000 --- a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfPlaceholder.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright © 2018-2021 Apollo Foundation - */ -package com.apollocurrency.aplwallet.apl.conf; - -/** - * - * @author al - */ -public class ConfPlaceholder { - public KnownProperties getKnownProperties(){ - return KnownProperties.create(); - } -} diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/PropertyRecord.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigRecord.java similarity index 64% rename from apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/PropertyRecord.java rename to apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigRecord.java index a0f6ed2613..d5f82b2e29 100644 --- a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/PropertyRecord.java +++ b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigRecord.java @@ -12,12 +12,18 @@ * @author Oleksiy Lukin alukin@gmail.com */ @Builder -public class PropertyRecord { +public class ConfigRecord { public String name; - public String defaultValue; + @Default + public String defaultValue=""; public String description; - public Version sinceRelease; + @Default + public Version sinceRelease = new Version("1.0.0"); public Version deprecatedSince; @Default + public String cmdLineOpt=""; + @Default + public String envVar=""; + @Default public boolean isRequired = false; } diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/KnownProperties.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java similarity index 65% rename from apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/KnownProperties.java rename to apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java index 04bf4123ff..71638cb3ae 100644 --- a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/KnownProperties.java +++ b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java @@ -5,10 +5,12 @@ import com.apollocurrency.aplwallet.apl.util.Version; +import java.io.OutputStream; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Properties; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -17,69 +19,99 @@ * @author Oleksiy Lukin alukin@gmail.com */ @Slf4j -public class KnownProperties { +public class ConfigVerifier { private final static String FIRST_RELEASE = "1.0.0"; private final static String DEX_RELEASE = "1.35.0"; private final static String SHARDING_RELEASE = "1.36.0"; private final static String MARIADB_RELEASE = "1.36.0"; - private KnownProperties() { + private ConfigVerifier() { } /** * propery nanme mapoped to parameters */ @Getter - private Map knownProps; + private Map knownProps; public boolean isSupported(String propName){ - PropertyRecord rec = knownProps.get(propName); + ConfigRecord rec = knownProps.get(propName); return rec!=null; } - public PropertyRecord get(String propName){ + public ConfigRecord get(String propName){ return knownProps.get(propName); } - private void put(String name, PropertyRecord pr){ + private void put(String name, ConfigRecord pr){ pr.name = name; knownProps.put(name, pr); } - public List listDeprecated(Version currVersion){ - List res = new ArrayList<>(); + public List listDeprecated(Version currVersion){ + List res = new ArrayList<>(); knownProps.values().stream().filter(pr -> (pr.deprecatedSince.lessThan(currVersion))).forEachOrdered(pr -> { res.add(pr); }); return res; } - public List listNewAfter(Version ver){ - List res = new ArrayList<>(); + public List listNewAfter(Version ver){ + List res = new ArrayList<>(); knownProps.values().stream().filter(pr -> (pr.sinceRelease.greaterThan(ver))).forEachOrdered(pr -> { res.add(pr); }); return res; } - public void dumpToPropertiesFile(Path pathToDump){ + /** + * Dumps all known properties with comment lines + * containing all available information about config propery + * @param pos output stream where to dump + */ + public void dumpToProperties(OutputStream pos){ //TODO: implement } - public static KnownProperties create(){ - KnownProperties kp = new KnownProperties(); + +/** + * Parse properties file comparing to known properties and fillimng undefined with defaults + * @param config Properties file from resource or disk. + * Unknown proerties will be logged with WARN level; missing required properties will + * be filled with default and warning will be logged + * @return reaqdy to use properties + */ + public Properties parse(Properties config){ + //go trough suppied config and check it: warn on deprecated and on unknown + for(Object propery: config.entrySet()){ + + } + //define required properties, warn on undefined + for(ConfigRecord pr: knownProps.values()){ + + } + return config; + } +/** + * All known properties must be inited in this method; + * @return created properties fully inited with default values + */ + public static ConfigVerifier create(){ + ConfigVerifier kp = new ConfigVerifier(); kp.put("apl.shareMyAddress", - PropertyRecord.builder() + ConfigRecord.builder() .defaultValue("true") .description("Announce my IP address/hostname to peers and allow them to share it with other peers. If disabled, peer networking servlet will not be started at all.") .sinceRelease(new Version(FIRST_RELEASE)) .build() ); - //TODO: hardcode all known properties with ddescription from properies in resources + //TODO: hardcode all known properties with ddescription from properies in resources + + // kp.put("apl.customDbDir", - PropertyRecord.builder() + ConfigRecord.builder() .defaultValue("") .description("Directory where database is located. Default location is $HOME/.apl-blockchain/apl-blockchain-db. Could be overrided by env vars and cmd args") .sinceRelease(new Version(MARIADB_RELEASE)) @@ -87,7 +119,7 @@ public static KnownProperties create(){ ); kp.put("apl.customVaultKeystoreDir", - PropertyRecord.builder() + ConfigRecord.builder() .defaultValue("") .description("Absolute path to custom keystore dir. Could be overrided by env vars and cmd args") .sinceRelease(new Version(DEX_RELEASE)) @@ -95,7 +127,7 @@ public static KnownProperties create(){ ); kp.put("apl.customPidFile", - PropertyRecord.builder() + ConfigRecord.builder() .defaultValue("") .description("Absolute path to PID file. Could be overrided by env vars and cmd args") .sinceRelease(new Version(MARIADB_RELEASE)) @@ -103,7 +135,7 @@ public static KnownProperties create(){ ); kp.put("apl.dir2FA", - PropertyRecord.builder() + ConfigRecord.builder() .defaultValue("") .description("Absolute path to 2FAdata dir. Could be overrided by env vars and cmd args") .sinceRelease(new Version(DEX_RELEASE)) @@ -111,7 +143,7 @@ public static KnownProperties create(){ ); kp.put("apl.customDataExportDir", - PropertyRecord.builder() + ConfigRecord.builder() .defaultValue("") .description("Absolute path to custom data export dir (shard files and other data). Could be overrided by env vars and cmd args") .sinceRelease(new Version(SHARDING_RELEASE)) @@ -119,7 +151,7 @@ public static KnownProperties create(){ ); kp.put("apl.customDexStorageDir", - PropertyRecord.builder() + ConfigRecord.builder() .defaultValue("") .description("Absolute path to custom DEX storage. Could be overrided by env vars and cmd args") .sinceRelease(new Version(DEX_RELEASE)) diff --git a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java index d58a029909..2f9ec4e221 100644 --- a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java +++ b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java @@ -5,7 +5,7 @@ import ch.qos.logback.classic.Level; import ch.qos.logback.classic.LoggerContext; -import com.apollocurrency.aplwallet.apl.conf.ConfPlaceholder; +import com.apollocurrency.aplwallet.apl.conf.ConfigVerifier; import com.apollocurrency.aplwallet.apl.core.app.AplCoreRuntime; import com.apollocurrency.aplwallet.apl.core.chainid.BlockchainConfig; import com.apollocurrency.aplwallet.apl.core.chainid.BlockchainConfigUpdater; @@ -83,7 +83,9 @@ public class Apollo { private static Logger log; private static AplContainer container; private static AplCoreRuntime aplCoreRuntime; - + + private static final ConfigVerifier configVerifier = ConfigVerifier.create(); + private static void setLogLevel(int logLevel) { // let's SET LEVEL EXPLOCITLY only when it was passed via command line params String packageName = "com.apollocurrency.aplwallet.apl"; @@ -136,19 +138,6 @@ public static boolean saveStartParams(String[] argv, String pidPath, ConfigDirPr return res; } -// public static PredefinedDirLocations merge(CmdLineArgs args, EnvironmentVariables vars, CustomDirLocations customDirLocations) { -// return new PredefinedDirLocations( -// customDirLocations.getDbDir().isEmpty() ? StringUtils.isBlank(args.dbDir) ? vars.dbDir : args.dbDir : customDirLocations.getDbDir().get(), -// StringUtils.isBlank(args.logDir) ? vars.logDir : args.logDir, -// customDirLocations.getKeystoreDir().isEmpty() ? StringUtils.isBlank(args.vaultKeystoreDir) ? vars.vaultKeystoreDir : args.vaultKeystoreDir : customDirLocations.getKeystoreDir().get(), -// StringUtils.isBlank(args.pidFile) ? vars.pidFile : args.pidFile, -// StringUtils.isBlank(args.twoFactorAuthDir) ? vars.twoFactorAuthDir : args.twoFactorAuthDir, -// StringUtils.isBlank(args.dataExportDir) ? vars.dataExportDir : args.dataExportDir, -// StringUtils.isBlank(args.dexKeystoreDir) ? vars.dexKeystoreDir : args.dexKeystoreDir -// ); -// } -// - /** * Merge command line argumentsm environment variables and properties from config files * into one set of properties. Precedence: command line, environment vars, configs. @@ -160,13 +149,33 @@ public static boolean saveStartParams(String[] argv, String pidPath, ConfigDirPr */ public static Properties merge(CmdLineArgs args, EnvironmentVariables vars, Properties props){ - String logDir = StringUtils.byPrecednce(args.logDir, vars.logDir, (String)props.get("apl.customLogDir")); + //{"--log-dir", "-l"} + String logDir = StringUtils.byPrecednce(args.logDir, vars.logDir, props.getProperty("apl.customLogDir")); props.setProperty("apl.customLogDir",logDir); - - String dbDir = StringUtils.byPrecednce(args.dbDir, vars.dbDir, (String)props.get("apl.customDbDir")); + //{"--db-dir"} + String dbDir = StringUtils.byPrecednce(args.dbDir, vars.dbDir, props.getProperty("apl.customDbDir")); props.setProperty("apl.customDbDir", dbDir); - //TPDO: all command line params - + // {"--vault-key-dir"} + String vaultKeystoreDir = StringUtils.byPrecednce(args.vaultKeystoreDir, vars.vaultKeystoreDir, props.getProperty("apl.customVaultKeystoreDir")); + props.setProperty("apl.customVaultKeystoreDir", vaultKeystoreDir); + // {"--dex-key-dir"} + String dexKeystoreDir = StringUtils.byPrecednce(args.dexKeystoreDir, vars.dexKeystoreDir, props.getProperty("apl.customDexStorageDir")); + props.setProperty("apl.customDexStorageDir", dexKeystoreDir); + // {"--no-shard-import"} + String noShardImport = StringUtils.byPrecednce(args.noShardImport.toString(), props.getProperty("apl.noshardimport")); + props.setProperty("apl.noshardimport",noShardImport); + // {"--no-shard-create"} + String noShardCreate = StringUtils.byPrecednce(args.noShardCreate.toString(), props.getProperty("apl.noshardcreate")); + props.setProperty("apl.noshardcreate",noShardCreate); + // {"--2fa-dir"} + String twoFactorAuthDir = StringUtils.byPrecednce(args.twoFactorAuthDir,vars.twoFactorAuthDir, props.getProperty("apl.dir2FA")); + props.setProperty("apl.dir2FA",twoFactorAuthDir); + // {"--dexp-dir"} + String dataExportDir = StringUtils.byPrecednce(args.dataExportDir, vars.dataExportDir, props.getProperty("apl.customDataExportDir")); + props.setProperty("apl.customDataExportDir",dataExportDir); + // {"--pid-file"} + String pidFile = StringUtils.byPrecednce(args.pidFile, vars.pidFile, props.getProperty("apl.customPidFile")); + props.getProperty("apl.customPidFile", pidFile); return props; } @@ -254,8 +263,6 @@ public static void main(String[] argv) { RuntimeEnvironment.getInstance().setMain(Apollo.class); //set some important system properties setSystemProperties(args); -//cheat classloader to get access to "conf" package resources - ConfPlaceholder ph = new ConfPlaceholder(); //--------------- config locading section ------------------------------------- @@ -288,7 +295,10 @@ public static void main(String[] argv) { // load everuthing into applicationProperies. This is the place where all configuration // is collected from configs, command line and environment variables Properties applicationProperties = propertiesLoader.load(); - + +//verify and complete configuration + applicationProperties = configVerifier.parse(applicationProperties); + ChainsConfigLoader chainsConfigLoader = new ChainsConfigLoader( configDirProvider, configDir, @@ -298,15 +308,6 @@ public static void main(String[] argv) { // init chains configurations by loading chains.json file Map chains = chainsConfigLoader.load(); UUID chainId = ChainUtils.getActiveChain(chains).getChainId(); - -//over-write config options from command line if set - - if (args.noShardImport != null) { - applicationProperties.setProperty("apl.noshardimport", "" + args.noShardImport); - } - if (args.noShardCreate != null) { - applicationProperties.setProperty("apl.noshardcreate", "" + args.noShardCreate); - } DirProviderFactory.setup( args.serviceMode, chainId, From 65a20da3dabc71156cbc6a2843e6ee76bacabb6d Mon Sep 17 00:00:00 2001 From: Oleksiy Lukin Date: Tue, 23 Mar 2021 18:06:50 +0200 Subject: [PATCH 4/9] Properties deprecation and other checks implemented --- .../aplwallet/apl/conf/ConfigVerifier.java | 32 +++++++++++++++---- .../aplwallet/apl/exec/Apollo.java | 2 +- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java index 71638cb3ae..f5dff915fd 100644 --- a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java +++ b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java @@ -5,8 +5,10 @@ import com.apollocurrency.aplwallet.apl.util.Version; +import java.io.IOException; import java.io.OutputStream; -import java.nio.file.Path; +import java.io.OutputStreamWriter; +import java.io.Writer; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -69,8 +71,13 @@ public List listNewAfter(Version ver){ * containing all available information about config propery * @param pos output stream where to dump */ - public void dumpToProperties(OutputStream pos){ - //TODO: implement + public void dumpToProperties(OutputStream pos) throws IOException{ + Writer w = new OutputStreamWriter(pos); + for(ConfigRecord cr: knownProps.values()){ + w.write("# "+cr.description); + w.write("# Command line option: "+cr.cmdLineOpt+" Environment variable: "+cr.envVar); + w.write(cr.name+"="+cr.defaultValue); + } } @@ -79,16 +86,29 @@ public void dumpToProperties(OutputStream pos){ * @param config Properties file from resource or disk. * Unknown proerties will be logged with WARN level; missing required properties will * be filled with default and warning will be logged + * @param currentVer * @return reaqdy to use properties */ - public Properties parse(Properties config){ + public Properties parse(Properties config, Version currentVer){ //go trough suppied config and check it: warn on deprecated and on unknown - for(Object propery: config.entrySet()){ + for(Object key: config.keySet()){ + String name = (String)key; + String value = config.getProperty(name); + ConfigRecord cr = knownProps.get(name); + if(cr==null){ + log.warn("Unknown config property: "+name+" with value: "+value + ". It propbably will be ignored"); + }else if (cr.deprecatedSince.lessThan(currentVer)){ + log.warn("Config property: "+name+" is deprecated since version "+cr.deprecatedSince); + } } //define required properties, warn on undefined for(ConfigRecord pr: knownProps.values()){ - + String val = config.getProperty(pr.name); + if(pr.isRequired && (val==null || val.isEmpty())){ + config.put(pr.name, pr.defaultValue); + log.warn("Required property: "+pr.name+" is not defined in config. Putting default value: "+pr.defaultValue); + } } return config; } diff --git a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java index 2f9ec4e221..094b065739 100644 --- a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java +++ b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java @@ -297,7 +297,7 @@ public static void main(String[] argv) { Properties applicationProperties = propertiesLoader.load(); //verify and complete configuration - applicationProperties = configVerifier.parse(applicationProperties); + applicationProperties = configVerifier.parse(applicationProperties, Constants.VERSION); ChainsConfigLoader chainsConfigLoader = new ChainsConfigLoader( configDirProvider, From 814831ca309059824d50452ec5c95de1638a76db Mon Sep 17 00:00:00 2001 From: Oleksiy Lukin Date: Wed, 24 Mar 2021 10:12:45 +0200 Subject: [PATCH 5/9] default config parser implemented --- .../aplwallet/apl/conf/ConfigRecord.java | 6 +- .../aplwallet/apl/conf/ConfigVerifier.java | 97 +++++++------------ .../aplwallet/apl/conf/DefaultConfig.java | 61 ++++++++++++ .../aplwallet/apl/exec/Apollo.java | 19 +++- 4 files changed, 114 insertions(+), 69 deletions(-) create mode 100644 apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/DefaultConfig.java diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigRecord.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigRecord.java index d5f82b2e29..fe182b199c 100644 --- a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigRecord.java +++ b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigRecord.java @@ -16,10 +16,12 @@ public class ConfigRecord { public String name; @Default public String defaultValue=""; - public String description; + @Default + public String description=""; @Default public Version sinceRelease = new Version("1.0.0"); - public Version deprecatedSince; + @Default + public Version deprecatedSince = new Version("999.0.0"); @Default public String cmdLineOpt=""; @Default diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java index f5dff915fd..23adf66866 100644 --- a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java +++ b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java @@ -6,6 +6,7 @@ import com.apollocurrency.aplwallet.apl.util.Version; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; @@ -42,12 +43,19 @@ public boolean isSupported(String propName){ } public ConfigRecord get(String propName){ - return knownProps.get(propName); + ConfigRecord res = knownProps.get(propName); + return res; } - - private void put(String name, ConfigRecord pr){ - pr.name = name; - knownProps.put(name, pr); + + private ConfigRecord getOrAdd(String propName){ + ConfigRecord res = knownProps.get(propName); + if(res==null){ + res = ConfigRecord.builder() + .name(propName) + .build(); + knownProps.put(propName,res); + } + return res; } public List listDeprecated(Version currVersion){ @@ -97,7 +105,7 @@ public Properties parse(Properties config, Version currentVer){ ConfigRecord cr = knownProps.get(name); if(cr==null){ log.warn("Unknown config property: "+name+" with value: "+value + ". It propbably will be ignored"); - }else if (cr.deprecatedSince.lessThan(currentVer)){ + }else if (currentVer.greaterThan(cr.deprecatedSince)){ log.warn("Config property: "+name+" is deprecated since version "+cr.deprecatedSince); } @@ -112,71 +120,36 @@ public Properties parse(Properties config, Version currentVer){ } return config; } + /** - * All known properties must be inited in this method; + * All known properties must be inited in this method; All known properties are defined + * in resource file conf/apl-blockchain.properties or in files in corresponding testnet config + * directories.TODO: keywords for deprecation, command line options and env variables + * @param respurcePath path to properties file in resources * @return created properties fully inited with default values */ - public static ConfigVerifier create(){ + public static ConfigVerifier create( String respurcePath ) throws IOException { ConfigVerifier kp = new ConfigVerifier(); + DefaultConfig dc=null; + if(respurcePath==null || respurcePath.isEmpty()){ + respurcePath="conf/apl-blockchain.properties"; + } + ClassLoader classloader = Thread.currentThread().getContextClassLoader(); - kp.put("apl.shareMyAddress", - ConfigRecord.builder() - .defaultValue("true") - .description("Announce my IP address/hostname to peers and allow them to share it with other peers. If disabled, peer networking servlet will not be started at all.") - .sinceRelease(new Version(FIRST_RELEASE)) - .build() - ); + try (InputStream is = classloader.getResourceAsStream(respurcePath)) { + dc = DefaultConfig.fromStream(is); + } - //TODO: hardcode all known properties with ddescription from properies in resources + kp.knownProps = dc.getKnownProperties(); + + //TODO: hardcode command line and env if so - // - kp.put("apl.customDbDir", - ConfigRecord.builder() - .defaultValue("") - .description("Directory where database is located. Default location is $HOME/.apl-blockchain/apl-blockchain-db. Could be overrided by env vars and cmd args") - .sinceRelease(new Version(MARIADB_RELEASE)) - .build() - ); - - kp.put("apl.customVaultKeystoreDir", - ConfigRecord.builder() - .defaultValue("") - .description("Absolute path to custom keystore dir. Could be overrided by env vars and cmd args") - .sinceRelease(new Version(DEX_RELEASE)) - .build() - ); + kp.getOrAdd("apl.customDbDir").sinceRelease = new Version(MARIADB_RELEASE); - kp.put("apl.customPidFile", - ConfigRecord.builder() - .defaultValue("") - .description("Absolute path to PID file. Could be overrided by env vars and cmd args") - .sinceRelease(new Version(MARIADB_RELEASE)) - .build() - ); + kp.getOrAdd("apl.customVaultKeystoreDir").sinceRelease = (new Version(DEX_RELEASE)); - kp.put("apl.dir2FA", - ConfigRecord.builder() - .defaultValue("") - .description("Absolute path to 2FAdata dir. Could be overrided by env vars and cmd args") - .sinceRelease(new Version(DEX_RELEASE)) - .build() - ); - - kp.put("apl.customDataExportDir", - ConfigRecord.builder() - .defaultValue("") - .description("Absolute path to custom data export dir (shard files and other data). Could be overrided by env vars and cmd args") - .sinceRelease(new Version(SHARDING_RELEASE)) - .build() - ); - - kp.put("apl.customDexStorageDir", - ConfigRecord.builder() - .defaultValue("") - .description("Absolute path to custom DEX storage. Could be overrided by env vars and cmd args") - .sinceRelease(new Version(DEX_RELEASE)) - .build() - ); + kp.getOrAdd("apl.customPidFile").sinceRelease = new Version(MARIADB_RELEASE); + return kp; } } diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/DefaultConfig.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/DefaultConfig.java new file mode 100644 index 0000000000..1fd3f65cdc --- /dev/null +++ b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/DefaultConfig.java @@ -0,0 +1,61 @@ +/* + * Copyright © 2018-2021 Apollo Foundation + */ +package com.apollocurrency.aplwallet.apl.conf; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.Getter; + +/** + * + * @author Oleksiy Lukin alukin@gmail.com + */ +public class DefaultConfig { + @Getter + final Map knownProperties = new HashMap<>(); + + public static DefaultConfig fromStream(InputStream is) throws IOException { + DefaultConfig conf = new DefaultConfig(); + List commentBuf = new ArrayList<>(); + try ( BufferedReader br = new BufferedReader(new InputStreamReader(is))) { + String line; + while ((line = br.readLine()) != null) { + line=line.trim(); + if(line.startsWith("#")){ + commentBuf.add(line.substring(1)); + }else if (line.isBlank()){ + commentBuf.clear(); +//TODO: define key words for deprecation and introduction version +//TODO: define key words for command line options and environment variables + }else{ + String[] parts = line.split("="); + String key=parts[0]; + String value=""; + if(parts.length > 1){ + value = parts[1]; + } + int idx = value.indexOf("#"); + if(idx>=0){ + value=value.substring(idx); + } + String comment = commentBuf.stream().collect(Collectors.joining(" ")); + ConfigRecord cr = ConfigRecord.builder() + .description(comment) + .name(key) + .defaultValue(value) + .build(); + conf.knownProperties.put(key, cr); + } + } + } + return conf; + } +} diff --git a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java index 094b065739..1bab8aca21 100644 --- a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java +++ b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java @@ -41,6 +41,7 @@ import javax.enterprise.inject.spi.CDI; import java.io.File; import java.io.FileNotFoundException; +import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Path; import java.nio.file.Paths; @@ -84,7 +85,7 @@ public class Apollo { private static AplContainer container; private static AplCoreRuntime aplCoreRuntime; - private static final ConfigVerifier configVerifier = ConfigVerifier.create(); + private static ConfigVerifier configVerifier; private static void setLogLevel(int logLevel) { // let's SET LEVEL EXPLOCITLY only when it was passed via command line params @@ -162,10 +163,12 @@ public static Properties merge(CmdLineArgs args, EnvironmentVariables vars, Prop String dexKeystoreDir = StringUtils.byPrecednce(args.dexKeystoreDir, vars.dexKeystoreDir, props.getProperty("apl.customDexStorageDir")); props.setProperty("apl.customDexStorageDir", dexKeystoreDir); // {"--no-shard-import"} - String noShardImport = StringUtils.byPrecednce(args.noShardImport.toString(), props.getProperty("apl.noshardimport")); + String nsi = args.noShardImport==null ? "": args.noShardImport.toString(); + String noShardImport = StringUtils.byPrecednce(nsi, props.getProperty("apl.noshardimport")); props.setProperty("apl.noshardimport",noShardImport); // {"--no-shard-create"} - String noShardCreate = StringUtils.byPrecednce(args.noShardCreate.toString(), props.getProperty("apl.noshardcreate")); + String nsc = args.noShardCreate == null ? "": args.noShardCreate.toString(); + String noShardCreate = StringUtils.byPrecednce(nsc, props.getProperty("apl.noshardcreate")); props.setProperty("apl.noshardcreate",noShardCreate); // {"--2fa-dir"} String twoFactorAuthDir = StringUtils.byPrecednce(args.twoFactorAuthDir,vars.twoFactorAuthDir, props.getProperty("apl.dir2FA")); @@ -296,8 +299,14 @@ public static void main(String[] argv) { // is collected from configs, command line and environment variables Properties applicationProperties = propertiesLoader.load(); -//verify and complete configuration - applicationProperties = configVerifier.parse(applicationProperties, Constants.VERSION); + try { + //verify and complete configuration + configVerifier = ConfigVerifier.create(configDirProvider.getConfigName()+"/apl-blockchain.properties"); + applicationProperties = configVerifier.parse(applicationProperties, Constants.VERSION); + } catch (IOException ex) { + System.err.println("WARNING! Can not verify config because can not read/parse default config fropm resources!"); + } + ChainsConfigLoader chainsConfigLoader = new ChainsConfigLoader( configDirProvider, From 23d7d84913fc48d8dff4aa855f1c376ec2b3c67c Mon Sep 17 00:00:00 2001 From: Oleksiy Lukin Date: Wed, 24 Mar 2021 12:52:55 +0200 Subject: [PATCH 6/9] versions, command lilne and env vars comments parser implemented --- .../aplwallet/apl/conf/ConfigVerifier.java | 6 +- .../aplwallet/apl/conf/DefaultConfig.java | 80 ++++++++++++++----- .../resources/conf/apl-blockchain.properties | 9 ++- 3 files changed, 71 insertions(+), 24 deletions(-) diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java index 23adf66866..7c7d6feea9 100644 --- a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java +++ b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java @@ -24,9 +24,9 @@ @Slf4j public class ConfigVerifier { private final static String FIRST_RELEASE = "1.0.0"; - private final static String DEX_RELEASE = "1.35.0"; - private final static String SHARDING_RELEASE = "1.36.0"; - private final static String MARIADB_RELEASE = "1.36.0"; + private final static String DEX_RELEASE = "1.36.0"; + private final static String SHARDING_RELEASE = "1.35.0"; + private final static String MARIADB_RELEASE = "1.48.0"; private ConfigVerifier() { } diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/DefaultConfig.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/DefaultConfig.java index 1fd3f65cdc..2f06006f1a 100644 --- a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/DefaultConfig.java +++ b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/DefaultConfig.java @@ -3,6 +3,7 @@ */ package com.apollocurrency.aplwallet.apl.conf; +import com.apollocurrency.aplwallet.apl.util.Version; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -13,45 +14,86 @@ import java.util.Map; import java.util.stream.Collectors; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; /** - * + * Parser of default config from resources. + * Default config must contain all properties known to the program with default values, + * descritption and keywords signaling corresponding command line options and + * environment variuables. Keywords are prefixed * @author Oleksiy Lukin alukin@gmail.com */ +@Slf4j public class DefaultConfig { + + public static final String KW_DEPRECATED = "DEPRECATED"; + public static final String KW_SINCE = "SINCE"; + public static final String KW_COMMAND_LINE = "CMDLINE"; + public static final String KW_ENV_VAR = "ENVVAR"; + @Getter final Map knownProperties = new HashMap<>(); + static ConfigRecord createCr(String key, String value, List comments) { + String comment = comments.stream().collect(Collectors.joining(" ")); + ConfigRecord cr = ConfigRecord.builder() + .name(key) + .defaultValue(value) + .description(comment) + .build(); + for (String line : comments) { + if (line.startsWith("!")) { + int end = line.indexOf(" ")>3 ? line.indexOf(" "): line.length()-1; + String cmd = line.substring(1,end).trim(); + String val = line.substring(end).trim(); + int val_end = val.indexOf(" ")>0 ? val.indexOf(" "): val.length(); + val = val.substring(0,val_end); + switch(cmd){ + case KW_DEPRECATED: + cr.deprecatedSince = new Version(val); + break; + case KW_SINCE: + cr.sinceRelease = new Version(val); + break; + case KW_COMMAND_LINE: + cr.cmdLineOpt=val; + break; + case KW_ENV_VAR: + cr.envVar = val; + break; + default: + log.warn("Unknown keyword in the propery comments. Propery: {} Keyword: {}",key,cmd); + } + } + } + + return cr; + } + public static DefaultConfig fromStream(InputStream is) throws IOException { DefaultConfig conf = new DefaultConfig(); List commentBuf = new ArrayList<>(); try ( BufferedReader br = new BufferedReader(new InputStreamReader(is))) { String line; while ((line = br.readLine()) != null) { - line=line.trim(); - if(line.startsWith("#")){ + line = line.trim(); + if (line.startsWith("#")) { commentBuf.add(line.substring(1)); - }else if (line.isBlank()){ + } else if (line.isBlank()) { commentBuf.clear(); -//TODO: define key words for deprecation and introduction version -//TODO: define key words for command line options and environment variables - }else{ + } else { String[] parts = line.split("="); - String key=parts[0]; - String value=""; - if(parts.length > 1){ - value = parts[1]; + String key = parts[0]; + String value = ""; + if (parts.length > 1) { + value = parts[1]; } int idx = value.indexOf("#"); - if(idx>=0){ - value=value.substring(idx); + if (idx >= 0) { + value = value.substring(idx); } - String comment = commentBuf.stream().collect(Collectors.joining(" ")); - ConfigRecord cr = ConfigRecord.builder() - .description(comment) - .name(key) - .defaultValue(value) - .build(); + + ConfigRecord cr = createCr(key, value, commentBuf); conf.knownProperties.put(key, cr); } } diff --git a/apl-conf/src/main/resources/conf/apl-blockchain.properties b/apl-conf/src/main/resources/conf/apl-blockchain.properties index 51b30b13a4..57311af2f7 100644 --- a/apl-conf/src/main/resources/conf/apl-blockchain.properties +++ b/apl-conf/src/main/resources/conf/apl-blockchain.properties @@ -23,10 +23,10 @@ # Set the socks proxy host. #socksProxyHost=localhost - +socksProxyHost= # Set the socks proxy port. #socksProxyPort=9050 - +socksProxyPort= #### PEER NETWORKING #### @@ -66,6 +66,7 @@ apl.myAddress= apl.myPlatform= # My hallmark, if available. +#!DEPRECATED 1.25.1 apl.myHallmark= # Maximum number of inbound connections. @@ -424,9 +425,13 @@ apl.batchCommitSize=100 apl.sharding.backupDb=false # if true, app will not import last shard, instead will start from genesis block +#!SINCE 1.35.0 +#!CMDLINE --no-shard-import apl.noshardimport=false # if true, app will not divide database for shards, will store large database files instead +#!SINCE 1.35.0 +#!CMDLINE --no-shard-import apl.noshardcreate=false # Minimal delay (in seconds) after reached shard height to wait before starting sharding process. From adc3784e33337ec9cca93576e7ab06f6f1f151e0 Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Wed, 10 May 2023 20:39:45 +0300 Subject: [PATCH 7/9] minor pom.xml rollback --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f7c670a136..96070ea8d1 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ dev none - + slow @@ -95,7 +95,7 @@ package - + slow From 7f6f0bd520da4bdbfd0d36e0e40cc47615e0b386 Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Thu, 11 May 2023 18:13:27 +0300 Subject: [PATCH 8/9] added unit tests for new classes --- .../aplwallet/apl/conf/ConfigVerifier.java | 105 +++++++++-------- .../aplwallet/apl/conf/DefaultConfig.java | 19 +-- .../apl/conf/ConfigVerifierTest.java | 110 ++++++++++++++++++ apl-conf/src/test/resources/logback-test.xml | 64 ++++++++++ .../src/test/resources/test-env.properties | 6 + .../aplwallet/apl/exec/Apollo.java | 4 +- 6 files changed, 246 insertions(+), 62 deletions(-) create mode 100644 apl-conf/src/test/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifierTest.java create mode 100644 apl-conf/src/test/resources/logback-test.xml create mode 100644 apl-conf/src/test/resources/test-env.properties diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java index 7c7d6feea9..b9db476c44 100644 --- a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java +++ b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifier.java @@ -30,34 +30,33 @@ public class ConfigVerifier { private ConfigVerifier() { } - + /** - * propery nanme mapoped to parameters + * property name mapped to parameters */ @Getter private Map knownProps; - - public boolean isSupported(String propName){ - ConfigRecord rec = knownProps.get(propName); - return rec!=null; - } - + + public boolean isSupported(String propName) { + return knownProps.containsKey(propName); + } + public ConfigRecord get(String propName){ ConfigRecord res = knownProps.get(propName); return res; } private ConfigRecord getOrAdd(String propName){ - ConfigRecord res = knownProps.get(propName); - if(res==null){ + ConfigRecord res = knownProps.get(propName); + if (res == null) { res = ConfigRecord.builder() - .name(propName) - .build(); - knownProps.put(propName,res); + .name(propName) + .build(); + knownProps.put(propName, res); } return res; } - + public List listDeprecated(Version currVersion){ List res = new ArrayList<>(); knownProps.values().stream().filter(pr -> (pr.deprecatedSince.lessThan(currVersion))).forEachOrdered(pr -> { @@ -65,7 +64,7 @@ public List listDeprecated(Version currVersion){ }); return res; } - + public List listNewAfter(Version ver){ List res = new ArrayList<>(); knownProps.values().stream().filter(pr -> (pr.sinceRelease.greaterThan(ver))).forEachOrdered(pr -> { @@ -73,82 +72,82 @@ public List listNewAfter(Version ver){ }); return res; } - + /** * Dumps all known properties with comment lines - * containing all available information about config propery + * containing all available information about config property * @param pos output stream where to dump - */ + */ public void dumpToProperties(OutputStream pos) throws IOException{ Writer w = new OutputStreamWriter(pos); for(ConfigRecord cr: knownProps.values()){ w.write("# "+cr.description); w.write("# Command line option: "+cr.cmdLineOpt+" Environment variable: "+cr.envVar); - w.write(cr.name+"="+cr.defaultValue); + w.write(cr.name+"="+cr.defaultValue); } } - + /** - * Parse properties file comparing to known properties and fillimng undefined with defaults + * Parse properties file comparing to known properties and filling undefined with defaults * @param config Properties file from resource or disk. - * Unknown proerties will be logged with WARN level; missing required properties will + * Unknown properties will be logged with WARN level; missing required properties will * be filled with default and warning will be logged - * @param currentVer - * @return reaqdy to use properties + * @param currentVersion + * @return ready to use properties */ - public Properties parse(Properties config, Version currentVer){ - //go trough suppied config and check it: warn on deprecated and on unknown + public Properties parse(Properties config, Version currentVersion){ + //go through supplied config and check it, warn on deprecated and on unknown for(Object key: config.keySet()){ String name = (String)key; String value = config.getProperty(name); ConfigRecord cr = knownProps.get(name); - if(cr==null){ - log.warn("Unknown config property: "+name+" with value: "+value + ". It propbably will be ignored"); - }else if (currentVer.greaterThan(cr.deprecatedSince)){ - log.warn("Config property: "+name+" is deprecated since version "+cr.deprecatedSince); + if (cr == null) { + log.warn("Unknown config property: '{}' with value: '{}'. It probably will be ignored", name, value); + } else if (currentVersion.greaterThan(cr.deprecatedSince)) { + log.warn("Config property: '{}' is deprecated since version '{}'", name, cr.deprecatedSince); } - + } //define required properties, warn on undefined for(ConfigRecord pr: knownProps.values()){ String val = config.getProperty(pr.name); - if(pr.isRequired && (val==null || val.isEmpty())){ + if (pr.isRequired && (val == null || val.isEmpty())) { config.put(pr.name, pr.defaultValue); - log.warn("Required property: "+pr.name+" is not defined in config. Putting default value: "+pr.defaultValue); + log.warn("Required property: '{}' is not defined in config. Putting default value: '{}'", pr.name, pr.defaultValue); } } return config; } -/** - * All known properties must be inited in this method; All known properties are defined - * in resource file conf/apl-blockchain.properties or in files in corresponding testnet config - * directories.TODO: keywords for deprecation, command line options and env variables - * @param respurcePath path to properties file in resources - * @return created properties fully inited with default values - */ - public static ConfigVerifier create( String respurcePath ) throws IOException { + /** + * All known properties must be initiated in this method; All known properties are defined + * in resource file conf/apl-blockchain.properties or in files in corresponding testnet config + * directories.TODO: keywords for deprecation, command line options and env variables + * @param resourcePath path to properties file in resources + * @return created properties fully initiated with default values + */ + public static ConfigVerifier create( String resourcePath ) throws IOException { ConfigVerifier kp = new ConfigVerifier(); - DefaultConfig dc=null; - if(respurcePath==null || respurcePath.isEmpty()){ - respurcePath="conf/apl-blockchain.properties"; + DefaultConfig dc = null; + if (resourcePath == null || resourcePath.isEmpty()) { + resourcePath="conf/apl-blockchain.properties"; } ClassLoader classloader = Thread.currentThread().getContextClassLoader(); - - try (InputStream is = classloader.getResourceAsStream(respurcePath)) { + log.debug("Trying to load resource by path = '{}' ...", resourcePath); + try (InputStream is = classloader.getResourceAsStream(resourcePath)) { dc = DefaultConfig.fromStream(is); } - + kp.knownProps = dc.getKnownProperties(); //TODO: hardcode command line and env if so - - kp.getOrAdd("apl.customDbDir").sinceRelease = new Version(MARIADB_RELEASE); - - kp.getOrAdd("apl.customVaultKeystoreDir").sinceRelease = (new Version(DEX_RELEASE)); - - kp.getOrAdd("apl.customPidFile").sinceRelease = new Version(MARIADB_RELEASE); + + kp.getOrAdd("apl.customDbDir").sinceRelease = new Version(MARIADB_RELEASE); + + kp.getOrAdd("apl.customVaultKeystoreDir").sinceRelease = (new Version(DEX_RELEASE)); + + kp.getOrAdd("apl.customPidFile").sinceRelease = new Version(MARIADB_RELEASE); return kp; } diff --git a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/DefaultConfig.java b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/DefaultConfig.java index 2f06006f1a..aa83dcc9be 100644 --- a/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/DefaultConfig.java +++ b/apl-conf/src/main/java/com/apollocurrency/aplwallet/apl/conf/DefaultConfig.java @@ -12,6 +12,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -19,22 +20,25 @@ /** * Parser of default config from resources. * Default config must contain all properties known to the program with default values, - * descritption and keywords signaling corresponding command line options and - * environment variuables. Keywords are prefixed + * description and keywords signaling corresponding command line options and + * environment variables. Keywords are prefixed * @author Oleksiy Lukin alukin@gmail.com */ @Slf4j public class DefaultConfig { - + public static final String KW_DEPRECATED = "DEPRECATED"; public static final String KW_SINCE = "SINCE"; public static final String KW_COMMAND_LINE = "CMDLINE"; public static final String KW_ENV_VAR = "ENVVAR"; - + @Getter final Map knownProperties = new HashMap<>(); static ConfigRecord createCr(String key, String value, List comments) { + Objects.requireNonNull(key, "key is NULL"); + Objects.requireNonNull(value, "value is NULL"); + Objects.requireNonNull(comments, "comments list is NULL"); String comment = comments.stream().collect(Collectors.joining(" ")); ConfigRecord cr = ConfigRecord.builder() .name(key) @@ -48,7 +52,7 @@ static ConfigRecord createCr(String key, String value, List comments) { String val = line.substring(end).trim(); int val_end = val.indexOf(" ")>0 ? val.indexOf(" "): val.length(); val = val.substring(0,val_end); - switch(cmd){ + switch(cmd) { case KW_DEPRECATED: cr.deprecatedSince = new Version(val); break; @@ -62,15 +66,16 @@ static ConfigRecord createCr(String key, String value, List comments) { cr.envVar = val; break; default: - log.warn("Unknown keyword in the propery comments. Propery: {} Keyword: {}",key,cmd); + log.warn("Unknown keyword in the property comments. Property: {} Keyword: {}", key, cmd); } } } - + return cr; } public static DefaultConfig fromStream(InputStream is) throws IOException { + Objects.requireNonNull(is, "Input Stream is NULL"); DefaultConfig conf = new DefaultConfig(); List commentBuf = new ArrayList<>(); try ( BufferedReader br = new BufferedReader(new InputStreamReader(is))) { diff --git a/apl-conf/src/test/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifierTest.java b/apl-conf/src/test/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifierTest.java new file mode 100644 index 0000000000..a7c757b4a5 --- /dev/null +++ b/apl-conf/src/test/java/com/apollocurrency/aplwallet/apl/conf/ConfigVerifierTest.java @@ -0,0 +1,110 @@ +package com.apollocurrency.aplwallet.apl.conf; + +import com.apollocurrency.aplwallet.apl.util.Constants; +import com.apollocurrency.aplwallet.apl.util.Version; +import com.apollocurrency.aplwallet.apl.util.env.config.PropertiesConfigLoader; +import lombok.SneakyThrows; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; +import java.util.Properties; + +import static org.junit.jupiter.api.Assertions.*; + +class ConfigVerifierTest { + +// ConfigVerifier configVerifier; + + @AfterEach + void tearDown() { +// ConfigVerifier configVerifier = null; + } + + @SneakyThrows + @Test + void test_createEmpty() { + ConfigVerifier configVerifier = ConfigVerifier.create(null); + assertNotNull(configVerifier); + assertEquals(162, configVerifier.getKnownProps().size()); + } + + @SneakyThrows + @Test + void test_createNyKnownPath() { + ConfigVerifier configVerifier = ConfigVerifier.create("conf-tn2/apl-blockchain.properties"); + assertNotNull(configVerifier); + assertEquals(162, configVerifier.getKnownProps().size()); + } + + @SneakyThrows + @Test + void test_parse() { + ConfigVerifier configVerifier = ConfigVerifier.create("conf-tn2/apl-blockchain.properties"); + assertNotNull(configVerifier); + assertEquals(162, configVerifier.getKnownProps().size()); + + PropertiesConfigLoader propertiesLoader = new PropertiesConfigLoader( + null, + false, + null, + Constants.APPLICATION_DIR_NAME + ".properties", + Collections.emptyList()); + Properties applicationProperties = propertiesLoader.load(); + Properties properties = configVerifier.parse(applicationProperties, new Version(1, 25, 1)); + assertEquals(159, properties.size()); + } + + @SneakyThrows + @Test + void dumpToProperties() { + ConfigVerifier configVerifier = ConfigVerifier.create("conf-tn2/apl-blockchain.properties"); + assertNotNull(configVerifier); + assertEquals(162, configVerifier.getKnownProps().size()); + configVerifier.dumpToProperties(System.out); + } + + @SneakyThrows + @Test + void test_isSupported() { + ConfigVerifier configVerifier = ConfigVerifier.create("conf-tn1/apl-blockchain.properties"); + assertNotNull(configVerifier); + assertEquals(163, configVerifier.getKnownProps().size()); + assertTrue(configVerifier.isSupported("apl.myHallmark")); + } + + @SneakyThrows + @Test + void test_get() { + ConfigVerifier configVerifier = ConfigVerifier.create("conf-tn1/apl-blockchain.properties"); + assertNotNull(configVerifier); + assertEquals(163, configVerifier.getKnownProps().size()); + assertNotNull(configVerifier.get("apl.myHallmark")); + assertNull(configVerifier.get("apl.unknownPropertyName")); + } + + @SneakyThrows + @Test + void test_listDeprecated() { + ConfigVerifier configVerifier = ConfigVerifier.create("conf/apl-blockchain.properties"); + assertNotNull(configVerifier); + assertEquals(162, configVerifier.getKnownProps().size()); + List list = configVerifier.listDeprecated(new Version(1, 25, 3)); + assertNotNull(list); + assertEquals(1, list.size()); + assertEquals(new Version(1, 25, 1), list.get(0).deprecatedSince); + } + + @SneakyThrows + @Test + void test_listNewAfter() { + ConfigVerifier configVerifier = ConfigVerifier.create("conf/apl-blockchain.properties"); + assertNotNull(configVerifier); + assertEquals(162, configVerifier.getKnownProps().size()); + List list = configVerifier.listNewAfter(new Version(1, 35, 1)); + assertNotNull(list); + assertEquals(3, list.size()); + assertEquals(new Version(1, 48, 0), list.get(0).sinceRelease); + } +} \ No newline at end of file diff --git a/apl-conf/src/test/resources/logback-test.xml b/apl-conf/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..fed564207f --- /dev/null +++ b/apl-conf/src/test/resources/logback-test.xml @@ -0,0 +1,64 @@ + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M\(%line\) - %msg%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apl-conf/src/test/resources/test-env.properties b/apl-conf/src/test/resources/test-env.properties new file mode 100644 index 0000000000..157a989aa1 --- /dev/null +++ b/apl-conf/src/test/resources/test-env.properties @@ -0,0 +1,6 @@ +# +# Copyright (c) 2018-2021. Apollo Foundation. +# +#comment out next property to increase the verbose level +apl-test.env=quiet +#apl-test.env=verbose diff --git a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java index 86bec3234d..fb0755ef32 100644 --- a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java +++ b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java @@ -133,7 +133,7 @@ public static boolean saveStartParams(String[] argv, String pidPath, ConfigDirPr } /** - * Merge command line argumentsm environment variables and properties from config files + * Merge command line arguments environment variables and properties from config files * into one set of properties. Precedence: command line, environment vars, configs. * It means that command line can overwrite env vars and configs * @param args parsed command line arguments @@ -265,7 +265,7 @@ public static void main(String[] argv) { configVerifier = ConfigVerifier.create(configDirProvider.getConfigName()+"/apl-blockchain.properties"); applicationProperties = configVerifier.parse(applicationProperties, Constants.VERSION); } catch (IOException ex) { - System.err.println("WARNING! Can not verify config because can not read/parse default config fropm resources!"); + System.err.println("WARNING! Can not verify config because can not read/parse default config from resources!"); } From 3d7de4744c2153aababa9117b4d9dc4365cb67ea Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Fri, 12 May 2023 12:57:55 +0300 Subject: [PATCH 9/9] added unit tests --- .../aplwallet/apl/exec/Apollo.java | 20 +++++++------- .../aplwallet/apl/util/StringUtils.java | 4 +-- .../aplwallet/apl/util/StringUtilsTest.java | 26 +++++++++++++++++++ 3 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 apl-utils/src/test/java/com/apollocurrency/aplwallet/apl/util/StringUtilsTest.java diff --git a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java index fb0755ef32..d534cac448 100644 --- a/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java +++ b/apl-exec/src/main/java/com/apollocurrency/aplwallet/apl/exec/Apollo.java @@ -144,33 +144,33 @@ public static boolean saveStartParams(String[] argv, String pidPath, ConfigDirPr public static Properties merge(CmdLineArgs args, EnvironmentVariables vars, Properties props){ //{"--log-dir", "-l"} - String logDir = StringUtils.byPrecednce(args.logDir, vars.logDir, props.getProperty("apl.customLogDir")); + String logDir = StringUtils.byPrecedence(args.logDir, vars.logDir, props.getProperty("apl.customLogDir")); props.setProperty("apl.customLogDir",logDir); //{"--db-dir"} - String dbDir = StringUtils.byPrecednce(args.dbDir, vars.dbDir, props.getProperty("apl.customDbDir")); + String dbDir = StringUtils.byPrecedence(args.dbDir, vars.dbDir, props.getProperty("apl.customDbDir")); props.setProperty("apl.customDbDir", dbDir); // {"--vault-key-dir"} - String vaultKeystoreDir = StringUtils.byPrecednce(args.vaultKeystoreDir, vars.vaultKeystoreDir, props.getProperty("apl.customVaultKeystoreDir")); + String vaultKeystoreDir = StringUtils.byPrecedence(args.vaultKeystoreDir, vars.vaultKeystoreDir, props.getProperty("apl.customVaultKeystoreDir")); props.setProperty("apl.customVaultKeystoreDir", vaultKeystoreDir); // {"--dex-key-dir"} - String dexKeystoreDir = StringUtils.byPrecednce(args.dexKeystoreDir, vars.dexKeystoreDir, props.getProperty("apl.customDexStorageDir")); + String dexKeystoreDir = StringUtils.byPrecedence(args.dexKeystoreDir, vars.dexKeystoreDir, props.getProperty("apl.customDexStorageDir")); props.setProperty("apl.customDexStorageDir", dexKeystoreDir); // {"--no-shard-import"} String nsi = args.noShardImport ? "": String.valueOf(args.noShardImport); - String noShardImport = StringUtils.byPrecednce(nsi, props.getProperty("apl.noshardimport")); + String noShardImport = StringUtils.byPrecedence(nsi, props.getProperty("apl.noshardimport")); props.setProperty("apl.noshardimport",noShardImport); // {"--no-shard-create"} String nsc = args.noShardCreate ? "": String.valueOf(args.noShardCreate); - String noShardCreate = StringUtils.byPrecednce(nsc, props.getProperty("apl.noshardcreate")); + String noShardCreate = StringUtils.byPrecedence(nsc, props.getProperty("apl.noshardcreate")); props.setProperty("apl.noshardcreate",noShardCreate); // {"--2fa-dir"} - String twoFactorAuthDir = StringUtils.byPrecednce(args.twoFactorAuthDir,vars.twoFactorAuthDir, props.getProperty("apl.dir2FA")); + String twoFactorAuthDir = StringUtils.byPrecedence(args.twoFactorAuthDir,vars.twoFactorAuthDir, props.getProperty("apl.dir2FA")); props.setProperty("apl.dir2FA",twoFactorAuthDir); // {"--dexp-dir"} - String dataExportDir = StringUtils.byPrecednce(args.dataExportDir, vars.dataExportDir, props.getProperty("apl.customDataExportDir")); + String dataExportDir = StringUtils.byPrecedence(args.dataExportDir, vars.dataExportDir, props.getProperty("apl.customDataExportDir")); props.setProperty("apl.customDataExportDir",dataExportDir); // {"--pid-file"} - String pidFile = StringUtils.byPrecednce(args.pidFile, vars.pidFile, props.getProperty("apl.customPidFile")); + String pidFile = StringUtils.byPrecedence(args.pidFile, vars.pidFile, props.getProperty("apl.customPidFile")); props.getProperty("apl.customPidFile", pidFile); return props; } @@ -262,7 +262,7 @@ public static void main(String[] argv) { try { //verify and complete configuration - configVerifier = ConfigVerifier.create(configDirProvider.getConfigName()+"/apl-blockchain.properties"); + configVerifier = ConfigVerifier.create(configDirProvider.getConfigName() + File.separator + "apl-blockchain.properties"); applicationProperties = configVerifier.parse(applicationProperties, Constants.VERSION); } catch (IOException ex) { System.err.println("WARNING! Can not verify config because can not read/parse default config from resources!"); diff --git a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/StringUtils.java b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/StringUtils.java index 2426805a60..9ff59d4323 100644 --- a/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/StringUtils.java +++ b/apl-utils/src/main/java/com/apollocurrency/aplwallet/apl/util/StringUtils.java @@ -32,13 +32,13 @@ public static boolean equalsIgnoreCase(String str, List l) { } return false; } - + /** * Takes first not-empty value and ignores the rest of values * @param values strings or nulls * @return first not-empty value */ - public static String byPrecednce(String ...values){ + public static String byPrecedence(String ...values){ String res =""; String[] va = values; for (int i = 0; i