diff --git a/robozonky-api/src/main/java/com/github/triceo/robozonky/internal/api/Defaults.java b/robozonky-api/src/main/java/com/github/triceo/robozonky/internal/api/Defaults.java index ab0809e14..290888906 100644 --- a/robozonky-api/src/main/java/com/github/triceo/robozonky/internal/api/Defaults.java +++ b/robozonky-api/src/main/java/com/github/triceo/robozonky/internal/api/Defaults.java @@ -28,7 +28,7 @@ import org.slf4j.LoggerFactory; /** - * Carries default values for some basic application properties, such as charset or locale. + * Carries application constants (such as version) and desired environmental settings (such as charset or locale). */ public final class Defaults { @@ -60,46 +60,4 @@ public static String getHostAddress() { } } - private static int getPropertyValue(final String propertyName, final int defaultValue) { - final String value = System.getProperty(propertyName, String.valueOf(defaultValue)); - try { - return Integer.parseInt(value); - } catch (final NumberFormatException ex) { - return defaultValue; - } - } - - private static boolean getPropertyValue(final String propertyName, final boolean defaultValue) { - final String value = System.getProperty(propertyName, String.valueOf(defaultValue)); - try { - return Boolean.parseBoolean(value); - } catch (final NumberFormatException ex) { - return defaultValue; - } - } - - /** - * When set to true, this is essentially a controlled memory leak. Generally only useful for testing. - * @return - */ - public static boolean isDebugEventStorageEnabled() { - return Defaults.getPropertyValue("robozonky.debug.enable_event_storage", false); - } - - public static int getTokenRefreshBeforeExpirationInSeconds() { - return Defaults.getPropertyValue("robozonky.default.token_refresh_seconds", 60); - } - - public static int getRemoteResourceRefreshIntervalInMinutes() { - return Defaults.getPropertyValue("robozonky.default.resource_refresh_minutes", 5); - } - - public static int getCaptchaDelayInSeconds() { - return Defaults.getPropertyValue("robozonky.default.captcha_protection_seconds", 120); - } - - public static int getDefaultDryRunBalance() { - return Defaults.getPropertyValue("robozonky.default.dry_run_balance", -1); - } - } diff --git a/robozonky-api/src/main/java/com/github/triceo/robozonky/internal/api/Settings.java b/robozonky-api/src/main/java/com/github/triceo/robozonky/internal/api/Settings.java new file mode 100644 index 000000000..8aa4f51b9 --- /dev/null +++ b/robozonky-api/src/main/java/com/github/triceo/robozonky/internal/api/Settings.java @@ -0,0 +1,110 @@ +/* + * Copyright 2017 Lukáš Petrovický + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.triceo.robozonky.internal.api; + +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.nio.file.Files; +import java.util.Properties; +import java.util.function.Function; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * These are RoboZonky settings read from a property file at system startup. The location of this file will be looked + * up in a property {@link #FILE_LOCATION_PROPERTY}. Defaults for all settings looked up through this class come from + * {@link System#getProperties()}. + */ +public enum Settings { + + INSTANCE; // cheap thread-safe singleton + + public static final String FILE_LOCATION_PROPERTY = "robozonky.properties.file"; + private final Logger LOGGER = LoggerFactory.getLogger(Settings.class); + + private Properties getProperties() { + final String filename = System.getProperty(Settings.FILE_LOCATION_PROPERTY); + if (filename == null) { + return new Properties(); + } + final File f = new File(filename); + if (!f.exists()) { + throw new IllegalStateException("Properties file does not exist: " + f.getAbsolutePath()); + } + try (final Reader r = Files.newBufferedReader(f.toPath(), Defaults.CHARSET)) { + final Properties p = new Properties(); + p.load(r); + LOGGER.debug("Loaded from '{}'.", f.getAbsolutePath()); + return p; + } catch (final IOException ex) { + throw new IllegalStateException("Cannot read properties.", ex); + } + } + + private final Properties properties = this.getProperties(); + + public T get(final String key, final Function adapter) { + final String val = properties.containsKey(key) ? properties.getProperty(key) : System.getProperty(key); + return adapter.apply(val); + } + + public String get(final String key, final String defaultValue) { + return get(key, value -> value == null ? defaultValue : value); + } + + public int get(final String key, final int defaultValue) { + return get(key, value -> { + try { + return Integer.parseInt(value); + } catch (final NumberFormatException ex) { + return defaultValue; + } + }); + } + + public boolean get(final String key) { + return get(key, Boolean::parseBoolean); + } + + /** + * When set to true, this is essentially a controlled memory leak. Generally only useful for testing. + * @return + */ + public boolean isDebugEventStorageEnabled() { + return get("robozonky.debug.enable_event_storage"); + } + + public int getTokenRefreshBeforeExpirationInSeconds() { + return get("robozonky.default.token_refresh_seconds", 60); + } + + public int getRemoteResourceRefreshIntervalInMinutes() { + return get("robozonky.default.resource_refresh_minutes", 5); + } + + public int getCaptchaDelayInSeconds() { + return get("robozonky.default.captcha_protection_seconds", 120); + } + + public int getDefaultDryRunBalance() { + return get("robozonky.default.dry_run_balance", -1); + } + + +} diff --git a/robozonky-api/src/test/java/com/github/triceo/robozonky/internal/api/DefaultsTest.java b/robozonky-api/src/test/java/com/github/triceo/robozonky/internal/api/DefaultsTest.java index a7491d280..6f1c7c3d7 100644 --- a/robozonky-api/src/test/java/com/github/triceo/robozonky/internal/api/DefaultsTest.java +++ b/robozonky-api/src/test/java/com/github/triceo/robozonky/internal/api/DefaultsTest.java @@ -17,27 +17,10 @@ package com.github.triceo.robozonky.internal.api; import org.assertj.core.api.Assertions; -import org.assertj.core.api.SoftAssertions; -import org.junit.Rule; import org.junit.Test; -import org.junit.contrib.java.lang.system.RestoreSystemProperties; public class DefaultsTest { - @Rule - public final RestoreSystemProperties propertiesRestorer = new RestoreSystemProperties(); - - @Test - public void properties() { - SoftAssertions.assertSoftly(softly -> { - softly.assertThat(Defaults.isDebugEventStorageEnabled()).isFalse(); - softly.assertThat(Defaults.getTokenRefreshBeforeExpirationInSeconds()).isEqualTo(60); - softly.assertThat(Defaults.getRemoteResourceRefreshIntervalInMinutes()).isEqualTo(5); - softly.assertThat(Defaults.getCaptchaDelayInSeconds()).isEqualTo(120); - softly.assertThat(Defaults.getDefaultDryRunBalance()).isEqualTo(-1); - }); - } - @Test public void hostAddress() { Assertions.assertThat(Defaults.getHostAddress()).isNotEmpty(); diff --git a/robozonky-api/src/test/java/com/github/triceo/robozonky/internal/api/SettingsTest.java b/robozonky-api/src/test/java/com/github/triceo/robozonky/internal/api/SettingsTest.java new file mode 100644 index 000000000..a30bcde61 --- /dev/null +++ b/robozonky-api/src/test/java/com/github/triceo/robozonky/internal/api/SettingsTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Lukáš Petrovický + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.triceo.robozonky.internal.api; + +import java.util.UUID; + +import org.assertj.core.api.SoftAssertions; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.RestoreSystemProperties; + +/** + * Created by lpetrovi on 14.4.17. + */ +public class SettingsTest { + + @Rule + public final RestoreSystemProperties propertiesRestorer = new RestoreSystemProperties(); + + @Test + public void properties() { + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(Settings.INSTANCE.get("user.dir", "")).isNotEqualTo(""); + softly.assertThat(Settings.INSTANCE.get(UUID.randomUUID().toString(), "")) + .isEqualTo(""); + softly.assertThat(Settings.INSTANCE.isDebugEventStorageEnabled()).isFalse(); + softly.assertThat(Settings.INSTANCE.getTokenRefreshBeforeExpirationInSeconds()).isEqualTo(60); + softly.assertThat(Settings.INSTANCE.getRemoteResourceRefreshIntervalInMinutes()).isEqualTo(5); + softly.assertThat(Settings.INSTANCE.getCaptchaDelayInSeconds()).isEqualTo(120); + softly.assertThat(Settings.INSTANCE.getDefaultDryRunBalance()).isEqualTo(-1); + }); + } + + +} diff --git a/robozonky-app/src/main/java/com/github/triceo/robozonky/app/Events.java b/robozonky-app/src/main/java/com/github/triceo/robozonky/app/Events.java index 362f45ffc..013d2c755 100644 --- a/robozonky-app/src/main/java/com/github/triceo/robozonky/app/Events.java +++ b/robozonky-app/src/main/java/com/github/triceo/robozonky/app/Events.java @@ -31,7 +31,7 @@ import com.github.triceo.robozonky.api.notifications.EventListener; import com.github.triceo.robozonky.api.notifications.ListenerService; import com.github.triceo.robozonky.common.extensions.ListenerServiceLoader; -import com.github.triceo.robozonky.internal.api.Defaults; +import com.github.triceo.robozonky.internal.api.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -116,13 +116,13 @@ public static void fire(final E event) { Events.INSTANCE.getListeners(eventClass).parallel() .flatMap(r -> r.getLatest().map(Stream::of).orElse(Stream.empty())) .forEach(l -> Events.fire(event, l)); - if (Defaults.isDebugEventStorageEnabled()) { + if (Settings.INSTANCE.isDebugEventStorageEnabled()) { Events.EVENTS_FIRED.add(event); } } /** - * This only exists for testing purposes. Also see {@link Defaults#isDebugEventStorageEnabled()}. + * This only exists for testing purposes. Also see {@link Settings#isDebugEventStorageEnabled()}. * * @return Events that were stored, if any. Returns the storage directly, any mutation operations will mutate the * storage. diff --git a/robozonky-app/src/main/java/com/github/triceo/robozonky/app/configuration/AuthenticationCommandLineFragment.java b/robozonky-app/src/main/java/com/github/triceo/robozonky/app/configuration/AuthenticationCommandLineFragment.java index 28afb6337..ffd693f06 100644 --- a/robozonky-app/src/main/java/com/github/triceo/robozonky/app/configuration/AuthenticationCommandLineFragment.java +++ b/robozonky-app/src/main/java/com/github/triceo/robozonky/app/configuration/AuthenticationCommandLineFragment.java @@ -25,7 +25,7 @@ import com.beust.jcommander.ParameterException; import com.github.triceo.robozonky.app.authentication.AuthenticationHandler; import com.github.triceo.robozonky.common.secrets.SecretProvider; -import com.github.triceo.robozonky.internal.api.Defaults; +import com.github.triceo.robozonky.internal.api.Settings; class AuthenticationCommandLineFragment extends AbstractCommandLineFragment { @@ -74,7 +74,8 @@ public Optional getKeystore() { public AuthenticationHandler createAuthenticationHandler(final SecretProvider secrets) { if (refreshTokenEnabled) { - final TemporalAmount duration = Duration.ofSeconds(Defaults.getTokenRefreshBeforeExpirationInSeconds()); + final TemporalAmount duration = + Duration.ofSeconds(Settings.INSTANCE.getTokenRefreshBeforeExpirationInSeconds()); return AuthenticationHandler.tokenBased(secrets, duration); } else { return AuthenticationHandler.passwordBased(secrets); diff --git a/robozonky-app/src/main/java/com/github/triceo/robozonky/app/investing/ResultTracker.java b/robozonky-app/src/main/java/com/github/triceo/robozonky/app/investing/ResultTracker.java index 8b993d47c..ce38eba38 100644 --- a/robozonky-app/src/main/java/com/github/triceo/robozonky/app/investing/ResultTracker.java +++ b/robozonky-app/src/main/java/com/github/triceo/robozonky/app/investing/ResultTracker.java @@ -27,13 +27,15 @@ import com.github.triceo.robozonky.api.remote.entities.Loan; import com.github.triceo.robozonky.api.strategies.LoanDescriptor; import com.github.triceo.robozonky.internal.api.Defaults; +import com.github.triceo.robozonky.internal.api.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; class ResultTracker { private static final Logger LOGGER = LoggerFactory.getLogger(ResultTracker.class); - static final TemporalAmount CAPTCHA_DELAY = Duration.ofSeconds(Defaults.getCaptchaDelayInSeconds()); + static final TemporalAmount CAPTCHA_DELAY = + Duration.ofSeconds(Settings.INSTANCE.getCaptchaDelayInSeconds()); /** * We are using volatile so that the write operation is guaranteed to be atomic. diff --git a/robozonky-app/src/main/java/com/github/triceo/robozonky/app/investing/Session.java b/robozonky-app/src/main/java/com/github/triceo/robozonky/app/investing/Session.java index 99ca5771b..41e2d0cca 100644 --- a/robozonky-app/src/main/java/com/github/triceo/robozonky/app/investing/Session.java +++ b/robozonky-app/src/main/java/com/github/triceo/robozonky/app/investing/Session.java @@ -49,6 +49,7 @@ import com.github.triceo.robozonky.api.strategies.Recommendation; import com.github.triceo.robozonky.app.Events; import com.github.triceo.robozonky.internal.api.Defaults; +import com.github.triceo.robozonky.internal.api.Settings; import com.github.triceo.robozonky.internal.api.Retriever; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -88,7 +89,7 @@ public synchronized static Session create(final ZonkyProxy api, final Collection } static BigDecimal getAvailableBalance(final ZonkyProxy api) { - final int balance = Defaults.getDefaultDryRunBalance(); + final int balance = Settings.INSTANCE.getDefaultDryRunBalance(); return (api.isDryRun() && balance > -1) ? BigDecimal.valueOf(balance) : api.execute(zonky -> zonky.getWallet().getAvailableBalance()); diff --git a/robozonky-common/src/main/java/com/github/triceo/robozonky/util/Scheduler.java b/robozonky-common/src/main/java/com/github/triceo/robozonky/util/Scheduler.java index 25be50b0c..48ec130c6 100644 --- a/robozonky-common/src/main/java/com/github/triceo/robozonky/util/Scheduler.java +++ b/robozonky-common/src/main/java/com/github/triceo/robozonky/util/Scheduler.java @@ -28,14 +28,15 @@ import java.util.function.Supplier; import com.github.triceo.robozonky.api.Refreshable; -import com.github.triceo.robozonky.internal.api.Defaults; +import com.github.triceo.robozonky.internal.api.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Scheduler { private static final Logger LOGGER = LoggerFactory.getLogger(Scheduler.class); - private static final TemporalAmount REFRESH = Duration.ofMinutes(Defaults.getRemoteResourceRefreshIntervalInMinutes()); + private static final TemporalAmount REFRESH = + Duration.ofMinutes(Settings.INSTANCE.getRemoteResourceRefreshIntervalInMinutes()); public static final Scheduler BACKGROUND_SCHEDULER = new Scheduler(1); private final Supplier executorProvider; diff --git a/robozonky-installer/robozonky-installer-panels/src/main/java/com/github/triceo/robozonky/installer/panels/RoboZonkyInstallerListener.java b/robozonky-installer/robozonky-installer-panels/src/main/java/com/github/triceo/robozonky/installer/panels/RoboZonkyInstallerListener.java index f6e74b223..28cf0be08 100644 --- a/robozonky-installer/robozonky-installer-panels/src/main/java/com/github/triceo/robozonky/installer/panels/RoboZonkyInstallerListener.java +++ b/robozonky-installer/robozonky-installer-panels/src/main/java/com/github/triceo/robozonky/installer/panels/RoboZonkyInstallerListener.java @@ -18,7 +18,6 @@ import java.io.File; import java.io.IOException; -import java.io.Writer; import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.Charset; @@ -38,7 +37,7 @@ import com.github.triceo.robozonky.common.secrets.KeyStoreHandler; import com.github.triceo.robozonky.common.secrets.SecretProvider; -import com.github.triceo.robozonky.internal.api.Defaults; +import com.github.triceo.robozonky.internal.api.Settings; import com.github.triceo.robozonky.notifications.email.RefreshableEmailNotificationProperties; import com.izforge.izpack.api.data.InstallData; import com.izforge.izpack.api.data.Pack; @@ -50,8 +49,8 @@ public final class RoboZonkyInstallerListener extends AbstractInstallerListener private static final Logger LOGGER = Logger.getLogger(RoboZonkyInstallerListener.class.getSimpleName()); private static InstallData DATA; final static char[] KEYSTORE_PASSWORD = UUID.randomUUID().toString().toCharArray(); - static File INSTALL_PATH, DIST_PATH, KEYSTORE_FILE, JMX_PROPERTIES_FILE, EMAIL_CONFIG_FILE, CLI_CONFIG_FILE, - LOGBACK_CONFIG_FILE; + static File INSTALL_PATH, DIST_PATH, KEYSTORE_FILE, JMX_PROPERTIES_FILE, EMAIL_CONFIG_FILE, SETTINGS_FILE, + CLI_CONFIG_FILE, LOGBACK_CONFIG_FILE; private static void copyFile(final File from, final File to) throws IOException { Files.copy(from.toPath(), to.getAbsoluteFile().toPath(), StandardCopyOption.REPLACE_EXISTING); @@ -74,6 +73,7 @@ static void setInstallData(final InstallData data) { KEYSTORE_FILE = new File(INSTALL_PATH, "robozonky.keystore"); JMX_PROPERTIES_FILE = new File(INSTALL_PATH, "management.properties"); EMAIL_CONFIG_FILE = new File(INSTALL_PATH, "robozonky-notifications.cfg"); + SETTINGS_FILE = new File(INSTALL_PATH, "robozonky.properties"); CLI_CONFIG_FILE = new File(INSTALL_PATH, "robozonky.cli"); LOGBACK_CONFIG_FILE = new File(INSTALL_PATH, "logback.xml"); @@ -86,6 +86,7 @@ static void resetInstallData() { KEYSTORE_FILE = null; JMX_PROPERTIES_FILE = null; EMAIL_CONFIG_FILE = null; + SETTINGS_FILE = null; CLI_CONFIG_FILE = null; LOGBACK_CONFIG_FILE = null; } @@ -127,6 +128,7 @@ private SecretProvider getSecretProvider(final char[] keystorePassword) { final String username = Variables.ZONKY_USERNAME.getValue(DATA); final char[] password = Variables.ZONKY_PASSWORD.getValue(DATA).toCharArray(); try { + KEYSTORE_FILE.delete(); final KeyStoreHandler keystore = KeyStoreHandler.create(KEYSTORE_FILE, keystorePassword); return SecretProvider.keyStoreBased(keystore, username, password); } catch (final Exception ex) { @@ -149,8 +151,8 @@ CommandLinePart prepareJmx() { props.setProperty("com.sun.management.jmxremote.rmi.port", port); props.setProperty("com.sun.management.jmxremote.port", port); props.setProperty("java.rmi.server.hostname", Variables.JMX_HOSTNAME.getValue(DATA)); - try (final Writer w = Files.newBufferedWriter(JMX_PROPERTIES_FILE.toPath(), Defaults.CHARSET)) { - props.store(w, Defaults.ROBOZONKY_USER_AGENT); + try { + Util.writeOutProperties(props, JMX_PROPERTIES_FILE); } catch (final IOException ex) { throw new IllegalStateException("Failed writing JMX configuration.", ex); } @@ -203,13 +205,27 @@ CommandLinePart prepareCommandLine(final CommandLinePart strategy, final Command // store it to a file cli.storeOptions(CLI_CONFIG_FILE); // and have the file loaded during RoboZonky startup - final CommandLinePart result = new CommandLinePart() + final CommandLinePart commandLine = new CommandLinePart() .setOption("@" + CLI_CONFIG_FILE.getAbsolutePath()) + .setProperty(Settings.FILE_LOCATION_PROPERTY, SETTINGS_FILE.getAbsolutePath()) .setEnvironmentVariable("JAVA_HOME", Variables.JAVA_HOME.getValue(DATA)); + // now proceed to set all system properties and settings + final Properties settings = new Properties(); Stream.of(strategy.getProperties(), emailConfig.getProperties(), jmxConfig.getProperties(), credentials.getProperties(), logging.getProperties()) - .forEach(m -> m.forEach(result::setProperty)); - return result; + .flatMap(p -> p.entrySet().stream()) + .forEach(e -> { + final String key = e.getKey(); + final String value = e.getValue(); + if (key.startsWith("robozonky")) { // RoboZonky setting to be written to separate file + settings.setProperty(key, value); + } else { // general Java system property to end up on the command line + commandLine.setProperty(key, value); + } + }); + // write settings to a file + Util.writeOutProperties(settings, SETTINGS_FILE); + return commandLine; } catch (final IOException ex) { throw new IllegalStateException("Failed writing CLI.", ex); } @@ -272,31 +288,22 @@ CommandLinePart prepareLogging() { } } - void prepareDirectory() { - KEYSTORE_FILE.delete(); - EMAIL_CONFIG_FILE.delete(); - CLI_CONFIG_FILE.delete(); - LOGBACK_CONFIG_FILE.delete(); - } - @Override public void afterPacks(final List packs, final ProgressListener progressListener) { - progressListener.startAction("Konfigurace RoboZonky", 8); - progressListener.nextStep("Příprava instalačního adresáře.", 1, 1); - prepareDirectory(); - progressListener.nextStep("Příprava strategie.", 2, 1); + progressListener.startAction("Konfigurace RoboZonky", 7); + progressListener.nextStep("Příprava strategie.", 1, 1); final CommandLinePart strategyConfig = prepareStrategy(); - progressListener.nextStep("Příprava nastavení e-mailu.", 3, 1); + progressListener.nextStep("Příprava nastavení e-mailu.", 2, 1); final CommandLinePart emailConfig = prepareEmailConfiguration(); - progressListener.nextStep("Příprava nastavení JMX.", 4, 1); + progressListener.nextStep("Příprava nastavení JMX.", 3, 1); final CommandLinePart jmx = prepareJmx(); - progressListener.nextStep("Příprava nastavení Zonky.", 5, 1); + progressListener.nextStep("Příprava nastavení Zonky.", 4, 1); final CommandLinePart credentials = prepareCore(); - progressListener.nextStep("Příprava nastavení logování.", 6, 1); + progressListener.nextStep("Příprava nastavení logování.", 5, 1); final CommandLinePart logging = prepareLogging(); - progressListener.nextStep("Generování parametrů příkazové řádky.", 7, 1); + progressListener.nextStep("Generování parametrů příkazové řádky.", 6, 1); final CommandLinePart result = prepareCommandLine(strategyConfig, emailConfig, jmx, credentials, logging); - progressListener.nextStep("Generování spustitelného souboru.", 8, 1); + progressListener.nextStep("Generování spustitelného souboru.", 7, 1); prepareRunScript(result); progressListener.stopAction(); } diff --git a/robozonky-installer/robozonky-installer-panels/src/main/java/com/github/triceo/robozonky/installer/panels/Util.java b/robozonky-installer/robozonky-installer-panels/src/main/java/com/github/triceo/robozonky/installer/panels/Util.java index 55634ee86..a959d7d43 100644 --- a/robozonky-installer/robozonky-installer-panels/src/main/java/com/github/triceo/robozonky/installer/panels/Util.java +++ b/robozonky-installer/robozonky-installer-panels/src/main/java/com/github/triceo/robozonky/installer/panels/Util.java @@ -17,10 +17,9 @@ package com.github.triceo.robozonky.installer.panels; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStreamWriter; import java.io.Writer; +import java.nio.file.Files; import java.util.Properties; import com.github.triceo.robozonky.internal.api.Defaults; @@ -40,8 +39,8 @@ private static final String toInt(final String string) { } public static void writeOutProperties(final Properties properties, final File target) throws IOException { - try (final Writer w = new OutputStreamWriter(new FileOutputStream(target), Defaults.CHARSET)) { - properties.store(w, "Konfigurace e-mailových notifikací z RoboZonky"); + try (final Writer w = Files.newBufferedWriter(target.toPath(), Defaults.CHARSET)) { + properties.store(w, Defaults.ROBOZONKY_USER_AGENT); } } diff --git a/robozonky-installer/robozonky-installer-panels/src/test/java/com/github/triceo/robozonky/installer/panels/RoboZonkyInstallerListenerTest.java b/robozonky-installer/robozonky-installer-panels/src/test/java/com/github/triceo/robozonky/installer/panels/RoboZonkyInstallerListenerTest.java index 3ffe5eb16..329fb5050 100644 --- a/robozonky-installer/robozonky-installer-panels/src/test/java/com/github/triceo/robozonky/installer/panels/RoboZonkyInstallerListenerTest.java +++ b/robozonky-installer/robozonky-installer-panels/src/test/java/com/github/triceo/robozonky/installer/panels/RoboZonkyInstallerListenerTest.java @@ -245,7 +245,7 @@ public void progressUnix() { softly.assertThat(RoboZonkyInstallerListener.CLI_CONFIG_FILE).exists(); }); Mockito.verify(progress, times(1)).startAction(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt()); - Mockito.verify(progress, times(8)) + Mockito.verify(progress, times(7)) .nextStep(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt(), ArgumentMatchers.eq(1)); Mockito.verify(progress, times(1)).stopAction(); } @@ -267,7 +267,7 @@ public void progressWindows() { softly.assertThat(RoboZonkyInstallerListener.CLI_CONFIG_FILE).exists(); }); Mockito.verify(progress, times(1)).startAction(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt()); - Mockito.verify(progress, times(8)) + Mockito.verify(progress, times(7)) .nextStep(ArgumentMatchers.anyString(), ArgumentMatchers.anyInt(), ArgumentMatchers.eq(1)); Mockito.verify(progress, times(1)).stopAction(); } diff --git a/robozonky-notifications/src/main/java/com/github/triceo/robozonky/notifications/RefreshableNotificationProperties.java b/robozonky-notifications/src/main/java/com/github/triceo/robozonky/notifications/RefreshableNotificationProperties.java index 4c78bb859..6aa474614 100644 --- a/robozonky-notifications/src/main/java/com/github/triceo/robozonky/notifications/RefreshableNotificationProperties.java +++ b/robozonky-notifications/src/main/java/com/github/triceo/robozonky/notifications/RefreshableNotificationProperties.java @@ -28,6 +28,7 @@ import java.util.stream.Collectors; import com.github.triceo.robozonky.api.Refreshable; +import com.github.triceo.robozonky.internal.api.Settings; import com.github.triceo.robozonky.internal.api.Defaults; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,9 +67,9 @@ public Supplier> getLatestSource() { } private Optional getPropertiesContents() { - final String propValue = System.getProperty(this.getConfigFileLocationPropertyName()); + final String propValue = Settings.INSTANCE.get(this.getConfigFileLocationPropertyName(), (String)null); if (propValue != null) { // attempt to read from the URL specified by the property - LOGGER.debug("Reading e-mail notification configuration from {}.", propValue); + LOGGER.debug("Reading notification configuration from {}.", propValue); try { return Optional.of(RefreshableNotificationProperties.readUrl(new URL(propValue))); } catch (final IOException ex) {