diff --git a/build.gradle b/build.gradle index 9a17f7db1a..d7126cc9e4 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ sourceCompatibility = 1.8 sourceSets.main.resources.srcDirs += 'src/main/java' -mainClassName = "io.bitsquare.app.gui.Main" +mainClassName = "io.bitsquare.app.gui.BitsquareAppMain" run { if (project.hasProperty('args')) { @@ -33,6 +33,8 @@ repositories { dependencies { compile 'org.bitcoinj:bitcoinj-core:0.12' compile 'net.tomp2p:tomp2p-all:5.0-Alpha.aa0c736-SNAPSHOT' + compile 'org.springframework:spring-core:4.1.1.RELEASE' + compile 'net.sf.jopt-simple:jopt-simple:4.8' compile 'org.slf4j:slf4j-api:1.7.7' compile 'ch.qos.logback:logback-core:1.1.2' compile 'ch.qos.logback:logback-classic:1.1.2' @@ -45,7 +47,6 @@ dependencies { compile 'com.google.code.findbugs:jsr305:2.0.3' compile 'net.jcip:jcip-annotations:1.0' compile 'org.jetbrains:annotations:13.0' - compile 'net.sourceforge.argparse4j:argparse4j:0.4.4' compile 'eu.hansolo.enzo:Enzo:0.1.5' testCompile 'junit:junit:4.11' } diff --git a/src/main/java/io/bitsquare/gui/FatalException.java b/src/main/java/io/bitsquare/BitsquareException.java similarity index 73% rename from src/main/java/io/bitsquare/gui/FatalException.java rename to src/main/java/io/bitsquare/BitsquareException.java index 1ceb228864..ced9490e4f 100644 --- a/src/main/java/io/bitsquare/gui/FatalException.java +++ b/src/main/java/io/bitsquare/BitsquareException.java @@ -15,16 +15,20 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.gui; +package io.bitsquare; @SuppressWarnings("serializable") -public class FatalException extends RuntimeException { +public class BitsquareException extends RuntimeException { - public FatalException(String format, Object... args) { + public BitsquareException(Throwable cause) { + super(cause); + } + + public BitsquareException(String format, Object... args) { super(String.format(format, args)); } - public FatalException(Throwable cause, String format, Object... args) { + public BitsquareException(Throwable cause, String format, Object... args) { super(String.format(format, args), cause); } } diff --git a/src/main/java/io/bitsquare/BitsquareModule.java b/src/main/java/io/bitsquare/BitsquareModule.java index 9293650999..1e244cc936 100644 --- a/src/main/java/io/bitsquare/BitsquareModule.java +++ b/src/main/java/io/bitsquare/BitsquareModule.java @@ -22,17 +22,18 @@ import com.google.common.collect.Sets; import com.google.inject.AbstractModule; import com.google.inject.Injector; -import java.util.Properties; import java.util.Set; +import org.springframework.core.env.Environment; + public abstract class BitsquareModule extends AbstractModule { - protected final Properties properties; + protected final Environment env; private final Set modules = Sets.newHashSet(); - protected BitsquareModule(Properties properties) { - this.properties = properties; + protected BitsquareModule(Environment env) { + this.env = env; } protected void install(BitsquareModule module) { diff --git a/src/main/java/io/bitsquare/app/ArgumentParser.java b/src/main/java/io/bitsquare/app/ArgumentParser.java deleted file mode 100644 index e3a847d77e..0000000000 --- a/src/main/java/io/bitsquare/app/ArgumentParser.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * This file is part of Bitsquare. - * - * Bitsquare is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bitsquare is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bitsquare. If not, see . - */ - -package io.bitsquare.app; - -import io.bitsquare.btc.BitcoinModule; -import io.bitsquare.network.Node; - -import net.sourceforge.argparse4j.ArgumentParsers; -import net.sourceforge.argparse4j.inf.ArgumentParserException; -import net.sourceforge.argparse4j.inf.Namespace; - -import static io.bitsquare.app.AppModule.APP_NAME_KEY; -import static io.bitsquare.msg.tomp2p.TomP2PMessageModule.*; - -public class ArgumentParser { - - private final net.sourceforge.argparse4j.inf.ArgumentParser parser; - - public ArgumentParser() { - parser = ArgumentParsers.newArgumentParser("Bitsquare") - .defaultHelp(true) - .description("Bitsquare - The decentralized bitcoin exchange"); - - // Args for local node config - parser.addArgument("--" + Node.NAME_KEY) - .help("Local node name"); - parser.addArgument("--" + Node.PORT_KEY) - .help("Local node port"); - - // Args for bootstrap node config - parser.addArgument("--" + BOOTSTRAP_NODE_NAME_KEY) - .help("Bootstrap node name"); - parser.addArgument("--" + BOOTSTRAP_NODE_IP_KEY) - .help("Bootstrap node IP address"); - parser.addArgument("--" + BOOTSTRAP_NODE_PORT_KEY) - .help("Bootstrap node port"); - - // A custom network interface (needed at the moment for windows, but might be useful also later) - parser.addArgument("--" + NETWORK_INTERFACE_KEY) - .help("Network interface"); - - parser.addArgument("--" + BitcoinModule.BITCOIN_NETWORK_KEY) - .setDefault(BitcoinModule.DEFAULT_BITCOIN_NETWORK.toString()) - .help("Bitcoin network to use"); - - // Args for app config - parser.addArgument("-n", "--" + APP_NAME_KEY) - .help("Name to append to default application name"); - } - - public Namespace parseArgs(String... args) { - try { - return parser.parseArgs(args); - } catch (ArgumentParserException e) { - parser.handleError(e); - System.exit(1); - return null; - } - } -} diff --git a/src/main/java/io/bitsquare/app/BitsquareEnvironment.java b/src/main/java/io/bitsquare/app/BitsquareEnvironment.java new file mode 100644 index 0000000000..2155ba3bf8 --- /dev/null +++ b/src/main/java/io/bitsquare/app/BitsquareEnvironment.java @@ -0,0 +1,98 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bitsquare is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bitsquare. If not, see . + */ + +package io.bitsquare.app; + +import io.bitsquare.BitsquareException; + +import com.google.common.base.Preconditions; + +import java.io.IOException; + +import java.util.Properties; + +import joptsimple.OptionSet; +import lighthouse.files.AppDirectory; +import org.springframework.core.env.JOptCommandLinePropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertiesPropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.core.env.StandardEnvironment; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.io.support.ResourcePropertySource; + +public class BitsquareEnvironment extends StandardEnvironment { + + public static final String APP_NAME_KEY = "appName"; + public static final String DEFAULT_APP_NAME = "Bitsquare"; + + private static final String BITSQUARE_APP_PROPERTY_SOURCE_NAME = "bitsquareAppProperties"; + private static final String BITSQUARE_CLASSPATH_PROPERTY_SOURCE_NAME = "bitsquareClasspathProperties"; + private static final String BITSQUARE_FILESYSTEM_PROPERTY_SOURCE_NAME = "bitsquareFilesystemProperties"; + private static final String BITSQUARE_COMMANDLINE_PROPERTY_SOURCE_NAME = "bitsquareCommandLineProperties"; + + private final ResourceLoader resourceLoader = new DefaultResourceLoader(); + + public BitsquareEnvironment(OptionSet options) { + Preconditions.checkArgument(options != null, "Options must not be null"); + + PropertySource commandLineProperties = + new JOptCommandLinePropertySource(BITSQUARE_COMMANDLINE_PROPERTY_SOURCE_NAME, options); + + String appName = commandLineProperties.containsProperty(APP_NAME_KEY) ? + DEFAULT_APP_NAME + "-" + commandLineProperties.getProperty(APP_NAME_KEY) : + DEFAULT_APP_NAME; + + MutablePropertySources propertySources = this.getPropertySources(); + propertySources.addBefore(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, appProperties(appName)); + propertySources.addBefore(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, classpathProperties()); + propertySources.addBefore(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, filesystemProperties(appName)); + propertySources.addAfter(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, commandLineProperties); + } + + private PropertySource appProperties(String appName) { + return new PropertiesPropertySource(BITSQUARE_APP_PROPERTY_SOURCE_NAME, new Properties() {{ + setProperty(APP_NAME_KEY, appName); + }}); + } + + private PropertySource classpathProperties() { + try { + Resource resource = resourceLoader.getResource("classpath:bitsquare.properties"); + return new ResourcePropertySource(BITSQUARE_CLASSPATH_PROPERTY_SOURCE_NAME, resource); + } catch (IOException ex) { + throw new BitsquareException(ex); + } + } + + private PropertySource filesystemProperties(String appName) { + String location = String.format("file:%s/bitsquare.conf", AppDirectory.dir(appName)); + Resource resource = resourceLoader.getResource(location); + + if (!resource.exists()) { + return new PropertySource.StubPropertySource(BITSQUARE_FILESYSTEM_PROPERTY_SOURCE_NAME); + } + + try { + return new ResourcePropertySource(BITSQUARE_FILESYSTEM_PROPERTY_SOURCE_NAME, resource); + } catch (IOException ex) { + throw new BitsquareException(ex); + } + } +} diff --git a/src/main/java/io/bitsquare/app/BitsquareExecutable.java b/src/main/java/io/bitsquare/app/BitsquareExecutable.java new file mode 100644 index 0000000000..fd5b3f35f4 --- /dev/null +++ b/src/main/java/io/bitsquare/app/BitsquareExecutable.java @@ -0,0 +1,57 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bitsquare is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bitsquare. If not, see . + */ + +package io.bitsquare.app; + +import joptsimple.OptionException; +import joptsimple.OptionParser; +import joptsimple.OptionSet; + +public abstract class BitsquareExecutable { + public static final int EXIT_SUCCESS = 0; + public static final int EXIT_FAILURE = 1; + public static final String HELP_KEY = "help"; + + public void execute(String[] args) throws Exception { + OptionParser parser = new OptionParser(); + parser.accepts(HELP_KEY, "This help text").forHelp(); + + this.customizeOptionParsing(parser); + + OptionSet options; + try { + options = parser.parse(args); + if (options.has(HELP_KEY)) { + parser.printHelpOn(System.out); + System.exit(EXIT_SUCCESS); + return; + } + } catch (OptionException ex) { + System.out.println("error: " + ex.getMessage()); + System.out.println(); + parser.printHelpOn(System.out); + System.exit(EXIT_FAILURE); + return; + } + + this.doExecute(options); + } + + protected abstract void customizeOptionParsing(OptionParser parser); + + protected abstract void doExecute(OptionSet options); +} diff --git a/src/main/java/io/bitsquare/app/cli/BootstrapNode.java b/src/main/java/io/bitsquare/app/cli/BootstrapNode.java index b5d076a4a6..296d7e55b0 100644 --- a/src/main/java/io/bitsquare/app/cli/BootstrapNode.java +++ b/src/main/java/io/bitsquare/app/cli/BootstrapNode.java @@ -17,7 +17,6 @@ package io.bitsquare.app.cli; -import io.bitsquare.app.ArgumentParser; import io.bitsquare.network.Node; import net.tomp2p.dht.PeerBuilderDHT; @@ -33,7 +32,7 @@ import net.tomp2p.rpc.ObjectDataReply; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import net.sourceforge.argparse4j.inf.Namespace; +import org.springframework.core.env.Environment; public class BootstrapNode { private static final Logger log = LoggerFactory.getLogger(BootstrapNode.class); @@ -41,16 +40,15 @@ public class BootstrapNode { private static Peer peer = null; private static boolean running = true; - public static void main(String[] args) throws Exception { - ArgumentParser parser = new ArgumentParser(); - Namespace namespace = parser.parseArgs(args); + private final Environment env; - String name = namespace.getString(Node.NAME_KEY); - if (name == null) - throw new IllegalArgumentException(String.format("--%s option is required", Node.NAME_KEY)); + public BootstrapNode(Environment env) { + this.env = env; + } - String portValue = namespace.getString(Node.PORT_KEY); - int port = portValue != null ? Integer.valueOf(portValue) : Node.DEFAULT_PORT; + public void start() { + String name = env.getRequiredProperty(Node.NAME_KEY); + int port = env.getProperty(Node.PORT_KEY, Integer.class, Node.DEFAULT_PORT); try { Number160 peerId = Number160.createHash(name); @@ -90,12 +88,4 @@ public class BootstrapNode { peer.shutdown().awaitUninterruptibly(); } } - - public static void stop() { - running = false; - if (peer != null) { - peer.shutdown().awaitUninterruptibly(); - } - peer = null; - } } diff --git a/src/main/java/io/bitsquare/app/cli/BootstrapNodeMain.java b/src/main/java/io/bitsquare/app/cli/BootstrapNodeMain.java new file mode 100644 index 0000000000..b45849e4f6 --- /dev/null +++ b/src/main/java/io/bitsquare/app/cli/BootstrapNodeMain.java @@ -0,0 +1,42 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bitsquare is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bitsquare. If not, see . + */ + +package io.bitsquare.app.cli; + +import io.bitsquare.app.BitsquareEnvironment; +import io.bitsquare.app.BitsquareExecutable; +import io.bitsquare.network.Node; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; + +public class BootstrapNodeMain extends BitsquareExecutable { + + public static void main(String[] args) throws Exception { + new BootstrapNodeMain().execute(args); + } + + protected void customizeOptionParsing(OptionParser parser) { + parser.accepts(Node.NAME_KEY, "Name of this node").withRequiredArg().isRequired(); + parser.accepts(Node.PORT_KEY, "Port to listen on").withRequiredArg() + .defaultsTo(String.valueOf(Node.DEFAULT_PORT)); + } + + protected void doExecute(OptionSet options) { + new BootstrapNode(new BitsquareEnvironment(options)).start(); + } +} diff --git a/src/main/java/io/bitsquare/app/gui/Main.java b/src/main/java/io/bitsquare/app/gui/BitsquareApp.java similarity index 61% rename from src/main/java/io/bitsquare/app/gui/Main.java rename to src/main/java/io/bitsquare/app/gui/BitsquareApp.java index 899d7aba7c..2fe756c9de 100644 --- a/src/main/java/io/bitsquare/app/gui/Main.java +++ b/src/main/java/io/bitsquare/app/gui/BitsquareApp.java @@ -17,7 +17,7 @@ package io.bitsquare.app.gui; -import io.bitsquare.app.ArgumentParser; +import io.bitsquare.app.BitsquareEnvironment; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.SystemTray; import io.bitsquare.gui.ViewLoader; @@ -26,8 +26,8 @@ import io.bitsquare.gui.util.ImageUtil; import io.bitsquare.persistence.Persistence; import io.bitsquare.settings.Settings; import io.bitsquare.user.User; -import io.bitsquare.util.ConfigLoader; +import com.google.common.base.Preconditions; import com.google.common.base.Throwables; import com.google.inject.Guice; @@ -35,8 +35,6 @@ import com.google.inject.Injector; import java.io.IOException; -import java.util.Properties; - import javafx.application.Application; import javafx.scene.*; import javafx.scene.image.*; @@ -47,59 +45,28 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import lighthouse.files.AppDirectory; -import net.sourceforge.argparse4j.inf.Namespace; +import org.springframework.core.env.Environment; -import static io.bitsquare.app.AppModule.APP_NAME_KEY; -import static io.bitsquare.btc.BitcoinModule.BITCOIN_NETWORK_KEY; -import static io.bitsquare.msg.tomp2p.TomP2PMessageModule.*; -import static io.bitsquare.network.Node.*; +public class BitsquareApp extends Application { + private static final Logger log = LoggerFactory.getLogger(BitsquareApp.class); -public class Main extends Application { - private static final Logger log = LoggerFactory.getLogger(Main.class); - private static String appName = "Bitsquare"; - private static Properties properties; + private static Environment env; - private MainModule mainModule; + private BitsquareAppModule bitsquareAppModule; private Injector injector; - public static void main(String[] args) { - Namespace argumentsNamespace = new ArgumentParser().parseArgs(args); - - if (argumentsNamespace.getString(APP_NAME_KEY) != null) - appName = appName + "-" + argumentsNamespace.getString(APP_NAME_KEY); - - properties = ConfigLoader.loadConfig(appName); - - properties.setProperty(APP_NAME_KEY, appName); - - if (argumentsNamespace.getString(NAME_KEY) != null) - properties.setProperty(NAME_KEY, argumentsNamespace.getString(NAME_KEY)); - - if (argumentsNamespace.getString(PORT_KEY) != null) - properties.setProperty(PORT_KEY, argumentsNamespace.getString(PORT_KEY)); - - if (argumentsNamespace.getString(BOOTSTRAP_NODE_NAME_KEY) != null) - properties.setProperty(BOOTSTRAP_NODE_NAME_KEY, argumentsNamespace.getString(BOOTSTRAP_NODE_NAME_KEY)); - - if (argumentsNamespace.getString(BOOTSTRAP_NODE_IP_KEY) != null) - properties.setProperty(BOOTSTRAP_NODE_IP_KEY, argumentsNamespace.getString(BOOTSTRAP_NODE_IP_KEY)); - - if (argumentsNamespace.getString(BOOTSTRAP_NODE_PORT_KEY) != null) - properties.setProperty(BOOTSTRAP_NODE_PORT_KEY, argumentsNamespace.getString(BOOTSTRAP_NODE_PORT_KEY)); - - if (argumentsNamespace.getString(NETWORK_INTERFACE_KEY) != null) - properties.setProperty(NETWORK_INTERFACE_KEY, argumentsNamespace.getString(NETWORK_INTERFACE_KEY)); - - if (argumentsNamespace.getString(BITCOIN_NETWORK_KEY) != null) - properties.setProperty(BITCOIN_NETWORK_KEY, argumentsNamespace.getString(BITCOIN_NETWORK_KEY)); - - Application.launch(Main.class, args); + public static void setEnvironment(Environment env) { + BitsquareApp.env = env; } @Override - public void start(Stage primaryStage) { - mainModule = new MainModule(properties, primaryStage); - injector = Guice.createInjector(mainModule); + public void start(Stage primaryStage) throws IOException { + Preconditions.checkArgument(env != null, "Environment must not be null"); + + String appName = env.getRequiredProperty(BitsquareEnvironment.APP_NAME_KEY); + + bitsquareAppModule = new BitsquareAppModule(env, primaryStage); + injector = Guice.createInjector(bitsquareAppModule); // route uncaught exceptions to a user-facing dialog @@ -173,7 +140,7 @@ public class Main extends Application { @Override public void stop() { - mainModule.close(injector); + bitsquareAppModule.close(injector); System.exit(0); } } diff --git a/src/main/java/io/bitsquare/app/gui/BitsquareAppMain.java b/src/main/java/io/bitsquare/app/gui/BitsquareAppMain.java new file mode 100644 index 0000000000..1bc8fbe0b5 --- /dev/null +++ b/src/main/java/io/bitsquare/app/gui/BitsquareAppMain.java @@ -0,0 +1,57 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bitsquare is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bitsquare. If not, see . + */ + +package io.bitsquare.app.gui; + +import io.bitsquare.app.BitsquareEnvironment; +import io.bitsquare.app.BitsquareExecutable; +import io.bitsquare.btc.BitcoinModule; +import io.bitsquare.network.BootstrapNodes; +import io.bitsquare.network.Node; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; + +import static io.bitsquare.app.BitsquareEnvironment.APP_NAME_KEY; +import static io.bitsquare.btc.BitcoinModule.BITCOIN_NETWORK_KEY; +import static io.bitsquare.msg.tomp2p.TomP2PMessageModule.*; +import static io.bitsquare.network.Node.*; + +public class BitsquareAppMain extends BitsquareExecutable { + + public static void main(String[] args) throws Exception { + new BitsquareAppMain().execute(args); + } + + @Override + protected void customizeOptionParsing(OptionParser parser) { + parser.accepts(APP_NAME_KEY, "Qualified application name").withRequiredArg(); + parser.accepts(NAME_KEY, "Name of this node").withRequiredArg(); + parser.accepts(PORT_KEY, "Port to listen on").withRequiredArg().defaultsTo(String.valueOf(Node.DEFAULT_PORT)); + parser.accepts(BITCOIN_NETWORK_KEY).withRequiredArg().defaultsTo(BitcoinModule.DEFAULT_BITCOIN_NETWORK); + parser.accepts(BOOTSTRAP_NODE_NAME_KEY).withRequiredArg().defaultsTo(BootstrapNodes.DEFAULT.getName()); + parser.accepts(BOOTSTRAP_NODE_IP_KEY).withRequiredArg().defaultsTo(BootstrapNodes.DEFAULT.getIp()); + parser.accepts(BOOTSTRAP_NODE_PORT_KEY).withRequiredArg().defaultsTo(BootstrapNodes.DEFAULT.getPortAsString()); + parser.accepts(NETWORK_INTERFACE_KEY, "Network interface").withRequiredArg(); + } + + @Override + protected void doExecute(OptionSet options) { + BitsquareApp.setEnvironment(new BitsquareEnvironment(options)); + javafx.application.Application.launch(BitsquareApp.class); + } +} diff --git a/src/main/java/io/bitsquare/app/AppModule.java b/src/main/java/io/bitsquare/app/gui/BitsquareAppModule.java similarity index 71% rename from src/main/java/io/bitsquare/app/AppModule.java rename to src/main/java/io/bitsquare/app/gui/BitsquareAppModule.java index 8b7a134a0e..8e2343f059 100644 --- a/src/main/java/io/bitsquare/app/AppModule.java +++ b/src/main/java/io/bitsquare/app/gui/BitsquareAppModule.java @@ -15,11 +15,13 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.app; +package io.bitsquare.app.gui; import io.bitsquare.BitsquareModule; +import io.bitsquare.app.BitsquareEnvironment; import io.bitsquare.btc.BitcoinModule; import io.bitsquare.crypto.CryptoModule; +import io.bitsquare.gui.GuiModule; import io.bitsquare.msg.MessageModule; import io.bitsquare.msg.tomp2p.TomP2PMessageModule; import io.bitsquare.offer.OfferModule; @@ -29,21 +31,20 @@ import io.bitsquare.settings.Settings; import io.bitsquare.trade.TradeModule; import io.bitsquare.user.User; -import com.google.common.base.Preconditions; - import com.google.inject.Injector; import com.google.inject.name.Names; -import java.util.Properties; +import javafx.stage.Stage; -/** - * Configures all non-UI modules necessary to run a Bitsquare application. - */ -public class AppModule extends BitsquareModule { - public static final String APP_NAME_KEY = "appName"; +import org.springframework.core.env.Environment; - public AppModule(Properties properties) { - super(properties); +class BitsquareAppModule extends BitsquareModule { + + private final Stage primaryStage; + + public BitsquareAppModule(Environment env, Stage primaryStage) { + super(env); + this.primaryStage = primaryStage; } @Override @@ -57,35 +58,38 @@ public class AppModule extends BitsquareModule { install(cryptoModule()); install(tradeModule()); install(offerModule()); + install(guiModule()); - String appName = properties.getProperty(APP_NAME_KEY); - Preconditions.checkArgument(appName != null, "App name must be non-null"); + String appName = env.getRequiredProperty(BitsquareEnvironment.APP_NAME_KEY); bindConstant().annotatedWith(Names.named("appName")).to(appName); } protected MessageModule messageModule() { - return new TomP2PMessageModule(properties); + return new TomP2PMessageModule(env); } protected BitcoinModule bitcoinModule() { - return new BitcoinModule(properties); + return new BitcoinModule(env); } protected CryptoModule cryptoModule() { - return new CryptoModule(properties); + return new CryptoModule(env); } protected TradeModule tradeModule() { - return new TradeModule(properties); + return new TradeModule(env); } protected OfferModule offerModule() { - return new TomP2POfferModule(properties); + return new TomP2POfferModule(env); + } + + protected GuiModule guiModule() { + return new GuiModule(env, primaryStage); } @Override protected void doClose(Injector injector) { } } - diff --git a/src/main/java/io/bitsquare/btc/BitcoinModule.java b/src/main/java/io/bitsquare/btc/BitcoinModule.java index c43edba080..1d77a557ff 100644 --- a/src/main/java/io/bitsquare/btc/BitcoinModule.java +++ b/src/main/java/io/bitsquare/btc/BitcoinModule.java @@ -26,15 +26,15 @@ import org.bitcoinj.params.TestNet3Params; import com.google.inject.Injector; -import java.util.Properties; +import org.springframework.core.env.Environment; public class BitcoinModule extends BitsquareModule { public static final String BITCOIN_NETWORK_KEY = "bitcoin.network"; public static final String DEFAULT_BITCOIN_NETWORK = BitcoinNetwork.TESTNET.toString(); - public BitcoinModule(Properties properties) { - super(properties); + public BitcoinModule(Environment env) { + super(env); } @Override @@ -52,7 +52,7 @@ public class BitcoinModule extends BitsquareModule { private NetworkParameters network() { BitcoinNetwork network = BitcoinNetwork.valueOf( - properties.getProperty(BITCOIN_NETWORK_KEY, DEFAULT_BITCOIN_NETWORK).toUpperCase()); + env.getProperty(BITCOIN_NETWORK_KEY, DEFAULT_BITCOIN_NETWORK).toUpperCase()); switch (network) { case MAINNET: diff --git a/src/main/java/io/bitsquare/crypto/CryptoModule.java b/src/main/java/io/bitsquare/crypto/CryptoModule.java index fc3472c98b..77189b2d3f 100644 --- a/src/main/java/io/bitsquare/crypto/CryptoModule.java +++ b/src/main/java/io/bitsquare/crypto/CryptoModule.java @@ -19,12 +19,12 @@ package io.bitsquare.crypto; import io.bitsquare.BitsquareModule; -import java.util.Properties; +import org.springframework.core.env.Environment; public class CryptoModule extends BitsquareModule { - public CryptoModule(Properties properties) { - super(properties); + public CryptoModule(Environment env) { + super(env); } @Override diff --git a/src/main/java/io/bitsquare/gui/GuiModule.java b/src/main/java/io/bitsquare/gui/GuiModule.java index 8491ce60bb..48f06c1975 100644 --- a/src/main/java/io/bitsquare/gui/GuiModule.java +++ b/src/main/java/io/bitsquare/gui/GuiModule.java @@ -28,16 +28,16 @@ import io.bitsquare.gui.util.validation.FiatValidator; import io.bitsquare.gui.util.validation.InputValidator; import io.bitsquare.gui.util.validation.PasswordValidator; -import java.util.Properties; - import javafx.stage.Stage; +import org.springframework.core.env.Environment; + public class GuiModule extends BitsquareModule { private final Stage primaryStage; - public GuiModule(Properties properties, Stage primaryStage) { - super(properties); + public GuiModule(Environment env, Stage primaryStage) { + super(env); this.primaryStage = primaryStage; } diff --git a/src/main/java/io/bitsquare/gui/ViewLoader.java b/src/main/java/io/bitsquare/gui/ViewLoader.java index 1de55a7a2e..fc3d7b3b9c 100644 --- a/src/main/java/io/bitsquare/gui/ViewLoader.java +++ b/src/main/java/io/bitsquare/gui/ViewLoader.java @@ -17,6 +17,7 @@ package io.bitsquare.gui; +import io.bitsquare.BitsquareException; import io.bitsquare.locale.BSResources; import com.google.inject.Injector; @@ -56,7 +57,7 @@ public class ViewLoader { public ViewLoader(Navigation.FxmlResource navItem, boolean useCaching) { this.url = ViewLoader.class.getResource(navItem.getFxmlUrl()); if (this.url == null) { - throw new FatalException("'%s' could not be loaded as a resource", navItem.getFxmlUrl()); + throw new BitsquareException("'%s' could not be loaded as a resource", navItem.getFxmlUrl()); } isCached = useCaching && cachedGUIItems.containsKey(url); @@ -87,7 +88,7 @@ public class ViewLoader { cachedGUIItems.put(url, item); return result; } catch (IOException e) { - throw new FatalException(e, "Failed to load view at %s", url); + throw new BitsquareException(e, "Failed to load view at %s", url); } } diff --git a/src/main/java/io/bitsquare/msg/MessageModule.java b/src/main/java/io/bitsquare/msg/MessageModule.java index e7092fa4da..14c358adbe 100644 --- a/src/main/java/io/bitsquare/msg/MessageModule.java +++ b/src/main/java/io/bitsquare/msg/MessageModule.java @@ -21,12 +21,12 @@ import io.bitsquare.BitsquareModule; import com.google.inject.Injector; -import java.util.Properties; +import org.springframework.core.env.Environment; public abstract class MessageModule extends BitsquareModule { - protected MessageModule(Properties properties) { - super(properties); + protected MessageModule(Environment env) { + super(env); } @Override diff --git a/src/main/java/io/bitsquare/msg/tomp2p/TomP2PMessageModule.java b/src/main/java/io/bitsquare/msg/tomp2p/TomP2PMessageModule.java index d1c1e7ca45..e4d49908c6 100644 --- a/src/main/java/io/bitsquare/msg/tomp2p/TomP2PMessageModule.java +++ b/src/main/java/io/bitsquare/msg/tomp2p/TomP2PMessageModule.java @@ -24,7 +24,7 @@ import io.bitsquare.network.Node; import com.google.inject.name.Names; -import java.util.Properties; +import org.springframework.core.env.Environment; import static io.bitsquare.msg.tomp2p.BootstrappedPeerFactory.*; @@ -35,25 +35,25 @@ public class TomP2PMessageModule extends MessageModule { public static final String BOOTSTRAP_NODE_PORT_KEY = "bootstrap.node.port"; public static final String NETWORK_INTERFACE_KEY = BootstrappedPeerFactory.NETWORK_INTERFACE_KEY; - public TomP2PMessageModule(Properties properties) { - super(properties); + public TomP2PMessageModule(Environment env) { + super(env); } @Override protected void doConfigure() { bind(int.class).annotatedWith(Names.named(Node.PORT_KEY)).toInstance( - Integer.valueOf(properties.getProperty(Node.PORT_KEY, String.valueOf(Node.DEFAULT_PORT)))); + env.getProperty(Node.PORT_KEY, Integer.class, Node.DEFAULT_PORT)); bind(TomP2PNode.class).asEagerSingleton(); bind(Node.class).annotatedWith(Names.named(BOOTSTRAP_NODE_KEY)).toInstance( Node.at( - properties.getProperty(BOOTSTRAP_NODE_NAME_KEY, BootstrapNodes.DEFAULT.getName()), - properties.getProperty(BOOTSTRAP_NODE_IP_KEY, BootstrapNodes.DEFAULT.getIp()), - properties.getProperty(BOOTSTRAP_NODE_PORT_KEY, BootstrapNodes.DEFAULT.getPortAsString()) + env.getProperty(BOOTSTRAP_NODE_NAME_KEY, BootstrapNodes.DEFAULT.getName()), + env.getProperty(BOOTSTRAP_NODE_IP_KEY, BootstrapNodes.DEFAULT.getIp()), + env.getProperty(BOOTSTRAP_NODE_PORT_KEY, BootstrapNodes.DEFAULT.getPortAsString()) ) ); bindConstant().annotatedWith(Names.named(NETWORK_INTERFACE_KEY)).to( - properties.getProperty(NETWORK_INTERFACE_KEY, NETWORK_INTERFACE_UNSPECIFIED)); + env.getProperty(NETWORK_INTERFACE_KEY, NETWORK_INTERFACE_UNSPECIFIED)); bind(BootstrappedPeerFactory.class).asEagerSingleton(); } diff --git a/src/main/java/io/bitsquare/offer/OfferModule.java b/src/main/java/io/bitsquare/offer/OfferModule.java index a83627f92e..227c30656b 100644 --- a/src/main/java/io/bitsquare/offer/OfferModule.java +++ b/src/main/java/io/bitsquare/offer/OfferModule.java @@ -19,12 +19,12 @@ package io.bitsquare.offer; import io.bitsquare.BitsquareModule; -import java.util.Properties; +import org.springframework.core.env.Environment; public abstract class OfferModule extends BitsquareModule { - protected OfferModule(Properties properties) { - super(properties); + protected OfferModule(Environment env) { + super(env); } @Override diff --git a/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferModule.java b/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferModule.java index fb7e3729ad..af2262573d 100644 --- a/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferModule.java +++ b/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferModule.java @@ -20,12 +20,12 @@ package io.bitsquare.offer.tomp2p; import io.bitsquare.offer.OfferModule; import io.bitsquare.offer.OfferRepository; -import java.util.Properties; +import org.springframework.core.env.Environment; public class TomP2POfferModule extends OfferModule { - public TomP2POfferModule(Properties properties) { - super(properties); + public TomP2POfferModule(Environment env) { + super(env); } @Override diff --git a/src/main/java/io/bitsquare/trade/TradeModule.java b/src/main/java/io/bitsquare/trade/TradeModule.java index 626e01e6ce..30242578f7 100644 --- a/src/main/java/io/bitsquare/trade/TradeModule.java +++ b/src/main/java/io/bitsquare/trade/TradeModule.java @@ -19,12 +19,12 @@ package io.bitsquare.trade; import io.bitsquare.BitsquareModule; -import java.util.Properties; +import org.springframework.core.env.Environment; public class TradeModule extends BitsquareModule { - public TradeModule(Properties properties) { - super(properties); + public TradeModule(Environment env) { + super(env); } @Override diff --git a/src/main/java/io/bitsquare/util/ConfigLoader.java b/src/main/java/io/bitsquare/util/ConfigLoader.java deleted file mode 100644 index 484cd7823c..0000000000 --- a/src/main/java/io/bitsquare/util/ConfigLoader.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is part of Bitsquare. - * - * Bitsquare is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bitsquare is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bitsquare. If not, see . - */ - -package io.bitsquare.util; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; - -import java.util.Properties; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import lighthouse.files.AppDirectory; - -public class ConfigLoader { - private static final Logger log = LoggerFactory.getLogger(ConfigLoader.class); - private static String configFilePath; - - public static Properties loadConfig(String appName) { - configFilePath = AppDirectory.dir(appName) + "/bitsquare.conf"; - InputStream inputStream = null; - - // load default properties from class path - Properties defaultProperties = new Properties(); - try { - InputStream is = ConfigLoader.class.getResourceAsStream("/bitsquare.properties"); - defaultProperties.load(is); - } catch (IOException ioe) { - ioe.printStackTrace(); - } finally { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - } - - // load properties file from config file path - Properties properties = new Properties(defaultProperties); - if (new File(configFilePath).exists()) { - try { - inputStream = new FileInputStream(configFilePath); - properties.load(inputStream); - } catch (IOException ioe) { - ioe.printStackTrace(); - } finally { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - } - } - return properties; - } -} diff --git a/src/main/java/io/bitsquare/app/gui/MainModule.java b/src/test/java/io/bitsquare/BitsquareEnvironmentTests.java similarity index 50% rename from src/main/java/io/bitsquare/app/gui/MainModule.java rename to src/test/java/io/bitsquare/BitsquareEnvironmentTests.java index 7fd38c8c52..c962effb94 100644 --- a/src/main/java/io/bitsquare/app/gui/MainModule.java +++ b/src/test/java/io/bitsquare/BitsquareEnvironmentTests.java @@ -15,27 +15,27 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.app.gui; +package io.bitsquare; -import io.bitsquare.BitsquareModule; -import io.bitsquare.app.AppModule; -import io.bitsquare.gui.GuiModule; +import io.bitsquare.app.BitsquareEnvironment; -import java.util.Properties; +import org.junit.Test; -import javafx.stage.Stage; +import joptsimple.OptionParser; -class MainModule extends BitsquareModule { - private final Stage primaryStage; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.*; - public MainModule(Properties properties, Stage primaryStage) { - super(properties); - this.primaryStage = primaryStage; +public class BitsquareEnvironmentTests { + + @Test + public void test() { + String[] args = new String[]{ "--arg1=val1", "--arg2=val2" }; + OptionParser parser = new OptionParser(); + parser.accepts("arg1").withRequiredArg(); + parser.accepts("arg2").withRequiredArg(); + BitsquareEnvironment env = new BitsquareEnvironment(parser.parse(args)); + assertThat(env.getProperty("arg1"), equalTo("val1")); + assertThat(env.getProperty("arg2"), equalTo("val2")); } - - @Override - protected void configure() { - install(new AppModule(properties)); - install(new GuiModule(properties, primaryStage)); - } -} +} \ No newline at end of file diff --git a/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java b/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java index b766d5aab0..d0d79f7aea 100644 --- a/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java +++ b/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java @@ -17,7 +17,8 @@ package io.bitsquare.app.gui; -import io.bitsquare.gui.FatalException; +import io.bitsquare.BitsquareException; +import io.bitsquare.app.BitsquareEnvironment; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.ViewLoader; @@ -34,7 +35,8 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import static io.bitsquare.app.AppModule.APP_NAME_KEY; +import joptsimple.OptionParser; +import org.springframework.core.env.PropertiesPropertySource; public class ViewLoaderTests { @@ -64,8 +66,11 @@ public class ViewLoaderTests { @Before public void setUp() { Properties properties = new Properties(); - properties.setProperty(APP_NAME_KEY, "testApp"); - Injector injector = Guice.createInjector(new MainModule(properties, TestApp.primaryStage)); + properties.setProperty(BitsquareEnvironment.APP_NAME_KEY, "testApp"); + OptionParser parser = new OptionParser(); + BitsquareEnvironment env = new BitsquareEnvironment(parser.parse(new String[] {})); + env.getPropertySources().addLast(new PropertiesPropertySource("testProperties", properties)); + Injector injector = Guice.createInjector(new BitsquareAppModule(env, TestApp.primaryStage)); ViewLoader.setInjector(injector); } @@ -74,7 +79,7 @@ public class ViewLoaderTests { ViewLoader.setInjector(null); } - @Test(expected = FatalException.class) + @Test(expected = BitsquareException.class) public void loadingBogusFxmlResourceShouldThrow() { new ViewLoader(() -> "a bogus fxml resource", false).load(); }