Skip to content
This repository has been archived by the owner on Oct 31, 2021. It is now read-only.

Commit

Permalink
Send all RoboZonky-specific properties to a file (#102)
Browse files Browse the repository at this point in the history
  • Loading branch information
triceo committed Apr 14, 2017
1 parent 2368c14 commit a13da48
Show file tree
Hide file tree
Showing 13 changed files with 215 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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);
}

}
Original file line number Diff line number Diff line change
@@ -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> T get(final String key, final Function<String, T> 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);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
});
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -116,13 +116,13 @@ public static <E extends Event> 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -74,7 +74,8 @@ public Optional<File> 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<ScheduledExecutorService> executorProvider;
Expand Down
Loading

0 comments on commit a13da48

Please sign in to comment.