diff --git a/src/main/java/io/bitsquare/AbstractBitsquareModule.java b/src/main/java/io/bitsquare/BitsquareModule.java similarity index 84% rename from src/main/java/io/bitsquare/AbstractBitsquareModule.java rename to src/main/java/io/bitsquare/BitsquareModule.java index 46a6f88c98..9293650999 100644 --- a/src/main/java/io/bitsquare/AbstractBitsquareModule.java +++ b/src/main/java/io/bitsquare/BitsquareModule.java @@ -25,24 +25,24 @@ import com.google.inject.Injector; import java.util.Properties; import java.util.Set; -public abstract class AbstractBitsquareModule extends AbstractModule { +public abstract class BitsquareModule extends AbstractModule { protected final Properties properties; - private final Set modules = Sets.newHashSet(); + private final Set modules = Sets.newHashSet(); - protected AbstractBitsquareModule(Properties properties) { + protected BitsquareModule(Properties properties) { this.properties = properties; } - protected void install(AbstractBitsquareModule module) { + protected void install(BitsquareModule module) { super.install(module); modules.add(module); } /** * Close any instances this module is responsible for and recursively close any - * sub-modules installed via {@link #install(AbstractBitsquareModule)}. This method + * sub-modules installed via {@link #install(BitsquareModule)}. This method * must be called manually, e.g. at the end of a main() method or in the stop() method * of a JavaFX Application; alternatively it may be registered as a JVM shutdown hook. * diff --git a/src/main/java/io/bitsquare/app/BitsquareModule.java b/src/main/java/io/bitsquare/app/AppModule.java similarity index 76% rename from src/main/java/io/bitsquare/app/BitsquareModule.java rename to src/main/java/io/bitsquare/app/AppModule.java index 9395174c84..904d3fb1ae 100644 --- a/src/main/java/io/bitsquare/app/BitsquareModule.java +++ b/src/main/java/io/bitsquare/app/AppModule.java @@ -17,25 +17,23 @@ package io.bitsquare.app; -import io.bitsquare.AbstractBitsquareModule; +import io.bitsquare.BitsquareModule; import io.bitsquare.btc.BitcoinModule; import io.bitsquare.crypto.CryptoModule; -import io.bitsquare.gui.GuiModule; -import io.bitsquare.msg.DefaultMessageModule; import io.bitsquare.msg.MessageModule; +import io.bitsquare.msg.tomp2p.TomP2PMessageModule; +import io.bitsquare.offer.OfferModule; +import io.bitsquare.offer.tomp2p.TomP2POfferModule; import io.bitsquare.persistence.Persistence; import io.bitsquare.settings.Settings; import io.bitsquare.trade.TradeModule; import io.bitsquare.user.User; -import io.bitsquare.util.ConfigLoader; import com.google.inject.Injector; import com.google.inject.name.Names; import java.util.Properties; -import javafx.stage.Stage; - import net.tomp2p.connection.Ports; import org.slf4j.Logger; @@ -44,19 +42,16 @@ import org.slf4j.LoggerFactory; import akka.actor.ActorSystem; import scala.concurrent.duration.Duration; -public class BitsquareModule extends AbstractBitsquareModule { +/** + * Configures all non-UI modules necessary to run a Bitsquare application. + */ +public class AppModule extends BitsquareModule { + private static final Logger log = LoggerFactory.getLogger(AppModule.class); - private static final Logger log = LoggerFactory.getLogger(BitsquareModule.class); - private final Stage primaryStage; private final String appName; - public BitsquareModule(Stage primaryStage, String appName) { - this(primaryStage, appName, ConfigLoader.loadConfig()); - } - - public BitsquareModule(Stage primaryStage, String appName, Properties properties) { + public AppModule(Properties properties, String appName) { super(properties); - this.primaryStage = primaryStage; this.appName = appName; } @@ -70,7 +65,7 @@ public class BitsquareModule extends AbstractBitsquareModule { install(bitcoinModule()); install(cryptoModule()); install(tradeModule()); - install(guiModule()); + install(offerModule()); bindConstant().annotatedWith(Names.named("appName")).to(appName); bind(ActorSystem.class).toInstance(ActorSystem.create(appName)); @@ -80,7 +75,7 @@ public class BitsquareModule extends AbstractBitsquareModule { } protected MessageModule messageModule() { - return new DefaultMessageModule(properties); + return new TomP2PMessageModule(properties); } protected BitcoinModule bitcoinModule() { @@ -95,9 +90,7 @@ public class BitsquareModule extends AbstractBitsquareModule { return new TradeModule(properties); } - protected GuiModule guiModule() { - return new GuiModule(properties, primaryStage); - } + protected OfferModule offerModule() { return new TomP2POfferModule(properties); } @Override protected void doClose(Injector injector) { diff --git a/src/main/java/io/bitsquare/app/gui/Main.java b/src/main/java/io/bitsquare/app/gui/Main.java index cc8edb5d7b..e35cb8cfad 100644 --- a/src/main/java/io/bitsquare/app/gui/Main.java +++ b/src/main/java/io/bitsquare/app/gui/Main.java @@ -18,7 +18,6 @@ package io.bitsquare.app.gui; import io.bitsquare.app.ArgumentParser; -import io.bitsquare.app.BitsquareModule; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.SystemTray; import io.bitsquare.gui.ViewLoader; @@ -51,7 +50,7 @@ public class Main extends Application { private static final Logger log = LoggerFactory.getLogger(Main.class); private static String appName = "Bitsquare"; - private BitsquareModule bitsquareModule; + private MainModule mainModule; private Injector injector; public static void main(String[] args) { @@ -67,8 +66,8 @@ public class Main extends Application { @Override public void start(Stage primaryStage) { - bitsquareModule = new BitsquareModule(primaryStage, appName); - injector = Guice.createInjector(bitsquareModule); + mainModule = new MainModule(appName, primaryStage); + injector = Guice.createInjector(mainModule); // route uncaught exceptions to a user-facing dialog @@ -138,7 +137,7 @@ public class Main extends Application { @Override public void stop() { - bitsquareModule.close(injector); + mainModule.close(injector); System.exit(0); } } diff --git a/src/main/java/io/bitsquare/app/gui/MainModule.java b/src/main/java/io/bitsquare/app/gui/MainModule.java new file mode 100644 index 0000000000..db57b7779d --- /dev/null +++ b/src/main/java/io/bitsquare/app/gui/MainModule.java @@ -0,0 +1,43 @@ +/* + * 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.BitsquareModule; +import io.bitsquare.app.AppModule; +import io.bitsquare.gui.GuiModule; +import io.bitsquare.util.ConfigLoader; + +import javafx.stage.Stage; + +class MainModule extends BitsquareModule { + + private final String appName; + private final Stage primaryStage; + + public MainModule(String appName, Stage primaryStage) { + super(ConfigLoader.loadConfig()); + this.appName = appName; + this.primaryStage = primaryStage; + } + + @Override + protected void configure() { + install(new AppModule(properties, appName)); + install(new GuiModule(properties, primaryStage)); + } +} diff --git a/src/main/java/io/bitsquare/btc/BitcoinModule.java b/src/main/java/io/bitsquare/btc/BitcoinModule.java index c08f2eb562..c6346f3a49 100644 --- a/src/main/java/io/bitsquare/btc/BitcoinModule.java +++ b/src/main/java/io/bitsquare/btc/BitcoinModule.java @@ -17,7 +17,7 @@ package io.bitsquare.btc; -import io.bitsquare.AbstractBitsquareModule; +import io.bitsquare.BitsquareModule; import org.bitcoinj.core.NetworkParameters; import org.bitcoinj.params.MainNetParams; @@ -28,7 +28,7 @@ import com.google.inject.Injector; import java.util.Properties; -public class BitcoinModule extends AbstractBitsquareModule { +public class BitcoinModule extends BitsquareModule { private static final BitcoinNetwork DEFAULT_NETWORK = BitcoinNetwork.REGTEST; diff --git a/src/main/java/io/bitsquare/crypto/CryptoModule.java b/src/main/java/io/bitsquare/crypto/CryptoModule.java index 4f114b65d1..fc3472c98b 100644 --- a/src/main/java/io/bitsquare/crypto/CryptoModule.java +++ b/src/main/java/io/bitsquare/crypto/CryptoModule.java @@ -17,11 +17,11 @@ package io.bitsquare.crypto; -import io.bitsquare.AbstractBitsquareModule; +import io.bitsquare.BitsquareModule; import java.util.Properties; -public class CryptoModule extends AbstractBitsquareModule { +public class CryptoModule extends BitsquareModule { public CryptoModule(Properties properties) { super(properties); diff --git a/src/main/java/io/bitsquare/gui/GuiModule.java b/src/main/java/io/bitsquare/gui/GuiModule.java index dd39924be1..8491ce60bb 100644 --- a/src/main/java/io/bitsquare/gui/GuiModule.java +++ b/src/main/java/io/bitsquare/gui/GuiModule.java @@ -17,7 +17,7 @@ package io.bitsquare.gui; -import io.bitsquare.AbstractBitsquareModule; +import io.bitsquare.BitsquareModule; import io.bitsquare.gui.components.Popups; import io.bitsquare.gui.main.help.Help; import io.bitsquare.gui.main.trade.offerbook.OfferBook; @@ -32,7 +32,7 @@ import java.util.Properties; import javafx.stage.Stage; -public class GuiModule extends AbstractBitsquareModule { +public class GuiModule extends BitsquareModule { private final Stage primaryStage; diff --git a/src/main/java/io/bitsquare/gui/main/trade/offerbook/OfferBook.java b/src/main/java/io/bitsquare/gui/main/trade/offerbook/OfferBook.java index f9296cd0ee..0bbc0986c8 100644 --- a/src/main/java/io/bitsquare/gui/main/trade/offerbook/OfferBook.java +++ b/src/main/java/io/bitsquare/gui/main/trade/offerbook/OfferBook.java @@ -20,9 +20,8 @@ package io.bitsquare.gui.main.trade.offerbook; import io.bitsquare.bank.BankAccount; import io.bitsquare.locale.Country; import io.bitsquare.locale.CurrencyUtil; -import io.bitsquare.msg.MessageFacade; -import io.bitsquare.msg.listeners.OfferBookListener; import io.bitsquare.offer.Offer; +import io.bitsquare.offer.OfferRepository; import io.bitsquare.user.User; import io.bitsquare.util.Utilities; @@ -44,18 +43,18 @@ import static com.google.common.base.Preconditions.checkArgument; * Holds and manages the unsorted and unfiltered offerbook list of both buy and sell offers. * It is handled as singleton by Guice and is used by 2 instances of OfferBookModel (one for Buy one for Sell). * As it is used only by the Buy and Sell UIs we treat it as local UI model. - * It also use OfferBookListener as the lists items class and we don't want to get any dependency out of the package - * for that. + * It also use OfferRepository.Listener as the lists items class and we don't want to get any dependency out of the + * package for that. */ public class OfferBook { private static final Logger log = LoggerFactory.getLogger(OfferBook.class); - private final MessageFacade messageFacade; + private final OfferRepository offerRepository; private final User user; private final ObservableList offerBookListItems = FXCollections.observableArrayList(); - private final OfferBookListener offerBookListener; + private final OfferRepository.Listener offerRepositoryListener; private final ChangeListener bankAccountChangeListener; private final ChangeListener invalidationListener; private String fiatCode; @@ -69,14 +68,14 @@ public class OfferBook { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - OfferBook(MessageFacade messageFacade, User user) { - this.messageFacade = messageFacade; + OfferBook(OfferRepository offerRepository, User user) { + this.offerRepository = offerRepository; this.user = user; bankAccountChangeListener = (observableValue, oldValue, newValue) -> setBankAccount(newValue); invalidationListener = (ov, oldValue, newValue) -> requestOffers(); - offerBookListener = new OfferBookListener() { + offerRepositoryListener = new OfferRepository.Listener() { @Override public void onOfferAdded(Offer offer) { addOfferToOfferBookListItems(offer); @@ -143,15 +142,15 @@ public class OfferBook { private void addListeners() { log.debug("addListeners "); user.currentBankAccountProperty().addListener(bankAccountChangeListener); - messageFacade.addOfferBookListener(offerBookListener); - messageFacade.invalidationTimestampProperty().addListener(invalidationListener); + offerRepository.addListener(offerRepositoryListener); + offerRepository.invalidationTimestampProperty().addListener(invalidationListener); } private void removeListeners() { log.debug("removeListeners "); user.currentBankAccountProperty().removeListener(bankAccountChangeListener); - messageFacade.removeOfferBookListener(offerBookListener); - messageFacade.invalidationTimestampProperty().removeListener(invalidationListener); + offerRepository.removeListener(offerRepositoryListener); + offerRepository.invalidationTimestampProperty().removeListener(invalidationListener); } private void addOfferToOfferBookListItems(Offer offer) { @@ -161,7 +160,7 @@ public class OfferBook { } private void requestOffers() { - messageFacade.getOffers(fiatCode); + offerRepository.getOffers(fiatCode); } @@ -174,11 +173,11 @@ public class OfferBook { addListeners(); setBankAccount(user.getCurrentBankAccount()); pollingTimer = Utilities.setInterval(3000, (animationTimer) -> { - messageFacade.requestInvalidationTimeStampFromDHT(fiatCode); + offerRepository.requestInvalidationTimeStampFromDHT(fiatCode); return null; }); - messageFacade.getOffers(fiatCode); + offerRepository.getOffers(fiatCode); } private void stopPolling() { diff --git a/src/main/java/io/bitsquare/msg/DefaultMessageModule.java b/src/main/java/io/bitsquare/msg/DefaultMessageModule.java deleted file mode 100644 index 4e1e75c2fe..0000000000 --- a/src/main/java/io/bitsquare/msg/DefaultMessageModule.java +++ /dev/null @@ -1,54 +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.msg; - -import io.bitsquare.AbstractBitsquareModule; -import io.bitsquare.network.BootstrapNodes; -import io.bitsquare.network.Node; - -import com.google.inject.Injector; -import com.google.inject.name.Names; - -import java.util.Properties; - -public class DefaultMessageModule extends AbstractBitsquareModule implements MessageModule { - - public DefaultMessageModule(Properties properties) { - super(properties); - } - - @Override - protected void configure() { - bind(MessageFacade.class).to(TomP2PMessageFacade.class).asEagerSingleton(); - bind(P2PNode.class).asEagerSingleton(); - bind(BootstrappedPeerFactory.class).asEagerSingleton(); - bind(DHTSeedService.class); - - // we will probably later use disk storage instead of memory storage for TomP2P - bind(Boolean.class).annotatedWith(Names.named("useDiskStorage")).toInstance(false); - - bind(Node.class) - .annotatedWith(Names.named("bootstrapNode")) - .toInstance(BootstrapNodes.LOCALHOST); - } - - @Override - protected void doClose(Injector injector) { - injector.getInstance(MessageFacade.class).shutDown(); - } -} diff --git a/src/main/java/io/bitsquare/msg/MessageFacade.java b/src/main/java/io/bitsquare/msg/MessageFacade.java index f6d6de4c7a..1dd9f49868 100644 --- a/src/main/java/io/bitsquare/msg/MessageFacade.java +++ b/src/main/java/io/bitsquare/msg/MessageFacade.java @@ -18,22 +18,17 @@ package io.bitsquare.msg; import io.bitsquare.arbitrator.Arbitrator; -import io.bitsquare.msg.listeners.AddOfferListener; import io.bitsquare.msg.listeners.ArbitratorListener; import io.bitsquare.msg.listeners.BootstrapListener; import io.bitsquare.msg.listeners.GetPeerAddressListener; import io.bitsquare.msg.listeners.IncomingMessageListener; -import io.bitsquare.msg.listeners.OfferBookListener; import io.bitsquare.msg.listeners.OutgoingMessageListener; import io.bitsquare.network.Peer; -import io.bitsquare.offer.Offer; import java.security.PublicKey; import java.util.Locale; -import javafx.beans.property.LongProperty; - public interface MessageFacade extends MessageBroker { void sendMessage(Peer peer, Message message, OutgoingMessageListener listener); @@ -46,25 +41,11 @@ public interface MessageFacade extends MessageBroker { void removeIncomingMessageListener(IncomingMessageListener listener); - void addOffer(Offer offer, AddOfferListener addOfferListener); - void addArbitratorListener(ArbitratorListener listener); void getArbitrators(Locale defaultLanguageLocale); - LongProperty invalidationTimestampProperty(); - - void addOfferBookListener(OfferBookListener offerBookListener); - - void requestInvalidationTimeStampFromDHT(String fiatCode); - - void getOffers(String fiatCode); - - void removeOffer(Offer offer); - void init(int clientPort, BootstrapListener bootstrapListener); void getPeerAddress(PublicKey messagePublicKey, GetPeerAddressListener getPeerAddressListener); - - void removeOfferBookListener(OfferBookListener offerBookListener); } diff --git a/src/main/java/io/bitsquare/msg/MessageModule.java b/src/main/java/io/bitsquare/msg/MessageModule.java index c87f29439d..351fd3a923 100644 --- a/src/main/java/io/bitsquare/msg/MessageModule.java +++ b/src/main/java/io/bitsquare/msg/MessageModule.java @@ -17,7 +17,43 @@ package io.bitsquare.msg; -import com.google.inject.Module; +import io.bitsquare.BitsquareModule; +import io.bitsquare.network.BootstrapNodes; +import io.bitsquare.network.Node; -public interface MessageModule extends Module { +import com.google.inject.Injector; +import com.google.inject.name.Names; + +import java.util.Properties; + +public abstract class MessageModule extends BitsquareModule { + + protected MessageModule(Properties properties) { + super(properties); + } + + @Override + protected final void configure() { + bind(MessageFacade.class).to(messageFacade()).asEagerSingleton(); + bind(DHTSeedService.class); + + // we will probably later use disk storage instead of memory storage for TomP2P + bind(Boolean.class).annotatedWith(Names.named("useDiskStorage")).toInstance(false); + + bind(Node.class) + .annotatedWith(Names.named("bootstrapNode")) + .toInstance(BootstrapNodes.DIGITAL_OCEAN_1); + + doConfigure(); + } + + protected void doConfigure() { + } + + protected abstract Class messageFacade(); + + @Override + protected void doClose(Injector injector) { + injector.getInstance(MessageFacade.class).shutDown(); + } } diff --git a/src/main/java/io/bitsquare/msg/TomP2PMessageFacade.java b/src/main/java/io/bitsquare/msg/TomP2PMessageFacade.java deleted file mode 100644 index a459afe544..0000000000 --- a/src/main/java/io/bitsquare/msg/TomP2PMessageFacade.java +++ /dev/null @@ -1,564 +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.msg; - -import io.bitsquare.arbitrator.Arbitrator; -import io.bitsquare.msg.listeners.AddOfferListener; -import io.bitsquare.msg.listeners.ArbitratorListener; -import io.bitsquare.msg.listeners.BootstrapListener; -import io.bitsquare.msg.listeners.GetPeerAddressListener; -import io.bitsquare.msg.listeners.IncomingMessageListener; -import io.bitsquare.msg.listeners.OfferBookListener; -import io.bitsquare.msg.listeners.OutgoingMessageListener; -import io.bitsquare.network.Peer; -import io.bitsquare.network.tomp2p.TomP2PPeer; -import io.bitsquare.offer.Offer; -import io.bitsquare.user.User; - -import java.io.IOException; - -import java.security.PublicKey; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import javax.inject.Inject; - -import javafx.application.Platform; -import javafx.beans.property.LongProperty; -import javafx.beans.property.SimpleLongProperty; - -import net.tomp2p.dht.FutureGet; -import net.tomp2p.dht.FuturePut; -import net.tomp2p.dht.FutureRemove; -import net.tomp2p.futures.BaseFuture; -import net.tomp2p.futures.BaseFutureAdapter; -import net.tomp2p.futures.BaseFutureListener; -import net.tomp2p.futures.FutureDirect; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.Number640; -import net.tomp2p.storage.Data; -import net.tomp2p.utils.Utils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -/** - * That facade delivers direct messaging and DHT functionality from the TomP2P library - * It is the translating domain specific functionality to the messaging layer. - * The TomP2P library codebase shall not be used outside that facade. - * That way we limit the dependency of the TomP2P library only to that class (and it's sub components). - *

- * TODO: improve callbacks that Platform.runLater is not necessary. We call usually that methods form teh UI thread. - */ -class TomP2PMessageFacade implements MessageFacade { - private static final Logger log = LoggerFactory.getLogger(TomP2PMessageFacade.class); - private static final String ARBITRATORS_ROOT = "ArbitratorsRoot"; - - private final P2PNode p2pNode; - private final User user; - - private final List offerBookListeners = new ArrayList<>(); - private final List arbitratorListeners = new ArrayList<>(); - private final List incomingMessageListeners = new ArrayList<>(); - private final LongProperty invalidationTimestamp = new SimpleLongProperty(0); - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Constructor - /////////////////////////////////////////////////////////////////////////////////////////// - - @Inject - public TomP2PMessageFacade(User user, P2PNode p2pNode) { - this.user = user; - this.p2pNode = p2pNode; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Public Methods - /////////////////////////////////////////////////////////////////////////////////////////// - - public void init(int port, BootstrapListener bootstrapListener) { - p2pNode.setMessageBroker(this); - p2pNode.setKeyPair(user.getMessageKeyPair()); - - p2pNode.start(port, bootstrapListener); - } - - public void shutDown() { - if (p2pNode != null) - p2pNode.shutDown(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Find peer address by publicKey - /////////////////////////////////////////////////////////////////////////////////////////// - - - public void getPeerAddress(PublicKey publicKey, GetPeerAddressListener listener) { - final Number160 locationKey = Utils.makeSHAHash(publicKey.getEncoded()); - FutureGet futureGet = p2pNode.getDomainProtectedData(locationKey, publicKey); - - futureGet.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(BaseFuture baseFuture) throws Exception { - if (isSuccess(baseFuture) && futureGet.data() != null) { - final Peer peer = (Peer) futureGet.data().object(); - Platform.runLater(() -> listener.onResult(peer)); - } - else { - Platform.runLater(listener::onFailed); - } - } - }); - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Offer - /////////////////////////////////////////////////////////////////////////////////////////// - - public void addOffer(Offer offer, AddOfferListener addOfferListener) { - Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode()); - try { - final Data offerData = new Data(offer); - - // the offer is default 30 days valid - int defaultOfferTTL = 30 * 24 * 60 * 60; - offerData.ttlSeconds(defaultOfferTTL); - log.trace("Add offer to DHT requested. Added data: [locationKey: " + locationKey + - ", hash: " + offerData.hash().toString() + "]"); - FuturePut futurePut = p2pNode.addProtectedData(locationKey, offerData); - futurePut.addListener(new BaseFutureListener() { - @Override - public void operationComplete(BaseFuture future) throws Exception { - if (isSuccess(future)) { - Platform.runLater(() -> { - addOfferListener.onComplete(); - offerBookListeners.stream().forEach(listener -> { - try { - Object offerDataObject = offerData.object(); - if (offerDataObject instanceof Offer) { - log.error("Added offer to DHT with ID: " + ((Offer) - offerDataObject).getId()); - listener.onOfferAdded((Offer) offerDataObject); - } - } catch (ClassNotFoundException | IOException e) { - e.printStackTrace(); - log.error("Add offer to DHT failed: " + e.getMessage()); - } - }); - - // TODO will be removed when we don't use polling anymore - writeInvalidationTimestampToDHT(locationKey); - log.trace("Add offer to DHT was successful. Added data: " + - "[locationKey: " + locationKey + - ", value: " + offerData + "]"); - }); - } - else { - Platform.runLater(() -> { - addOfferListener.onFailed("Add offer to DHT failed.", - new Exception("Add offer to DHT failed. Reason: " + future - .failedReason())); - log.error("Add offer to DHT failed. Reason: " + future.failedReason - ()); - }); - } - } - - @Override - public void exceptionCaught(Throwable t) throws Exception { - Platform.runLater(() -> { - addOfferListener.onFailed("Add offer to DHT failed with an exception.", - t); - log.error("Add offer to DHT failed with an exception: " + t.getMessage()); - }); - } - } - - ); - } catch (IOException e) { - Platform.runLater(() -> { - addOfferListener.onFailed("Add offer to DHT failed with an exception.", e); - log.error("Add offer to DHT failed with an exception: " + e.getMessage()); - }); - } - } - - //TODO remove is failing, probably due Coin or Fiat class (was working before) - // objects are identical but returned object form network might have some problem with serialisation? - - public void removeOffer(Offer offer) { - Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode()); - try { - final Data offerData = new Data(offer); - log.trace("Remove offer from DHT requested. Removed data: [locationKey: " + locationKey + - ", hash: " + offerData.hash().toString() + "]"); - FutureRemove futureRemove = p2pNode.removeFromDataMap(locationKey, offerData); - futureRemove.addListener(new BaseFutureListener() { - @Override - public void operationComplete(BaseFuture future) throws Exception { - if (isSuccess(future)) { - Platform.runLater(() -> { - offerBookListeners.stream().forEach(offerBookListener -> { - try { - Object offerDataObject = offerData.object(); - if (offerDataObject instanceof Offer) { - log.trace("Remove offer from DHT was successful. Removed data: [key: " + - locationKey + ", " + - "offer: " + offerDataObject + "]"); - offerBookListener.onOfferRemoved((Offer) offerDataObject); - } - } catch (ClassNotFoundException | IOException e) { - e.printStackTrace(); - log.error("Remove offer from DHT failed. Error: " + e.getMessage()); - } - }); - writeInvalidationTimestampToDHT(locationKey); - }); - } - else { - log.error("Remove offer from DHT failed. Cause: future.isSuccess() = false, locationKey: " + - locationKey + ", Reason: " + future.failedReason()); - } - } - - @Override - public void exceptionCaught(Throwable t) throws Exception { - log.error("Remove offer from DHT failed. Error: " + t.getMessage()); - } - }); - } catch (IOException e) { - e.printStackTrace(); - log.error("Remove offer from DHT failed. Error: " + e.getMessage()); - } - } - - public void getOffers(String currencyCode) { - Number160 locationKey = Number160.createHash(currencyCode); - log.trace("Get offers from DHT requested for locationKey: " + locationKey); - FutureGet futureGet = p2pNode.getDataMap(locationKey); - futureGet.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(BaseFuture baseFuture) throws Exception { - if (isSuccess(baseFuture)) { - final Map dataMap = futureGet.dataMap(); - final List offers = new ArrayList<>(); - if (dataMap != null) { - for (Data offerData : dataMap.values()) { - try { - Object offerDataObject = offerData.object(); - if (offerDataObject instanceof Offer) { - offers.add((Offer) offerDataObject); - } - } catch (ClassNotFoundException | IOException e) { - e.printStackTrace(); - } - } - - Platform.runLater(() -> offerBookListeners.stream().forEach(listener -> - listener.onOffersReceived(offers))); - } - - log.trace("Get offers from DHT was successful. Stored data: [key: " + locationKey - + ", values: " + futureGet.dataMap() + "]"); - } - else { - final Map dataMap = futureGet.dataMap(); - if (dataMap == null || dataMap.size() == 0) { - log.trace("Get offers from DHT delivered empty dataMap."); - Platform.runLater(() -> offerBookListeners.stream().forEach(listener -> - listener.onOffersReceived(new ArrayList<>()))); - } - else { - log.error("Get offers from DHT was not successful with reason:" + baseFuture.failedReason()); - } - } - } - }); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Trade process - /////////////////////////////////////////////////////////////////////////////////////////// - - public void sendMessage(Peer peer, Message message, - OutgoingMessageListener listener) { - if (!(peer instanceof TomP2PPeer)) { - throw new IllegalArgumentException("peer must be of type TomP2PPeer"); - } - FutureDirect futureDirect = p2pNode.sendData(((TomP2PPeer) peer).getPeerAddress(), message); - futureDirect.addListener(new BaseFutureListener() { - @Override - public void operationComplete(BaseFuture future) throws Exception { - if (isSuccess(futureDirect)) { - Platform.runLater(listener::onResult); - } - else { - Platform.runLater(listener::onFailed); - } - } - - @Override - public void exceptionCaught(Throwable t) throws Exception { - Platform.runLater(listener::onFailed); - } - }); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Arbitrators - /////////////////////////////////////////////////////////////////////////////////////////// - - public void addArbitrator(Arbitrator arbitrator) { - Number160 locationKey = Number160.createHash(ARBITRATORS_ROOT); - try { - final Data arbitratorData = new Data(arbitrator); - - FuturePut addFuture = p2pNode.addProtectedData(locationKey, arbitratorData); - addFuture.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(BaseFuture future) throws Exception { - Platform.runLater(() -> arbitratorListeners.stream().forEach(listener -> - { - try { - Object arbitratorDataObject = arbitratorData.object(); - if (arbitratorDataObject instanceof Arbitrator) { - listener.onArbitratorAdded((Arbitrator) arbitratorDataObject); - } - } catch (ClassNotFoundException | IOException e) { - e.printStackTrace(); - log.error(e.toString()); - } - })); - - if (isSuccess(addFuture)) { - log.trace("Add arbitrator to DHT was successful. Stored data: [key: " + locationKey + ", " + - "values: " + arbitratorData + "]"); - } - else { - log.error("Add arbitrator to DHT failed with reason:" + addFuture.failedReason()); - } - } - }); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void removeArbitrator(Arbitrator arbitrator) throws IOException { - Number160 locationKey = Number160.createHash(ARBITRATORS_ROOT); - final Data arbitratorData = new Data(arbitrator); - FutureRemove removeFuture = p2pNode.removeFromDataMap(locationKey, arbitratorData); - removeFuture.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(BaseFuture future) throws Exception { - Platform.runLater(() -> arbitratorListeners.stream().forEach(listener -> - { - for (Data arbitratorData : removeFuture.dataMap().values()) { - try { - Object arbitratorDataObject = arbitratorData.object(); - if (arbitratorDataObject instanceof Arbitrator) { - Arbitrator arbitrator = (Arbitrator) arbitratorDataObject; - listener.onArbitratorRemoved(arbitrator); - } - } catch (ClassNotFoundException | IOException e) { - e.printStackTrace(); - } - } - })); - if (isSuccess(removeFuture)) { - log.trace("Remove arbitrator from DHT was successful. Stored data: [key: " + locationKey + ", " + - "values: " + arbitratorData + "]"); - } - else { - log.error("Remove arbitrators from DHT failed with reason:" + removeFuture.failedReason()); - } - } - }); - } - - public void getArbitrators(Locale languageLocale) { - Number160 locationKey = Number160.createHash(ARBITRATORS_ROOT); - FutureGet futureGet = p2pNode.getDataMap(locationKey); - futureGet.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(BaseFuture baseFuture) throws Exception { - Platform.runLater(() -> arbitratorListeners.stream().forEach(listener -> - { - List arbitrators = new ArrayList<>(); - for (Data arbitratorData : futureGet.dataMap().values()) { - try { - Object arbitratorDataObject = arbitratorData.object(); - if (arbitratorDataObject instanceof Arbitrator) { - arbitrators.add((Arbitrator) arbitratorDataObject); - } - } catch (ClassNotFoundException | IOException e) { - e.printStackTrace(); - log.error("Get arbitrators from DHT failed with exception:" + e.getMessage()); - } - } - - listener.onArbitratorsReceived(arbitrators); - })); - if (isSuccess(baseFuture)) { - log.trace("Get arbitrators from DHT was successful. Stored data: [key: " + locationKey + ", " + - "values: " + futureGet.dataMap() + "]"); - } - else { - log.error("Get arbitrators from DHT failed with reason:" + baseFuture.failedReason()); - } - } - }); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Event Listeners - /////////////////////////////////////////////////////////////////////////////////////////// - - public void addOfferBookListener(OfferBookListener listener) { - offerBookListeners.add(listener); - } - - public void removeOfferBookListener(OfferBookListener listener) { - offerBookListeners.remove(listener); - } - - public void addArbitratorListener(ArbitratorListener listener) { - arbitratorListeners.add(listener); - } - - public void removeArbitratorListener(ArbitratorListener listener) { - arbitratorListeners.remove(listener); - } - - public void addIncomingMessageListener(IncomingMessageListener listener) { - incomingMessageListeners.add(listener); - } - - public void removeIncomingMessageListener(IncomingMessageListener listener) { - incomingMessageListeners.remove(listener); - } - - - /* - * We store the timestamp of any change of the offer list (add, remove offer) and we poll in intervals for changes. - * If we detect a change we request the offer list from the DHT. - * Polling should be replaced by a push based solution later. - */ - - /////////////////////////////////////////////////////////////////////////////////////////// - // Polling - /////////////////////////////////////////////////////////////////////////////////////////// - - private void writeInvalidationTimestampToDHT(Number160 locationKey) { - invalidationTimestamp.set(System.currentTimeMillis()); - try { - FuturePut putFuture = p2pNode.putData(getInvalidatedLocationKey(locationKey), - new Data(invalidationTimestamp.get())); - putFuture.addListener(new BaseFutureListener() { - @Override - public void operationComplete(BaseFuture future) throws Exception { - if (isSuccess(putFuture)) - log.trace("Update invalidationTimestamp to DHT was successful. TimeStamp=" + - invalidationTimestamp.get()); - else - log.error("Update invalidationTimestamp to DHT failed with reason:" + putFuture.failedReason()); - } - - @Override - public void exceptionCaught(Throwable t) throws Exception { - log.error("Update invalidationTimestamp to DHT failed with exception:" + t.getMessage()); - } - }); - } catch (IOException e) { - log.error("Update invalidationTimestamp to DHT failed with exception:" + e.getMessage()); - } - } - - public LongProperty invalidationTimestampProperty() { - return invalidationTimestamp; - } - - public void requestInvalidationTimeStampFromDHT(String currencyCode) { - Number160 locationKey = Number160.createHash(currencyCode); - FutureGet getFuture = p2pNode.getData(getInvalidatedLocationKey(locationKey)); - getFuture.addListener(new BaseFutureListener() { - @Override - public void operationComplete(BaseFuture future) throws Exception { - if (isSuccess(getFuture)) { - Data data = getFuture.data(); - if (data != null && data.object() instanceof Long) { - final Object object = data.object(); - Platform.runLater(() -> { - Long timeStamp = (Long) object; - //log.trace("Get invalidationTimestamp from DHT was successful. TimeStamp=" + timeStamp); - invalidationTimestamp.set(timeStamp); - }); - } - else if (data != null) { - log.error("Get invalidationTimestamp from DHT failed. Data = " + data); - } - } - else if (getFuture.data() == null) { - // OK as nothing is set at the moment - log.trace("Get invalidationTimestamp from DHT returns null. That is ok for the startup."); - } - else { - log.error("Get invalidationTimestamp from DHT failed with reason:" + getFuture.failedReason()); - } - } - - @Override - public void exceptionCaught(Throwable t) throws Exception { - log.error("Get invalidationTimestamp from DHT failed with exception:" + t.getMessage()); - t.printStackTrace(); - } - }); - } - - private Number160 getInvalidatedLocationKey(Number160 locationKey) { - return Number160.createHash(locationKey + "invalidated"); - } - - // Isolate the success handling as there is bug in port forwarding mode - private boolean isSuccess(BaseFuture baseFuture) { - // return baseFuture.isSuccess(); - return true; - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message handler - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void handleMessage(Object message, Peer sender) { - if (message instanceof Message) { - Platform.runLater(() -> incomingMessageListeners.stream().forEach(e -> - e.onMessage((Message) message, sender))); - } - } -} diff --git a/src/main/java/io/bitsquare/msg/BootstrappedPeerFactory.java b/src/main/java/io/bitsquare/msg/tomp2p/BootstrappedPeerFactory.java similarity index 99% rename from src/main/java/io/bitsquare/msg/BootstrappedPeerFactory.java rename to src/main/java/io/bitsquare/msg/tomp2p/BootstrappedPeerFactory.java index df591d90b7..ba92febd6a 100644 --- a/src/main/java/io/bitsquare/msg/BootstrappedPeerFactory.java +++ b/src/main/java/io/bitsquare/msg/tomp2p/BootstrappedPeerFactory.java @@ -15,7 +15,7 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.msg; +package io.bitsquare.msg.tomp2p; import io.bitsquare.network.BootstrapState; import io.bitsquare.network.Node; @@ -65,7 +65,7 @@ import org.slf4j.LoggerFactory; /** * Creates a DHT peer and bootstrap to the network via a seed node */ -public class BootstrappedPeerFactory { +class BootstrappedPeerFactory { private static final Logger log = LoggerFactory.getLogger(BootstrappedPeerFactory.class); private KeyPair keyPair; diff --git a/src/main/java/io/bitsquare/msg/tomp2p/TomP2PMessageFacade.java b/src/main/java/io/bitsquare/msg/tomp2p/TomP2PMessageFacade.java new file mode 100644 index 0000000000..b223884544 --- /dev/null +++ b/src/main/java/io/bitsquare/msg/tomp2p/TomP2PMessageFacade.java @@ -0,0 +1,298 @@ +/* + * 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.msg.tomp2p; + +import io.bitsquare.arbitrator.Arbitrator; +import io.bitsquare.msg.Message; +import io.bitsquare.msg.MessageFacade; +import io.bitsquare.msg.listeners.ArbitratorListener; +import io.bitsquare.msg.listeners.BootstrapListener; +import io.bitsquare.msg.listeners.GetPeerAddressListener; +import io.bitsquare.msg.listeners.IncomingMessageListener; +import io.bitsquare.msg.listeners.OutgoingMessageListener; +import io.bitsquare.network.Peer; +import io.bitsquare.network.tomp2p.TomP2PPeer; +import io.bitsquare.user.User; + +import java.io.IOException; + +import java.security.PublicKey; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import javax.inject.Inject; + +import javafx.application.Platform; + +import net.tomp2p.dht.FutureGet; +import net.tomp2p.dht.FuturePut; +import net.tomp2p.dht.FutureRemove; +import net.tomp2p.futures.BaseFuture; +import net.tomp2p.futures.BaseFutureAdapter; +import net.tomp2p.futures.BaseFutureListener; +import net.tomp2p.futures.FutureDirect; +import net.tomp2p.peers.Number160; +import net.tomp2p.storage.Data; +import net.tomp2p.utils.Utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static io.bitsquare.util.tomp2p.BaseFutureUtil.isSuccess; + + +/** + * That facade delivers direct messaging and DHT functionality from the TomP2P library + * It is the translating domain specific functionality to the messaging layer. + * The TomP2P library codebase shall not be used outside that facade. + * That way we limit the dependency of the TomP2P library only to that class (and it's sub components). + *

+ * TODO: improve callbacks that Platform.runLater is not necessary. We call usually that methods form teh UI thread. + */ +class TomP2PMessageFacade implements MessageFacade { + private static final Logger log = LoggerFactory.getLogger(TomP2PMessageFacade.class); + private static final String ARBITRATORS_ROOT = "ArbitratorsRoot"; + + private final TomP2PNode p2pNode; + private final User user; + + private final List arbitratorListeners = new ArrayList<>(); + private final List incomingMessageListeners = new ArrayList<>(); + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Constructor + /////////////////////////////////////////////////////////////////////////////////////////// + + @Inject + public TomP2PMessageFacade(User user, TomP2PNode p2pNode) { + this.user = user; + this.p2pNode = p2pNode; + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Public Methods + /////////////////////////////////////////////////////////////////////////////////////////// + + public void init(int port, BootstrapListener bootstrapListener) { + p2pNode.setMessageBroker(this); + p2pNode.setKeyPair(user.getMessageKeyPair()); + + p2pNode.start(port, bootstrapListener); + } + + public void shutDown() { + if (p2pNode != null) + p2pNode.shutDown(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Find peer address by publicKey + /////////////////////////////////////////////////////////////////////////////////////////// + + + public void getPeerAddress(PublicKey publicKey, GetPeerAddressListener listener) { + final Number160 locationKey = Utils.makeSHAHash(publicKey.getEncoded()); + FutureGet futureGet = p2pNode.getDomainProtectedData(locationKey, publicKey); + + futureGet.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(BaseFuture baseFuture) throws Exception { + if (isSuccess(baseFuture) && futureGet.data() != null) { + final Peer peer = (Peer) futureGet.data().object(); + Platform.runLater(() -> listener.onResult(peer)); + } + else { + Platform.runLater(listener::onFailed); + } + } + }); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Trade process + /////////////////////////////////////////////////////////////////////////////////////////// + + public void sendMessage(Peer peer, Message message, + OutgoingMessageListener listener) { + if (!(peer instanceof TomP2PPeer)) { + throw new IllegalArgumentException("peer must be of type TomP2PPeer"); + } + FutureDirect futureDirect = p2pNode.sendData(((TomP2PPeer) peer).getPeerAddress(), message); + futureDirect.addListener(new BaseFutureListener() { + @Override + public void operationComplete(BaseFuture future) throws Exception { + if (isSuccess(futureDirect)) { + Platform.runLater(listener::onResult); + } + else { + Platform.runLater(listener::onFailed); + } + } + + @Override + public void exceptionCaught(Throwable t) throws Exception { + Platform.runLater(listener::onFailed); + } + }); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Arbitrators + /////////////////////////////////////////////////////////////////////////////////////////// + + public void addArbitrator(Arbitrator arbitrator) { + Number160 locationKey = Number160.createHash(ARBITRATORS_ROOT); + try { + final Data arbitratorData = new Data(arbitrator); + + FuturePut addFuture = p2pNode.addProtectedData(locationKey, arbitratorData); + addFuture.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(BaseFuture future) throws Exception { + Platform.runLater(() -> arbitratorListeners.stream().forEach(listener -> + { + try { + Object arbitratorDataObject = arbitratorData.object(); + if (arbitratorDataObject instanceof Arbitrator) { + listener.onArbitratorAdded((Arbitrator) arbitratorDataObject); + } + } catch (ClassNotFoundException | IOException e) { + e.printStackTrace(); + log.error(e.toString()); + } + })); + + if (isSuccess(addFuture)) { + log.trace("Add arbitrator to DHT was successful. Stored data: [key: " + locationKey + ", " + + "values: " + arbitratorData + "]"); + } + else { + log.error("Add arbitrator to DHT failed with reason:" + addFuture.failedReason()); + } + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void removeArbitrator(Arbitrator arbitrator) throws IOException { + Number160 locationKey = Number160.createHash(ARBITRATORS_ROOT); + final Data arbitratorData = new Data(arbitrator); + FutureRemove removeFuture = p2pNode.removeFromDataMap(locationKey, arbitratorData); + removeFuture.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(BaseFuture future) throws Exception { + Platform.runLater(() -> arbitratorListeners.stream().forEach(listener -> + { + for (Data arbitratorData : removeFuture.dataMap().values()) { + try { + Object arbitratorDataObject = arbitratorData.object(); + if (arbitratorDataObject instanceof Arbitrator) { + Arbitrator arbitrator = (Arbitrator) arbitratorDataObject; + listener.onArbitratorRemoved(arbitrator); + } + } catch (ClassNotFoundException | IOException e) { + e.printStackTrace(); + } + } + })); + if (isSuccess(removeFuture)) { + log.trace("Remove arbitrator from DHT was successful. Stored data: [key: " + locationKey + ", " + + "values: " + arbitratorData + "]"); + } + else { + log.error("Remove arbitrators from DHT failed with reason:" + removeFuture.failedReason()); + } + } + }); + } + + public void getArbitrators(Locale languageLocale) { + Number160 locationKey = Number160.createHash(ARBITRATORS_ROOT); + FutureGet futureGet = p2pNode.getDataMap(locationKey); + futureGet.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(BaseFuture baseFuture) throws Exception { + Platform.runLater(() -> arbitratorListeners.stream().forEach(listener -> + { + List arbitrators = new ArrayList<>(); + for (Data arbitratorData : futureGet.dataMap().values()) { + try { + Object arbitratorDataObject = arbitratorData.object(); + if (arbitratorDataObject instanceof Arbitrator) { + arbitrators.add((Arbitrator) arbitratorDataObject); + } + } catch (ClassNotFoundException | IOException e) { + e.printStackTrace(); + log.error("Get arbitrators from DHT failed with exception:" + e.getMessage()); + } + } + + listener.onArbitratorsReceived(arbitrators); + })); + if (isSuccess(baseFuture)) { + log.trace("Get arbitrators from DHT was successful. Stored data: [key: " + locationKey + ", " + + "values: " + futureGet.dataMap() + "]"); + } + else { + log.error("Get arbitrators from DHT failed with reason:" + baseFuture.failedReason()); + } + } + }); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Event Listeners + /////////////////////////////////////////////////////////////////////////////////////////// + + public void addArbitratorListener(ArbitratorListener listener) { + arbitratorListeners.add(listener); + } + + public void removeArbitratorListener(ArbitratorListener listener) { + arbitratorListeners.remove(listener); + } + + public void addIncomingMessageListener(IncomingMessageListener listener) { + incomingMessageListeners.add(listener); + } + + public void removeIncomingMessageListener(IncomingMessageListener listener) { + incomingMessageListeners.remove(listener); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message handler + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void handleMessage(Object message, Peer sender) { + if (message instanceof Message) { + Platform.runLater(() -> incomingMessageListeners.stream().forEach(e -> + e.onMessage((Message) message, sender))); + } + } +} diff --git a/src/main/java/io/bitsquare/msg/tomp2p/TomP2PMessageModule.java b/src/main/java/io/bitsquare/msg/tomp2p/TomP2PMessageModule.java new file mode 100644 index 0000000000..3e31154074 --- /dev/null +++ b/src/main/java/io/bitsquare/msg/tomp2p/TomP2PMessageModule.java @@ -0,0 +1,41 @@ +/* + * 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.msg.tomp2p; + +import io.bitsquare.msg.MessageFacade; +import io.bitsquare.msg.MessageModule; + +import java.util.Properties; + +public class TomP2PMessageModule extends MessageModule { + + public TomP2PMessageModule(Properties properties) { + super(properties); + } + + @Override + protected void doConfigure() { + bind(TomP2PNode.class).asEagerSingleton(); + bind(BootstrappedPeerFactory.class).asEagerSingleton(); + } + + @Override + protected Class messageFacade() { + return TomP2PMessageFacade.class; + } +} diff --git a/src/main/java/io/bitsquare/msg/P2PNode.java b/src/main/java/io/bitsquare/msg/tomp2p/TomP2PNode.java similarity index 96% rename from src/main/java/io/bitsquare/msg/P2PNode.java rename to src/main/java/io/bitsquare/msg/tomp2p/TomP2PNode.java index 58ae953cec..c186428e7c 100644 --- a/src/main/java/io/bitsquare/msg/P2PNode.java +++ b/src/main/java/io/bitsquare/msg/tomp2p/TomP2PNode.java @@ -15,8 +15,9 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.msg; +package io.bitsquare.msg.tomp2p; +import io.bitsquare.msg.MessageBroker; import io.bitsquare.msg.listeners.BootstrapListener; import io.bitsquare.network.tomp2p.TomP2PPeer; @@ -66,14 +67,16 @@ import org.slf4j.LoggerFactory; import lighthouse.files.AppDirectory; +import static io.bitsquare.util.tomp2p.BaseFutureUtil.isSuccess; + /** * The fully bootstrapped P2PNode which is responsible himself for his availability in the messaging system. It saves * for instance the IP address periodically. * This class is offering generic functionality of TomP2P needed for Bitsquare, like data and domain protection. * It does not handle any domain aspects of Bitsquare. */ -public class P2PNode { - private static final Logger log = LoggerFactory.getLogger(P2PNode.class); +public class TomP2PNode { + private static final Logger log = LoggerFactory.getLogger(TomP2PNode.class); private KeyPair keyPair; private final Boolean useDiskStorage; @@ -90,14 +93,14 @@ public class P2PNode { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public P2PNode(BootstrappedPeerFactory bootstrappedPeerFactory, - @Named("useDiskStorage") Boolean useDiskStorage) { + public TomP2PNode(BootstrappedPeerFactory bootstrappedPeerFactory, + @Named("useDiskStorage") Boolean useDiskStorage) { this.bootstrappedPeerFactory = bootstrappedPeerFactory; this.useDiskStorage = useDiskStorage; } // for unit testing - P2PNode(KeyPair keyPair, PeerDHT peerDHT) { + TomP2PNode(KeyPair keyPair, PeerDHT peerDHT) { this.keyPair = keyPair; this.peerDHT = peerDHT; peerDHT.peerBean().keyPair(keyPair); @@ -309,7 +312,7 @@ public class P2PNode { public void onSuccess(@Nullable PeerDHT peerDHT) { try { if (peerDHT != null) { - P2PNode.this.peerDHT = peerDHT; + TomP2PNode.this.peerDHT = peerDHT; setupReplyHandler(); FuturePut futurePut = storePeerAddress(); futurePut.addListener(new BaseFutureListener() { @@ -400,10 +403,4 @@ public class P2PNode { storage = new StorageMemory(); } } - - // Isolate the success handling as there is bug in port forwarding mode - private boolean isSuccess(BaseFuture baseFuture) { - // return baseFuture.isSuccess(); - return true; - } } diff --git a/src/main/java/io/bitsquare/offer/Offer.java b/src/main/java/io/bitsquare/offer/Offer.java index 8cfa2940e4..e439a78271 100644 --- a/src/main/java/io/bitsquare/offer/Offer.java +++ b/src/main/java/io/bitsquare/offer/Offer.java @@ -34,6 +34,9 @@ import java.util.Date; import java.util.List; import java.util.Locale; +import static com.google.common.base.Preconditions.*; +import static io.bitsquare.btc.Restrictions.MIN_TRADE_AMOUNT; + //TODO flatten down? public class Offer implements Serializable { @@ -194,6 +197,37 @@ public class Offer implements Serializable { return bankAccountUID; } + public Date getCreationDate() { + return creationDate; + } + + public void validate() throws Exception { + checkNotNull(getAcceptedCountries(), "AcceptedCountries is null"); + checkNotNull(getAcceptedLanguageLocales(), "AcceptedLanguageLocales is null"); + checkNotNull(getAmount(), "Amount is null"); + checkNotNull(getArbitrators(), "Arbitrator is null"); + checkNotNull(getBankAccountId(), "BankAccountId is null"); + checkNotNull(getSecurityDeposit(), "SecurityDeposit is null"); + checkNotNull(getCreationDate(), "CreationDate is null"); + checkNotNull(getCurrency(), "Currency is null"); + checkNotNull(getDirection(), "Direction is null"); + checkNotNull(getId(), "Id is null"); + checkNotNull(getMessagePublicKey(), "MessagePublicKey is null"); + checkNotNull(getMinAmount(), "MinAmount is null"); + checkNotNull(getPrice(), "Price is null"); + + checkArgument(getMinAmount().compareTo(MIN_TRADE_AMOUNT) >= 0, "MinAmount is less then " + MIN_TRADE_AMOUNT); + checkArgument(getAmount().compareTo(MIN_TRADE_AMOUNT) >= 0, "Amount is less then " + MIN_TRADE_AMOUNT); + checkArgument(getAmount().compareTo(getMinAmount()) >= 0, "MinAmount is larger then Amount"); + checkArgument(getSecurityDeposit().isPositive(), "SecurityDeposit is not positive"); + checkArgument(getPrice().isPositive(), "Price is 0 or negative"); + + // TODO check balance + // securityDeposit + // Coin totalsToFund + // getAddressInfoByTradeID(offerId) + // TODO when offer is flattened continue here... + } @Override public String toString() { @@ -215,9 +249,4 @@ public class Offer implements Serializable { ", arbitrator=" + arbitrators + '}'; } - - - public Date getCreationDate() { - return creationDate; - } } diff --git a/src/main/java/io/bitsquare/offer/OfferModule.java b/src/main/java/io/bitsquare/offer/OfferModule.java new file mode 100644 index 0000000000..a83627f92e --- /dev/null +++ b/src/main/java/io/bitsquare/offer/OfferModule.java @@ -0,0 +1,36 @@ +/* + * 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.offer; + +import io.bitsquare.BitsquareModule; + +import java.util.Properties; + +public abstract class OfferModule extends BitsquareModule { + + protected OfferModule(Properties properties) { + super(properties); + } + + @Override + protected void configure() { + bind(OfferRepository.class).to(offerRepository()).asEagerSingleton(); + } + + protected abstract Class offerRepository(); +} diff --git a/src/main/java/io/bitsquare/offer/OfferRepository.java b/src/main/java/io/bitsquare/offer/OfferRepository.java new file mode 100644 index 0000000000..2b8c60f0c7 --- /dev/null +++ b/src/main/java/io/bitsquare/offer/OfferRepository.java @@ -0,0 +1,50 @@ +/* + * 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.offer; + +import io.bitsquare.util.task.FaultHandler; +import io.bitsquare.util.task.ResultHandler; + +import java.util.List; + +import javafx.beans.property.LongProperty; + +public interface OfferRepository { + + void getOffers(String fiatCode); + + void addOffer(Offer offer, ResultHandler resultHandler, FaultHandler faultHandler); + + void removeOffer(Offer offer); + + void addListener(Listener listener); + + void removeListener(Listener listener); + + LongProperty invalidationTimestampProperty(); + + void requestInvalidationTimeStampFromDHT(String fiatCode); + + interface Listener { + void onOfferAdded(Offer offer); + + void onOffersReceived(List offers); + + void onOfferRemoved(Offer offer); + } +} diff --git a/src/main/java/io/bitsquare/msg/listeners/OfferBookListener.java b/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferModule.java similarity index 62% rename from src/main/java/io/bitsquare/msg/listeners/OfferBookListener.java rename to src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferModule.java index 8a6edae6dc..fb7e3729ad 100644 --- a/src/main/java/io/bitsquare/msg/listeners/OfferBookListener.java +++ b/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferModule.java @@ -15,16 +15,21 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.msg.listeners; +package io.bitsquare.offer.tomp2p; -import io.bitsquare.offer.Offer; +import io.bitsquare.offer.OfferModule; +import io.bitsquare.offer.OfferRepository; -import java.util.List; +import java.util.Properties; -public interface OfferBookListener { - void onOfferAdded(Offer offer); +public class TomP2POfferModule extends OfferModule { - void onOffersReceived(List offers); + public TomP2POfferModule(Properties properties) { + super(properties); + } - void onOfferRemoved(Offer offer); -} \ No newline at end of file + @Override + public Class offerRepository() { + return TomP2POfferRepository.class; + } +} diff --git a/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferRepository.java b/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferRepository.java new file mode 100644 index 0000000000..86f8ea1061 --- /dev/null +++ b/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferRepository.java @@ -0,0 +1,296 @@ +/* + * 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.offer.tomp2p; + +import io.bitsquare.msg.tomp2p.TomP2PNode; +import io.bitsquare.offer.Offer; +import io.bitsquare.offer.OfferRepository; +import io.bitsquare.util.task.FaultHandler; +import io.bitsquare.util.task.ResultHandler; + +import java.io.IOException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; + +import javafx.application.Platform; +import javafx.beans.property.LongProperty; +import javafx.beans.property.SimpleLongProperty; + +import net.tomp2p.dht.FutureGet; +import net.tomp2p.dht.FuturePut; +import net.tomp2p.dht.FutureRemove; +import net.tomp2p.futures.BaseFuture; +import net.tomp2p.futures.BaseFutureAdapter; +import net.tomp2p.futures.BaseFutureListener; +import net.tomp2p.peers.Number160; +import net.tomp2p.peers.Number640; +import net.tomp2p.storage.Data; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static io.bitsquare.util.tomp2p.BaseFutureUtil.isSuccess; + +class TomP2POfferRepository implements OfferRepository { + + private static final Logger log = LoggerFactory.getLogger(TomP2POfferRepository.class); + + private final List offerRepositoryListeners = new ArrayList<>(); + private final LongProperty invalidationTimestamp = new SimpleLongProperty(0); + + private final TomP2PNode p2pNode; + + @Inject + public TomP2POfferRepository(TomP2PNode p2pNode) { + this.p2pNode = p2pNode; + } + + @Override + public void addOffer(Offer offer, ResultHandler resultHandler, FaultHandler faultHandler) { + Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode()); + try { + final Data offerData = new Data(offer); + + // the offer is default 30 days valid + int defaultOfferTTL = 30 * 24 * 60 * 60; + offerData.ttlSeconds(defaultOfferTTL); + log.trace("Add offer to DHT requested. Added data: [locationKey: " + locationKey + + ", hash: " + offerData.hash().toString() + "]"); + FuturePut futurePut = p2pNode.addProtectedData(locationKey, offerData); + futurePut.addListener(new BaseFutureListener() { + @Override + public void operationComplete(BaseFuture future) throws Exception { + if (isSuccess(future)) { + Platform.runLater(() -> { + resultHandler.handleResult(); + offerRepositoryListeners.stream().forEach(listener -> { + try { + Object offerDataObject = offerData.object(); + if (offerDataObject instanceof Offer) { + log.error("Added offer to DHT with ID: " + offerDataObject); + listener.onOfferAdded((Offer) offerDataObject); + } + } catch (ClassNotFoundException | IOException e) { + e.printStackTrace(); + log.error("Add offer to DHT failed: " + e.getMessage()); + } + }); + + writeInvalidationTimestampToDHT(locationKey); + log.trace("Add offer to DHT was successful. Added data: [locationKey: " + locationKey + + ", value: " + offerData + "]"); + }); + } + } + + @Override + public void exceptionCaught(Throwable ex) throws Exception { + Platform.runLater(() -> { + faultHandler.handleFault("Failed to add offer to DHT", ex); + }); + } + }); + } catch (IOException ex) { + Platform.runLater(() -> { + faultHandler.handleFault("Failed to add offer to DHT", ex); + }); + } + } + + //TODO remove is failing, probably due Coin or Fiat class (was working before) + // objects are identical but returned object form network might have some problem with serialisation? + public void removeOffer(Offer offer) { + Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode()); + try { + final Data offerData = new Data(offer); + log.trace("Remove offer from DHT requested. Removed data: [locationKey: " + locationKey + + ", hash: " + offerData.hash().toString() + "]"); + FutureRemove futureRemove = p2pNode.removeFromDataMap(locationKey, offerData); + futureRemove.addListener(new BaseFutureListener() { + @Override + public void operationComplete(BaseFuture future) throws Exception { + if (isSuccess(future)) { + Platform.runLater(() -> { + offerRepositoryListeners.stream().forEach(listener -> { + try { + Object offerDataObject = offerData.object(); + if (offerDataObject instanceof Offer) { + log.trace("Remove offer from DHT was successful. Removed data: [key: " + + locationKey + ", " + + "offer: " + (Offer) offerDataObject + "]"); + listener.onOfferRemoved((Offer) offerDataObject); + } + } catch (ClassNotFoundException | IOException e) { + e.printStackTrace(); + log.error("Remove offer from DHT failed. Error: " + e.getMessage()); + } + }); + writeInvalidationTimestampToDHT(locationKey); + }); + } + } + + @Override + public void exceptionCaught(Throwable t) throws Exception { + log.error("Remove offer from DHT failed. Error: " + t.getMessage()); + } + }); + } catch (IOException e) { + e.printStackTrace(); + log.error("Remove offer from DHT failed. Error: " + e.getMessage()); + } + } + + public void getOffers(String currencyCode) { + Number160 locationKey = Number160.createHash(currencyCode); + log.trace("Get offers from DHT requested for locationKey: " + locationKey); + FutureGet futureGet = p2pNode.getDataMap(locationKey); + futureGet.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(BaseFuture baseFuture) throws Exception { + if (isSuccess(baseFuture)) { + final Map dataMap = futureGet.dataMap(); + final List offers = new ArrayList<>(); + if (dataMap != null) { + for (Data offerData : dataMap.values()) { + try { + Object offerDataObject = offerData.object(); + if (offerDataObject instanceof Offer) { + offers.add((Offer) offerDataObject); + } + } catch (ClassNotFoundException | IOException e) { + e.printStackTrace(); + } + } + + Platform.runLater(() -> offerRepositoryListeners.stream().forEach(listener -> + listener.onOffersReceived(offers))); + } + + log.trace("Get offers from DHT was successful. Stored data: [key: " + locationKey + + ", values: " + futureGet.dataMap() + "]"); + } + else { + final Map dataMap = futureGet.dataMap(); + if (dataMap == null || dataMap.size() == 0) { + log.trace("Get offers from DHT delivered empty dataMap."); + Platform.runLater(() -> offerRepositoryListeners.stream().forEach(listener -> + listener.onOffersReceived(new ArrayList<>()))); + } + else { + log.error("Get offers from DHT was not successful with reason:" + baseFuture.failedReason()); + } + } + } + }); + } + + @Override + public void addListener(Listener listener) { + offerRepositoryListeners.add(listener); + } + + @Override + public void removeListener(Listener listener) { + offerRepositoryListeners.remove(listener); + } + + /* + * We store the timestamp of any change of the offer list (add, remove offer) and we poll + * in intervals for changes. If we detect a change we request the offer list from the DHT. + * Polling should be replaced by a push based solution later. + */ + + /////////////////////////////////////////////////////////////////////////////////////////// + // Polling + /////////////////////////////////////////////////////////////////////////////////////////// + + private void writeInvalidationTimestampToDHT(Number160 locationKey) { + invalidationTimestamp.set(System.currentTimeMillis()); + try { + FuturePut putFuture = p2pNode.putData(getInvalidatedLocationKey(locationKey), + new Data(invalidationTimestamp.get())); + putFuture.addListener(new BaseFutureListener() { + @Override + public void operationComplete(BaseFuture future) throws Exception { + if (isSuccess(putFuture)) + log.trace("Update invalidationTimestamp to DHT was successful. TimeStamp=" + + invalidationTimestamp.get()); + else + log.error("Update invalidationTimestamp to DHT failed with reason:" + putFuture.failedReason()); + } + + @Override + public void exceptionCaught(Throwable t) throws Exception { + log.error("Update invalidationTimestamp to DHT failed with exception:" + t.getMessage()); + } + }); + } catch (IOException e) { + log.error("Update invalidationTimestamp to DHT failed with exception:" + e.getMessage()); + } + } + + public LongProperty invalidationTimestampProperty() { + return invalidationTimestamp; + } + + public void requestInvalidationTimeStampFromDHT(String currencyCode) { + Number160 locationKey = Number160.createHash(currencyCode); + FutureGet getFuture = p2pNode.getData(getInvalidatedLocationKey(locationKey)); + getFuture.addListener(new BaseFutureListener() { + @Override + public void operationComplete(BaseFuture future) throws Exception { + if (isSuccess(getFuture)) { + Data data = getFuture.data(); + if (data != null && data.object() instanceof Long) { + final Object object = data.object(); + Platform.runLater(() -> { + Long timeStamp = (Long) object; + //log.trace("Get invalidationTimestamp from DHT was successful. TimeStamp=" + timeStamp); + invalidationTimestamp.set(timeStamp); + }); + } + else if (data != null) { + log.error("Get invalidationTimestamp from DHT failed. Data = " + data); + } + } + else if (getFuture.data() == null) { + // OK as nothing is set at the moment + // log.trace("Get invalidationTimestamp from DHT returns null. That is ok for the startup."); + } + else { + log.error("Get invalidationTimestamp from DHT failed with reason:" + getFuture.failedReason()); + } + } + + @Override + public void exceptionCaught(Throwable t) throws Exception { + log.error("Get invalidationTimestamp from DHT failed with exception:" + t.getMessage()); + t.printStackTrace(); + } + }); + } + + private Number160 getInvalidatedLocationKey(Number160 locationKey) { + return Number160.createHash(locationKey + "invalidated"); + } +} diff --git a/src/main/java/io/bitsquare/trade/TradeManager.java b/src/main/java/io/bitsquare/trade/TradeManager.java index 7956036edb..1d9d7d7dc4 100644 --- a/src/main/java/io/bitsquare/trade/TradeManager.java +++ b/src/main/java/io/bitsquare/trade/TradeManager.java @@ -25,9 +25,9 @@ import io.bitsquare.msg.MessageFacade; import io.bitsquare.network.Peer; import io.bitsquare.offer.Direction; import io.bitsquare.offer.Offer; +import io.bitsquare.offer.OfferRepository; import io.bitsquare.persistence.Persistence; import io.bitsquare.settings.Settings; -import io.bitsquare.trade.handlers.ErrorMessageHandler; import io.bitsquare.trade.handlers.TransactionResultHandler; import io.bitsquare.trade.protocol.createoffer.CreateOfferCoordinator; import io.bitsquare.trade.protocol.trade.TradeMessage; @@ -44,6 +44,7 @@ import io.bitsquare.trade.protocol.trade.taker.messages.RequestOffererPublishDep import io.bitsquare.trade.protocol.trade.taker.messages.RequestTakeOfferMessage; import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage; import io.bitsquare.user.User; +import io.bitsquare.util.task.ErrorMessageHandler; import org.bitcoinj.core.Coin; import org.bitcoinj.core.Transaction; @@ -78,11 +79,11 @@ public class TradeManager { private final BlockChainFacade blockChainFacade; private final WalletFacade walletFacade; private final CryptoFacade cryptoFacade; + private final OfferRepository offerRepository; //TODO store TakerAsSellerProtocol in trade private final Map takerAsSellerProtocolMap = new HashMap<>(); private final Map offererAsBuyerProtocolMap = new HashMap<>(); - private final Map createOfferCoordinatorMap = new HashMap<>(); private final ObservableMap offers = FXCollections.observableHashMap(); private final ObservableMap pendingTrades = FXCollections.observableHashMap(); @@ -99,7 +100,8 @@ public class TradeManager { @Inject public TradeManager(User user, Settings settings, Persistence persistence, MessageFacade messageFacade, - BlockChainFacade blockChainFacade, WalletFacade walletFacade, CryptoFacade cryptoFacade) { + BlockChainFacade blockChainFacade, WalletFacade walletFacade, CryptoFacade cryptoFacade, + OfferRepository offerRepository) { this.user = user; this.settings = settings; this.persistence = persistence; @@ -107,6 +109,7 @@ public class TradeManager { this.blockChainFacade = blockChainFacade; this.walletFacade = walletFacade; this.cryptoFacade = cryptoFacade; + this.offerRepository = offerRepository; Object offersObject = persistence.read(this, "offers"); if (offersObject instanceof Map) { @@ -163,36 +166,23 @@ public class TradeManager { settings.getAcceptedCountries(), settings.getAcceptedLanguageLocales()); - if (createOfferCoordinatorMap.containsKey(offer.getId())) { - errorMessageHandler.onFault("A createOfferCoordinator for the offer with the id " + offer.getId() + " " + - "already exists."); - } - else { - CreateOfferCoordinator createOfferCoordinator = new CreateOfferCoordinator(persistence, - offer, - walletFacade, - messageFacade, - (transactionId) -> { - try { - offer.setOfferFeePaymentTxID(transactionId.getHashAsString()); - addOffer(offer); - createOfferCoordinatorMap.remove(offer.getId()); + CreateOfferCoordinator createOfferCoordinator = new CreateOfferCoordinator( + offer, + walletFacade, + (transactionId) -> { + try { + offer.setOfferFeePaymentTxID(transactionId.getHashAsString()); + addOffer(offer); + resultHandler.onResult(transactionId); + } catch (Exception e) { + errorMessageHandler.handleErrorMessage("Could not save offer. Reason: " + + (e.getCause() != null ? e.getCause().getMessage() : e.toString())); + } + }, + (message, throwable) -> errorMessageHandler.handleErrorMessage(message), + offerRepository); - resultHandler.onResult(transactionId); - } catch (Exception e) { - //TODO retry policy - errorMessageHandler.onFault("Could not save offer. Reason: " + - (e.getCause() != null ? e.getCause().getMessage() : e.toString())); - createOfferCoordinatorMap.remove(offer.getId()); - } - }, - (message, throwable) -> { - errorMessageHandler.onFault(message); - createOfferCoordinatorMap.remove(offer.getId()); - }); - createOfferCoordinatorMap.put(offer.getId(), createOfferCoordinator); - createOfferCoordinator.start(); - } + createOfferCoordinator.start(); } private void addOffer(Offer offer) { @@ -210,7 +200,7 @@ public class TradeManager { offers.remove(offer.getId()); persistOffers(); - messageFacade.removeOffer(offer); + offerRepository.removeOffer(offer); } diff --git a/src/main/java/io/bitsquare/trade/TradeModule.java b/src/main/java/io/bitsquare/trade/TradeModule.java index 3ccd4fc18c..626e01e6ce 100644 --- a/src/main/java/io/bitsquare/trade/TradeModule.java +++ b/src/main/java/io/bitsquare/trade/TradeModule.java @@ -17,11 +17,11 @@ package io.bitsquare.trade; -import io.bitsquare.AbstractBitsquareModule; +import io.bitsquare.BitsquareModule; import java.util.Properties; -public class TradeModule extends AbstractBitsquareModule { +public class TradeModule extends BitsquareModule { public TradeModule(Properties properties) { super(properties); diff --git a/src/main/java/io/bitsquare/trade/protocol/createoffer/CreateOfferCoordinator.java b/src/main/java/io/bitsquare/trade/protocol/createoffer/CreateOfferCoordinator.java index 4e17d6d897..c9bd515b22 100644 --- a/src/main/java/io/bitsquare/trade/protocol/createoffer/CreateOfferCoordinator.java +++ b/src/main/java/io/bitsquare/trade/protocol/createoffer/CreateOfferCoordinator.java @@ -18,157 +18,89 @@ package io.bitsquare.trade.protocol.createoffer; import io.bitsquare.btc.WalletFacade; -import io.bitsquare.msg.MessageFacade; import io.bitsquare.offer.Offer; -import io.bitsquare.persistence.Persistence; -import io.bitsquare.trade.handlers.FaultHandler; +import io.bitsquare.offer.OfferRepository; import io.bitsquare.trade.handlers.TransactionResultHandler; -import io.bitsquare.trade.protocol.createoffer.tasks.BroadCastOfferFeeTx; -import io.bitsquare.trade.protocol.createoffer.tasks.CreateOfferFeeTx; -import io.bitsquare.trade.protocol.createoffer.tasks.PublishOfferToDHT; -import io.bitsquare.trade.protocol.createoffer.tasks.VerifyOffer; +import io.bitsquare.util.task.FaultHandler; +import org.bitcoinj.core.InsufficientMoneyException; import org.bitcoinj.core.Transaction; -import java.io.Serializable; - -import javax.annotation.concurrent.Immutable; +import com.google.common.util.concurrent.FutureCallback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Responsible for coordinating tasks involved in the create offer process. - * It holds the model.state of the current process and support recovery if possible. */ -//TODO recover policy, timer - -@Immutable public class CreateOfferCoordinator { - public enum State { - INITED, - STARTED, - VALIDATED, - OFFER_FEE_TX_CREATED, - OFFER_FEE_BROAD_CASTED, - OFFER_PUBLISHED_TO_DHT - } - - /** - * The model is not immutable but only exposed to the CreateOfferCoordinator - */ - static class Model implements Serializable { - private static final long serialVersionUID = 3027720554200858916L; - - private final Persistence persistence; - private State state; - //TODO use tx id - Transaction transaction; - - Model(Persistence persistence) { - this.persistence = persistence; - } - - public State getState() { - return state; - } - - public void setState(State state) { - this.state = state; - - //TODO will have performance issues, but could be handled inside the persistence solution (queue up save - // requests and exec. them on dedicated thread) - persistence.write(this, "state", state); - } - } private static final Logger log = LoggerFactory.getLogger(CreateOfferCoordinator.class); private final Offer offer; private final WalletFacade walletFacade; - private final MessageFacade messageFacade; private final TransactionResultHandler resultHandler; private final FaultHandler faultHandler; - private final Model model; + private final OfferRepository offerRepository; - public CreateOfferCoordinator(Persistence persistence, Offer offer, WalletFacade walletFacade, - MessageFacade messageFacade, TransactionResultHandler resultHandler, - FaultHandler faultHandler) { - this(offer, walletFacade, messageFacade, resultHandler, faultHandler, new Model(persistence)); - } - - // for recovery from model - public CreateOfferCoordinator(Offer offer, WalletFacade walletFacade, MessageFacade messageFacade, - TransactionResultHandler resultHandler, FaultHandler faultHandler, Model model) { + public CreateOfferCoordinator(Offer offer, WalletFacade walletFacade, TransactionResultHandler resultHandler, + FaultHandler faultHandler, OfferRepository offerRepository) { this.offer = offer; this.walletFacade = walletFacade; - this.messageFacade = messageFacade; this.resultHandler = resultHandler; this.faultHandler = faultHandler; - this.model = model; - - model.setState(State.INITED); + this.offerRepository = offerRepository; } public void start() { - model.setState(State.STARTED); - VerifyOffer.run(this::onOfferValidated, this::onFailed, offer); - } + try { + offer.validate(); + } catch (Exception ex) { + faultHandler.handleFault("Offer validation failed", ex); + return; + } - private void onOfferValidated() { - model.setState(State.VALIDATED); - CreateOfferFeeTx.run(this::onOfferFeeTxCreated, this::onFailed, walletFacade, offer.getId()); - } + Transaction transaction; - private void onOfferFeeTxCreated(Transaction transaction) { - model.transaction = transaction; - model.setState(State.OFFER_FEE_TX_CREATED); - offer.setOfferFeePaymentTxID(transaction.getHashAsString()); - BroadCastOfferFeeTx.run(this::onOfferFeeTxBroadCasted, this::onFailed, walletFacade, transaction); - } + try { + transaction = walletFacade.createOfferFeeTx(offer.getId()); + offer.setOfferFeePaymentTxID(transaction.getHashAsString()); + } catch (InsufficientMoneyException ex) { + faultHandler.handleFault( + "Offer fee payment failed because there is insufficient money in the trade wallet", ex); + return; + } catch (Throwable ex) { + faultHandler.handleFault("Offer fee payment failed because of an exception occurred", ex); + return; + } - private void onOfferFeeTxBroadCasted() { - model.setState(State.OFFER_FEE_BROAD_CASTED); - PublishOfferToDHT.run(this::onOfferPublishedToDHT, this::onFailed, messageFacade, offer); - } + try { + walletFacade.broadcastCreateOfferFeeTx(transaction, new FutureCallback() { + @Override + public void onSuccess(Transaction transaction) { + log.info("sendResult onSuccess:" + transaction); + if (transaction == null) { + faultHandler.handleFault("Offer fee payment failed.", + new Exception("Offer fee payment failed. Transaction = null.")); + return; + } - private void onOfferPublishedToDHT() { - model.setState(State.OFFER_PUBLISHED_TO_DHT); - resultHandler.onResult(model.transaction); - } + try { + offerRepository.addOffer(offer, () -> resultHandler.onResult(transaction), faultHandler); + } catch (Exception e) { + faultHandler.handleFault("Offer fee payment failed.", e); + } + } - private void onFailed(String message, Throwable throwable) { - //TODO recover policy, timer - faultHandler.onFault(message, throwable); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Recovery - /////////////////////////////////////////////////////////////////////////////////////////// - - public void recover() { - switch (model.getState()) { - case INITED: - case STARTED: - case VALIDATED: - case OFFER_FEE_TX_CREATED: - // we start over again, no critical and expensive work done yet - start(); - break; - case OFFER_FEE_BROAD_CASTED: - // actually the only replay case here, tx publish was successful but storage to dht failed. - // Republish the offer to DHT - PublishOfferToDHT.run(this::onOfferPublishedToDHT, this::onFailed, messageFacade, offer); - break; - case OFFER_PUBLISHED_TO_DHT: - // should be impossible - log.warn("That case must not happen."); - break; - default: - log.error("Illegal state passes. That must not happen"); - break; + @Override + public void onFailure(Throwable t) { + faultHandler.handleFault("Offer fee payment failed with an exception.", t); + } + }); + } catch (Throwable t) { + faultHandler.handleFault("Offer fee payment failed because an exception occurred.", t); + return; } } - } diff --git a/src/main/java/io/bitsquare/trade/protocol/createoffer/tasks/BroadCastOfferFeeTx.java b/src/main/java/io/bitsquare/trade/protocol/createoffer/tasks/BroadCastOfferFeeTx.java deleted file mode 100644 index fc5a30f763..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/createoffer/tasks/BroadCastOfferFeeTx.java +++ /dev/null @@ -1,65 +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.trade.protocol.createoffer.tasks; - -import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.handlers.FaultHandler; -import io.bitsquare.trade.handlers.ResultHandler; - -import org.bitcoinj.core.Transaction; - -import com.google.common.util.concurrent.FutureCallback; - -import org.jetbrains.annotations.NotNull; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class BroadCastOfferFeeTx { - private static final Logger log = LoggerFactory.getLogger(BroadCastOfferFeeTx.class); - - public static void run(ResultHandler resultHandler, FaultHandler faultHandler, WalletFacade walletFacade, - Transaction tx) { - try { - walletFacade.broadcastCreateOfferFeeTx(tx, new FutureCallback() { - @Override - public void onSuccess(@javax.annotation.Nullable Transaction transaction) { - log.info("sendResult onSuccess:" + transaction); - if (transaction != null) { - try { - resultHandler.onResult(); - } catch (Exception e) { - faultHandler.onFault("Offer fee payment failed.", e); - } - } - else { - faultHandler.onFault("Offer fee payment failed.", - new Exception("Offer fee payment failed. Transaction = null.")); - } - } - - @Override - public void onFailure(@NotNull Throwable t) { - faultHandler.onFault("Offer fee payment failed with an exception.", t); - } - }); - } catch (Throwable t) { - faultHandler.onFault("Offer fee payment failed because an exception occurred.", t); - } - } -} diff --git a/src/main/java/io/bitsquare/trade/protocol/createoffer/tasks/CreateOfferFeeTx.java b/src/main/java/io/bitsquare/trade/protocol/createoffer/tasks/CreateOfferFeeTx.java deleted file mode 100644 index 4c944a0332..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/createoffer/tasks/CreateOfferFeeTx.java +++ /dev/null @@ -1,43 +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.trade.protocol.createoffer.tasks; - -import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.handlers.FaultHandler; -import io.bitsquare.trade.handlers.TransactionResultHandler; - -import org.bitcoinj.core.InsufficientMoneyException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class CreateOfferFeeTx { - private static final Logger log = LoggerFactory.getLogger(CreateOfferFeeTx.class); - - public static void run(TransactionResultHandler resultHandler, FaultHandler faultHandler, - WalletFacade walletFacade, String offerId) { - try { - resultHandler.onResult(walletFacade.createOfferFeeTx(offerId)); - } catch (InsufficientMoneyException e) { - faultHandler.onFault("Offer fee payment failed because there is insufficient money in the trade wallet. " + - "", e); - } catch (Throwable t) { - faultHandler.onFault("Offer fee payment failed because of an exception occurred. ", t); - } - } -} diff --git a/src/main/java/io/bitsquare/trade/protocol/createoffer/tasks/PublishOfferToDHT.java b/src/main/java/io/bitsquare/trade/protocol/createoffer/tasks/PublishOfferToDHT.java deleted file mode 100644 index d5611bd519..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/createoffer/tasks/PublishOfferToDHT.java +++ /dev/null @@ -1,46 +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.trade.protocol.createoffer.tasks; - -import io.bitsquare.msg.MessageFacade; -import io.bitsquare.msg.listeners.AddOfferListener; -import io.bitsquare.offer.Offer; -import io.bitsquare.trade.handlers.FaultHandler; -import io.bitsquare.trade.handlers.ResultHandler; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PublishOfferToDHT { - private static final Logger log = LoggerFactory.getLogger(PublishOfferToDHT.class); - - public static void run(ResultHandler resultHandler, FaultHandler faultHandler, MessageFacade messageFacade, - Offer offer) { - messageFacade.addOffer(offer, new AddOfferListener() { - @Override - public void onComplete() { - resultHandler.onResult(); - } - - @Override - public void onFailed(String reason, Throwable throwable) { - faultHandler.onFault("Publish offer to DHT failed.", throwable); - } - }); - } -} diff --git a/src/main/java/io/bitsquare/trade/protocol/createoffer/tasks/VerifyOffer.java b/src/main/java/io/bitsquare/trade/protocol/createoffer/tasks/VerifyOffer.java deleted file mode 100644 index d3857a74bb..0000000000 --- a/src/main/java/io/bitsquare/trade/protocol/createoffer/tasks/VerifyOffer.java +++ /dev/null @@ -1,74 +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.trade.protocol.createoffer.tasks; - -import io.bitsquare.btc.Restrictions; -import io.bitsquare.offer.Offer; -import io.bitsquare.trade.handlers.FaultHandler; -import io.bitsquare.trade.handlers.ResultHandler; - -import javax.annotation.concurrent.Immutable; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static com.google.common.base.Preconditions.*; - -@Immutable -public class VerifyOffer { - private static final Logger log = LoggerFactory.getLogger(VerifyOffer.class); - - public static void run(ResultHandler resultHandler, FaultHandler faultHandler, Offer offer) { - try { - checkNotNull(offer.getAcceptedCountries(), "AcceptedCountries is null"); - checkNotNull(offer.getAcceptedLanguageLocales(), "AcceptedLanguageLocales is null"); - checkNotNull(offer.getAmount(), "Amount is null"); - checkNotNull(offer.getArbitrators(), "Arbitrator is null"); - //checkNotNull(offer.getBankAccountCountry(), "BankAccountCountry is null"); - checkNotNull(offer.getBankAccountId(), "BankAccountId is null"); - checkNotNull(offer.getSecurityDeposit(), "SecurityDeposit is null"); - checkNotNull(offer.getCreationDate(), "CreationDate is null"); - checkNotNull(offer.getCurrency(), "Currency is null"); - checkNotNull(offer.getDirection(), "Direction is null"); - checkNotNull(offer.getId(), "Id is null"); - checkNotNull(offer.getMessagePublicKey(), "MessagePublicKey is null"); - checkNotNull(offer.getMinAmount(), "MinAmount is null"); - checkNotNull(offer.getPrice(), "Price is null"); - - //checkArgument(!offer.getAcceptedCountries().isEmpty(), "AcceptedCountries is empty"); - //checkArgument(!offer.getAcceptedLanguageLocales().isEmpty(), "AcceptedLanguageLocales is empty"); - checkArgument(offer.getMinAmount().compareTo(Restrictions.MIN_TRADE_AMOUNT) >= 0, - "MinAmount is less then " + Restrictions.MIN_TRADE_AMOUNT); - checkArgument(offer.getAmount().compareTo(Restrictions.MIN_TRADE_AMOUNT) >= 0, - "Amount is less then " + Restrictions.MIN_TRADE_AMOUNT); - checkArgument(offer.getAmount().compareTo(offer.getMinAmount()) >= 0, "MinAmount is larger then Amount"); - checkArgument(offer.getSecurityDeposit().isPositive(), "SecurityDeposit is not positive"); - checkArgument(offer.getPrice().isPositive(), "Price is 0 or negative"); - - // TODO check balance - // securityDeposit - // Coin totalsToFund - // getAddressInfoByTradeID(offerId) - // TODO when offer is flattened continue here... - - resultHandler.onResult(); - } catch (Throwable t) { - faultHandler.onFault("Offer validation failed.", t); - } - } -} diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/CreateDepositTx.java b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/CreateDepositTx.java index fa15c22276..bc82c84cc6 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/CreateDepositTx.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/CreateDepositTx.java @@ -18,7 +18,7 @@ package io.bitsquare.trade.protocol.trade.offerer.tasks; import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.handlers.ExceptionHandler; +import io.bitsquare.util.task.ExceptionHandler; import org.bitcoinj.core.Coin; import org.bitcoinj.core.InsufficientMoneyException; @@ -50,7 +50,7 @@ public class CreateDepositTx { resultHandler.onResult(offererPubKey, preparedOffererDepositTxAsHex, offererTxOutIndex); } catch (InsufficientMoneyException e) { log.error("Create deposit tx faultHandler.onFault due InsufficientMoneyException " + e); - exceptionHandler.onError( + exceptionHandler.handleException( new Exception("Create deposit tx faultHandler.onFault due InsufficientMoneyException " + e)); } } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/HandleTakeOfferRequest.java b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/HandleTakeOfferRequest.java index 02147d4e82..f889d3f5da 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/HandleTakeOfferRequest.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/HandleTakeOfferRequest.java @@ -21,8 +21,8 @@ import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingMessageListener; import io.bitsquare.network.Peer; import io.bitsquare.trade.Trade; -import io.bitsquare.trade.handlers.ExceptionHandler; import io.bitsquare.trade.protocol.trade.offerer.messages.RespondToTakeOfferRequestMessage; +import io.bitsquare.util.task.ExceptionHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,7 +49,7 @@ public class HandleTakeOfferRequest { @Override public void onFailed() { log.error("AcceptTakeOfferRequestMessage did not arrive at peer"); - exceptionHandler.onError(new Exception("AcceptTakeOfferRequestMessage did not arrive at peer")); + exceptionHandler.handleException(new Exception("AcceptTakeOfferRequestMessage did not arrive at peer")); } }); } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/RequestTakerDepositPayment.java b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/RequestTakerDepositPayment.java index ac34b12810..6352ac73d9 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/RequestTakerDepositPayment.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/RequestTakerDepositPayment.java @@ -21,9 +21,9 @@ import io.bitsquare.bank.BankAccount; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingMessageListener; import io.bitsquare.network.Peer; -import io.bitsquare.trade.handlers.ExceptionHandler; -import io.bitsquare.trade.handlers.ResultHandler; import io.bitsquare.trade.protocol.trade.offerer.messages.RequestTakerDepositPaymentMessage; +import io.bitsquare.util.task.ExceptionHandler; +import io.bitsquare.util.task.ResultHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,13 +48,14 @@ public class RequestTakerDepositPayment { @Override public void onResult() { log.trace("RequestTakerDepositPaymentMessage successfully arrived at peer"); - resultHandler.onResult(); + resultHandler.handleResult(); } @Override public void onFailed() { log.error("RequestTakerDepositPaymentMessage did not arrive at peer"); - exceptionHandler.onError(new Exception("RequestTakerDepositPaymentMessage did not arrive at peer")); + exceptionHandler.handleException(new Exception("RequestTakerDepositPaymentMessage did not arrive at " + + "peer")); } }); } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SendDepositTxIdToTaker.java b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SendDepositTxIdToTaker.java index 74287b44b9..7c597bca8a 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SendDepositTxIdToTaker.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SendDepositTxIdToTaker.java @@ -20,9 +20,9 @@ package io.bitsquare.trade.protocol.trade.offerer.tasks; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingMessageListener; import io.bitsquare.network.Peer; -import io.bitsquare.trade.handlers.ExceptionHandler; -import io.bitsquare.trade.handlers.ResultHandler; import io.bitsquare.trade.protocol.trade.offerer.messages.DepositTxPublishedMessage; +import io.bitsquare.util.task.ExceptionHandler; +import io.bitsquare.util.task.ResultHandler; import org.bitcoinj.core.Transaction; import org.bitcoinj.core.Utils; @@ -43,13 +43,13 @@ public class SendDepositTxIdToTaker { @Override public void onResult() { log.trace("DepositTxPublishedMessage successfully arrived at peer"); - resultHandler.onResult(); + resultHandler.handleResult(); } @Override public void onFailed() { log.error("DepositTxPublishedMessage did not arrive at peer"); - exceptionHandler.onError(new Exception("DepositTxPublishedMessage did not arrive at peer")); + exceptionHandler.handleException(new Exception("DepositTxPublishedMessage did not arrive at peer")); } }); } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SendSignedPayoutTx.java b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SendSignedPayoutTx.java index 3000aa8b95..c58a49871e 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SendSignedPayoutTx.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SendSignedPayoutTx.java @@ -21,9 +21,9 @@ import io.bitsquare.btc.WalletFacade; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingMessageListener; import io.bitsquare.network.Peer; -import io.bitsquare.trade.handlers.ExceptionHandler; -import io.bitsquare.trade.handlers.ResultHandler; import io.bitsquare.trade.protocol.trade.offerer.messages.BankTransferInitedMessage; +import io.bitsquare.util.task.ExceptionHandler; +import io.bitsquare.util.task.ResultHandler; import org.bitcoinj.core.Coin; import org.bitcoinj.core.ECKey; @@ -72,19 +72,19 @@ public class SendSignedPayoutTx { @Override public void onResult() { log.trace("BankTransferInitedMessage successfully arrived at peer"); - resultHandler.onResult(); + resultHandler.handleResult(); } @Override public void onFailed() { log.error("BankTransferInitedMessage did not arrive at peer"); - exceptionHandler.onError(new Exception("BankTransferInitedMessage did not arrive at peer")); + exceptionHandler.handleException(new Exception("BankTransferInitedMessage did not arrive at peer")); } }); } catch (Exception e) { log.error("Exception at OffererCreatesAndSignsPayoutTx " + e); - exceptionHandler.onError(e); + exceptionHandler.handleException(e); } } } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SetupListenerForBlockChainConfirmation.java b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SetupListenerForBlockChainConfirmation.java index 2a7128d84f..982e5d11ac 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SetupListenerForBlockChainConfirmation.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SetupListenerForBlockChainConfirmation.java @@ -17,8 +17,8 @@ package io.bitsquare.trade.protocol.trade.offerer.tasks; -import io.bitsquare.trade.handlers.ResultHandler; import io.bitsquare.trade.protocol.trade.offerer.BuyerAcceptsOfferProtocolListener; +import io.bitsquare.util.task.ResultHandler; import org.bitcoinj.core.Transaction; import org.bitcoinj.core.TransactionConfidence; @@ -44,7 +44,7 @@ public class SetupListenerForBlockChainConfirmation { listener.onDepositTxConfirmedInBlockchain(); depositTransaction.getConfidence().removeEventListener(this); log.trace("Tx is in blockchain"); - resultHandler.onResult(); + resultHandler.handleResult(); } } }); diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SignAndPublishDepositTx.java b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SignAndPublishDepositTx.java index 06fa14e8f1..5a3c20e477 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SignAndPublishDepositTx.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SignAndPublishDepositTx.java @@ -18,7 +18,7 @@ package io.bitsquare.trade.protocol.trade.offerer.tasks; import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.handlers.ExceptionHandler; +import io.bitsquare.util.task.ExceptionHandler; import org.bitcoinj.core.Transaction; @@ -59,12 +59,12 @@ public class SignAndPublishDepositTx { @Override public void onFailure(@NotNull Throwable t) { log.error("offererSignAndPublishTx faultHandler.onFault:" + t); - exceptionHandler.onError(t); + exceptionHandler.handleException(t); } }); } catch (Exception e) { log.error("offererSignAndPublishTx faultHandler.onFault:" + e); - exceptionHandler.onError(e); + exceptionHandler.handleException(e); } } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/VerifyAndSignContract.java b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/VerifyAndSignContract.java index a8afea8c00..9d6d795ff7 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/VerifyAndSignContract.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/VerifyAndSignContract.java @@ -21,8 +21,8 @@ import io.bitsquare.bank.BankAccount; import io.bitsquare.crypto.CryptoFacade; import io.bitsquare.offer.Offer; import io.bitsquare.trade.Contract; -import io.bitsquare.trade.handlers.ExceptionHandler; import io.bitsquare.util.Utilities; +import io.bitsquare.util.task.ExceptionHandler; import org.bitcoinj.core.Coin; import org.bitcoinj.core.ECKey; diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/VerifyTakeOfferFeePayment.java b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/VerifyTakeOfferFeePayment.java index 5b731a86e2..d29f7c7edb 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/VerifyTakeOfferFeePayment.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/VerifyTakeOfferFeePayment.java @@ -18,8 +18,8 @@ package io.bitsquare.trade.protocol.trade.offerer.tasks; import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.handlers.ExceptionHandler; -import io.bitsquare.trade.handlers.ResultHandler; +import io.bitsquare.util.task.ExceptionHandler; +import io.bitsquare.util.task.ResultHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,7 +33,7 @@ public class VerifyTakeOfferFeePayment { //TODO mocked yet, need a confidence listeners int numOfPeersSeenTx = walletFacade.getNumOfPeersSeenTx(takeOfferFeeTxId); if (numOfPeersSeenTx > 2) { - resultHandler.onResult(); + resultHandler.handleResult(); } } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/VerifyTakerAccount.java b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/VerifyTakerAccount.java index e1ed167ba4..2ffc5ebf3f 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/VerifyTakerAccount.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/VerifyTakerAccount.java @@ -19,9 +19,9 @@ package io.bitsquare.trade.protocol.trade.offerer.tasks; import io.bitsquare.bank.BankAccount; import io.bitsquare.btc.BlockChainFacade; -import io.bitsquare.trade.handlers.ExceptionHandler; -import io.bitsquare.trade.handlers.ResultHandler; import io.bitsquare.trade.protocol.trade.shared.tasks.VerifyPeerAccount; +import io.bitsquare.util.task.ExceptionHandler; +import io.bitsquare.util.task.ResultHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/shared/tasks/VerifyPeerAccount.java b/src/main/java/io/bitsquare/trade/protocol/trade/shared/tasks/VerifyPeerAccount.java index b60ae370cc..b4d7ba4ad9 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/shared/tasks/VerifyPeerAccount.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/shared/tasks/VerifyPeerAccount.java @@ -19,8 +19,8 @@ package io.bitsquare.trade.protocol.trade.shared.tasks; import io.bitsquare.bank.BankAccount; import io.bitsquare.btc.BlockChainFacade; -import io.bitsquare.trade.handlers.ExceptionHandler; -import io.bitsquare.trade.handlers.ResultHandler; +import io.bitsquare.util.task.ExceptionHandler; +import io.bitsquare.util.task.ResultHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,15 +34,16 @@ public class VerifyPeerAccount { if (blockChainFacade.verifyAccountRegistration()) { if (blockChainFacade.isAccountBlackListed(peersAccountId, peersBankAccount)) { log.error("Taker is blacklisted"); - exceptionHandler.onError(new Exception("Taker is blacklisted")); + exceptionHandler.handleException(new Exception("Taker is blacklisted")); } else { - resultHandler.onResult(); + resultHandler.handleResult(); } } else { log.error("Account registration validation for peer faultHandler.onFault."); - exceptionHandler.onError(new Exception("Account registration validation for peer faultHandler.onFault.")); + exceptionHandler.handleException(new Exception("Account registration validation for peer faultHandler" + + ".onFault.")); } } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/CreateAndSignContract.java b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/CreateAndSignContract.java index ea634dfa75..8bfbe31d73 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/CreateAndSignContract.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/CreateAndSignContract.java @@ -21,8 +21,8 @@ import io.bitsquare.bank.BankAccount; import io.bitsquare.crypto.CryptoFacade; import io.bitsquare.offer.Offer; import io.bitsquare.trade.Contract; -import io.bitsquare.trade.handlers.ExceptionHandler; import io.bitsquare.util.Utilities; +import io.bitsquare.util.task.ExceptionHandler; import org.bitcoinj.core.Coin; import org.bitcoinj.core.ECKey; @@ -58,7 +58,7 @@ public class CreateAndSignContract { resultHandler.onResult(contract, contractAsJson, signature); } catch (Throwable t) { log.error("Exception at sign contract " + t); - exceptionHandler.onError(t); + exceptionHandler.handleException(t); } } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/GetPeerAddress.java b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/GetPeerAddress.java index 85fdbdb1c4..a083549ba3 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/GetPeerAddress.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/GetPeerAddress.java @@ -20,7 +20,7 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.GetPeerAddressListener; import io.bitsquare.network.Peer; -import io.bitsquare.trade.handlers.ExceptionHandler; +import io.bitsquare.util.task.ExceptionHandler; import java.security.PublicKey; @@ -43,7 +43,7 @@ public class GetPeerAddress { @Override public void onFailed() { log.error("Lookup for peer address faultHandler.onFault."); - exceptionHandler.onError(new Exception("Lookup for peer address faultHandler.onFault.")); + exceptionHandler.handleException(new Exception("Lookup for peer address faultHandler.onFault.")); } }); } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayDeposit.java b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayDeposit.java index b4fa012929..1c44dad458 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayDeposit.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayDeposit.java @@ -18,7 +18,7 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.handlers.ExceptionHandler; +import io.bitsquare.util.task.ExceptionHandler; import org.bitcoinj.core.Coin; import org.bitcoinj.core.InsufficientMoneyException; @@ -57,7 +57,7 @@ public class PayDeposit { resultHandler.onResult(signedTakerDepositTx); } catch (InsufficientMoneyException e) { log.error("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e); - exceptionHandler.onError( + exceptionHandler.handleException( new Exception("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e)); } } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayTakeOfferFee.java b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayTakeOfferFee.java index 122f6a4287..8889b7a05e 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayTakeOfferFee.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayTakeOfferFee.java @@ -18,7 +18,7 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.handlers.ExceptionHandler; +import io.bitsquare.util.task.ExceptionHandler; import org.bitcoinj.core.InsufficientMoneyException; import org.bitcoinj.core.Transaction; @@ -47,13 +47,13 @@ public class PayTakeOfferFee { @Override public void onFailure(@NotNull Throwable t) { log.error("Take offer fee paid faultHandler.onFault with exception: " + t); - exceptionHandler.onError( + exceptionHandler.handleException( new Exception("Take offer fee paid faultHandler.onFault with exception: " + t)); } }); } catch (InsufficientMoneyException e) { log.error("Take offer fee paid faultHandler.onFault due InsufficientMoneyException " + e); - exceptionHandler.onError( + exceptionHandler.handleException( new Exception("Take offer fee paid faultHandler.onFault due to InsufficientMoneyException " + e)); } } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/RequestTakeOffer.java b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/RequestTakeOffer.java index 412f6ceaf0..de4f78e7bc 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/RequestTakeOffer.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/RequestTakeOffer.java @@ -20,9 +20,9 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingMessageListener; import io.bitsquare.network.Peer; -import io.bitsquare.trade.handlers.ExceptionHandler; -import io.bitsquare.trade.handlers.ResultHandler; import io.bitsquare.trade.protocol.trade.taker.messages.RequestTakeOfferMessage; +import io.bitsquare.util.task.ExceptionHandler; +import io.bitsquare.util.task.ResultHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,13 +38,14 @@ public class RequestTakeOffer { @Override public void onResult() { log.trace("RequestTakeOfferMessage successfully arrived at peer"); - resultHandler.onResult(); + resultHandler.handleResult(); } @Override public void onFailed() { log.error("RequestTakeOfferMessage did not arrive at peer"); - exceptionHandler.onError(new Exception("RequestTakeOfferMessage did not arrive at peer")); + exceptionHandler.handleException(new Exception("RequestTakeOfferMessage did not arrive at " + + "peer")); } }); } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendPayoutTxToOfferer.java b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendPayoutTxToOfferer.java index 79f120bca1..81eeef6b87 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendPayoutTxToOfferer.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendPayoutTxToOfferer.java @@ -20,9 +20,9 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingMessageListener; import io.bitsquare.network.Peer; -import io.bitsquare.trade.handlers.ExceptionHandler; -import io.bitsquare.trade.handlers.ResultHandler; import io.bitsquare.trade.protocol.trade.taker.messages.PayoutTxPublishedMessage; +import io.bitsquare.util.task.ExceptionHandler; +import io.bitsquare.util.task.ResultHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,13 +38,13 @@ public class SendPayoutTxToOfferer { @Override public void onResult() { log.trace("PayoutTxPublishedMessage successfully arrived at peer"); - resultHandler.onResult(); + resultHandler.handleResult(); } @Override public void onFailed() { log.error("PayoutTxPublishedMessage did not arrive at peer"); - exceptionHandler.onError(new Exception("PayoutTxPublishedMessage did not arrive at peer")); + exceptionHandler.handleException(new Exception("PayoutTxPublishedMessage did not arrive at peer")); } }); diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendSignedTakerDepositTxAsHex.java b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendSignedTakerDepositTxAsHex.java index 45bf09cfe2..249baf2de2 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendSignedTakerDepositTxAsHex.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendSignedTakerDepositTxAsHex.java @@ -22,9 +22,9 @@ import io.bitsquare.btc.WalletFacade; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingMessageListener; import io.bitsquare.network.Peer; -import io.bitsquare.trade.handlers.ExceptionHandler; -import io.bitsquare.trade.handlers.ResultHandler; import io.bitsquare.trade.protocol.trade.taker.messages.RequestOffererPublishDepositTxMessage; +import io.bitsquare.util.task.ExceptionHandler; +import io.bitsquare.util.task.ResultHandler; import org.bitcoinj.core.Transaction; import org.bitcoinj.core.Utils; @@ -72,13 +72,13 @@ public class SendSignedTakerDepositTxAsHex { @Override public void onResult() { log.trace("RequestOffererDepositPublicationMessage successfully arrived at peer"); - resultHandler.onResult(); + resultHandler.handleResult(); } @Override public void onFailed() { log.error("RequestOffererDepositPublicationMessage did not arrive at peer"); - exceptionHandler.onError( + exceptionHandler.handleException( new Exception("RequestOffererDepositPublicationMessage did not arrive at peer")); } }); diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendTakeOfferFeePayedTxId.java b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendTakeOfferFeePayedTxId.java index e9366ba9a6..4e0d3bd44e 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendTakeOfferFeePayedTxId.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendTakeOfferFeePayedTxId.java @@ -20,9 +20,9 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.listeners.OutgoingMessageListener; import io.bitsquare.network.Peer; -import io.bitsquare.trade.handlers.ExceptionHandler; -import io.bitsquare.trade.handlers.ResultHandler; import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage; +import io.bitsquare.util.task.ExceptionHandler; +import io.bitsquare.util.task.ResultHandler; import org.bitcoinj.core.Coin; @@ -48,13 +48,13 @@ public class SendTakeOfferFeePayedTxId { @Override public void onResult() { log.trace("TakeOfferFeePayedMessage successfully arrived at peer"); - resultHandler.onResult(); + resultHandler.handleResult(); } @Override public void onFailed() { log.error("TakeOfferFeePayedMessage did not arrive at peer"); - exceptionHandler.onError(new Exception("TakeOfferFeePayedMessage did not arrive at peer")); + exceptionHandler.handleException(new Exception("TakeOfferFeePayedMessage did not arrive at peer")); } }); } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SignAndPublishPayoutTx.java b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SignAndPublishPayoutTx.java index 38353fa8ef..ddaf56f9e8 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SignAndPublishPayoutTx.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SignAndPublishPayoutTx.java @@ -18,7 +18,7 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; import io.bitsquare.btc.WalletFacade; -import io.bitsquare.trade.handlers.ExceptionHandler; +import io.bitsquare.util.task.ExceptionHandler; import org.bitcoinj.core.Coin; import org.bitcoinj.core.Transaction; @@ -65,12 +65,12 @@ public class SignAndPublishPayoutTx { @Override public void onFailure(@NotNull Throwable t) { log.error("Exception at takerSignsAndSendsTx " + t); - exceptionHandler.onError(t); + exceptionHandler.handleException(t); } }); } catch (Exception e) { log.error("Exception at takerSignsAndSendsTx " + e); - exceptionHandler.onError(e); + exceptionHandler.handleException(e); } } diff --git a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/VerifyOffererAccount.java b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/VerifyOffererAccount.java index f42cc1ad98..f83af3358b 100644 --- a/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/VerifyOffererAccount.java +++ b/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/VerifyOffererAccount.java @@ -19,9 +19,9 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; import io.bitsquare.bank.BankAccount; import io.bitsquare.btc.BlockChainFacade; -import io.bitsquare.trade.handlers.ExceptionHandler; -import io.bitsquare.trade.handlers.ResultHandler; import io.bitsquare.trade.protocol.trade.shared.tasks.VerifyPeerAccount; +import io.bitsquare.util.task.ExceptionHandler; +import io.bitsquare.util.task.ResultHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/io/bitsquare/trade/handlers/ErrorMessageHandler.java b/src/main/java/io/bitsquare/util/task/ErrorMessageHandler.java similarity index 90% rename from src/main/java/io/bitsquare/trade/handlers/ErrorMessageHandler.java rename to src/main/java/io/bitsquare/util/task/ErrorMessageHandler.java index 0b911733a6..db4cf95fa8 100644 --- a/src/main/java/io/bitsquare/trade/handlers/ErrorMessageHandler.java +++ b/src/main/java/io/bitsquare/util/task/ErrorMessageHandler.java @@ -15,11 +15,11 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.trade.handlers; +package io.bitsquare.util.task; /** * For reporting error message only (UI) */ public interface ErrorMessageHandler { - void onFault(String errorMessage); + void handleErrorMessage(String errorMessage); } diff --git a/src/main/java/io/bitsquare/trade/handlers/ExceptionHandler.java b/src/main/java/io/bitsquare/util/task/ExceptionHandler.java similarity index 90% rename from src/main/java/io/bitsquare/trade/handlers/ExceptionHandler.java rename to src/main/java/io/bitsquare/util/task/ExceptionHandler.java index 6babb5075b..f598cd3585 100644 --- a/src/main/java/io/bitsquare/trade/handlers/ExceptionHandler.java +++ b/src/main/java/io/bitsquare/util/task/ExceptionHandler.java @@ -15,11 +15,11 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.trade.handlers; +package io.bitsquare.util.task; /** * For reporting throwables only */ public interface ExceptionHandler { - void onError(Throwable throwable); + void handleException(Throwable throwable); } diff --git a/src/main/java/io/bitsquare/trade/handlers/FaultHandler.java b/src/main/java/io/bitsquare/util/task/FaultHandler.java similarity index 89% rename from src/main/java/io/bitsquare/trade/handlers/FaultHandler.java rename to src/main/java/io/bitsquare/util/task/FaultHandler.java index 9cea5fb056..ecb0bb2874 100644 --- a/src/main/java/io/bitsquare/trade/handlers/FaultHandler.java +++ b/src/main/java/io/bitsquare/util/task/FaultHandler.java @@ -15,11 +15,11 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.trade.handlers; +package io.bitsquare.util.task; /** * For reporting a description message and throwable */ public interface FaultHandler { - void onFault(String message, Throwable throwable); + void handleFault(String message, Throwable throwable); } diff --git a/src/main/java/io/bitsquare/trade/handlers/ResultHandler.java b/src/main/java/io/bitsquare/util/task/ResultHandler.java similarity index 92% rename from src/main/java/io/bitsquare/trade/handlers/ResultHandler.java rename to src/main/java/io/bitsquare/util/task/ResultHandler.java index f18e242cb3..bb8f25c8ed 100644 --- a/src/main/java/io/bitsquare/trade/handlers/ResultHandler.java +++ b/src/main/java/io/bitsquare/util/task/ResultHandler.java @@ -15,8 +15,8 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.trade.handlers; +package io.bitsquare.util.task; public interface ResultHandler { - void onResult(); + void handleResult(); } diff --git a/src/main/java/io/bitsquare/msg/listeners/AddOfferListener.java b/src/main/java/io/bitsquare/util/tomp2p/BaseFutureUtil.java similarity index 69% rename from src/main/java/io/bitsquare/msg/listeners/AddOfferListener.java rename to src/main/java/io/bitsquare/util/tomp2p/BaseFutureUtil.java index 7a05c60141..fd11371e1e 100644 --- a/src/main/java/io/bitsquare/msg/listeners/AddOfferListener.java +++ b/src/main/java/io/bitsquare/util/tomp2p/BaseFutureUtil.java @@ -15,10 +15,15 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.msg.listeners; +package io.bitsquare.util.tomp2p; -public interface AddOfferListener { - void onComplete(); +import net.tomp2p.futures.BaseFuture; - void onFailed(String reason, Throwable throwable); +public class BaseFutureUtil { + + // Isolate the success handling as there is bug in port forwarding mode + public static boolean isSuccess(BaseFuture baseFuture) { + // return baseFuture.isSuccess(); + return true; + } } diff --git a/src/test/java/io/bitsquare/gui/ViewLoaderTest.java b/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java similarity index 88% rename from src/test/java/io/bitsquare/gui/ViewLoaderTest.java rename to src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java index 26cd7a32e4..77d0bcd6f9 100644 --- a/src/test/java/io/bitsquare/gui/ViewLoaderTest.java +++ b/src/test/java/io/bitsquare/app/gui/ViewLoaderTests.java @@ -15,9 +15,11 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.gui; +package io.bitsquare.app.gui; -import io.bitsquare.app.BitsquareModule; +import io.bitsquare.gui.FatalException; +import io.bitsquare.gui.Navigation; +import io.bitsquare.gui.ViewLoader; import com.google.inject.Guice; import com.google.inject.Injector; @@ -30,7 +32,7 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -public class ViewLoaderTest { +public class ViewLoaderTests { public static class TestApp extends Application { static Stage primaryStage; @@ -56,7 +58,7 @@ public class ViewLoaderTest { @Before public void setUp() { - Injector injector = Guice.createInjector(new BitsquareModule(TestApp.primaryStage, "testApp")); + Injector injector = Guice.createInjector(new MainModule("testApp", TestApp.primaryStage)); ViewLoader.setInjector(injector); } diff --git a/src/test/java/io/bitsquare/msg/P2PNodeTest.java b/src/test/java/io/bitsquare/msg/tomp2p/TomP2PNodeTest.java similarity index 94% rename from src/test/java/io/bitsquare/msg/P2PNodeTest.java rename to src/test/java/io/bitsquare/msg/tomp2p/TomP2PNodeTest.java index 05d79f07d7..1d1742d5ba 100644 --- a/src/test/java/io/bitsquare/msg/P2PNodeTest.java +++ b/src/test/java/io/bitsquare/msg/tomp2p/TomP2PNodeTest.java @@ -15,7 +15,7 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.msg; +package io.bitsquare.msg.tomp2p; import java.io.IOException; @@ -48,12 +48,12 @@ import org.slf4j.LoggerFactory; import static org.junit.Assert.*; -// TODO Reactivate tests when P2PNode is using original code again. we deactivated the security features atm. +// TODO Reactivate tests when TomP2PNode is using original code again. we deactivated the security features atm. // cause IOException: Not listening to anything. Maybe your binding information is wrong. // investigate what has broken it, probably from update to latest head @Ignore -public class P2PNodeTest { - private static final Logger log = LoggerFactory.getLogger(P2PNodeTest.class); +public class TomP2PNodeTest { + private static final Logger log = LoggerFactory.getLogger(TomP2PNodeTest.class); final private static Random rnd = new Random(42L); @@ -80,12 +80,12 @@ public class P2PNodeTest { KeyPair keyPairClient = keyGen.genKeyPair(); KeyPair keyPairOtherPeer = keyGen.genKeyPair(); - P2PNode node; + TomP2PNode node; Number160 locationKey; Object object; FutureDirect futureDirect; - node = new P2PNode(keyPairClient, client); + node = new TomP2PNode(keyPairClient, client); object = "clients data"; futureDirect = node.sendData(otherPeer.peerAddress(), object); futureDirect.awaitUninterruptibly(); @@ -110,7 +110,7 @@ public class P2PNodeTest { KeyPair keyPairClient = keyGen.genKeyPair(); KeyPair keyPairOtherPeer = keyGen.genKeyPair(); - P2PNode node; + TomP2PNode node; Number160 locationKey; Data data; FuturePut futurePut; @@ -119,7 +119,7 @@ public class P2PNodeTest { // otherPeer tries to squat clients location store // he can do it but as he has not the domain key of the client he cannot do any harm // he only can store und that path: locationKey.otherPeerDomainKey.data - node = new P2PNode(keyPairOtherPeer, otherPeer); + node = new TomP2PNode(keyPairOtherPeer, otherPeer); locationKey = Number160.createHash("clients location"); data = new Data("otherPeer data"); futurePut = node.putDomainProtectedData(locationKey, data); @@ -133,7 +133,7 @@ public class P2PNodeTest { // client store his data und his domainkey, no problem with previous occupied // he only can store und that path: locationKey.clientDomainKey.data - node = new P2PNode(keyPairClient, client); + node = new TomP2PNode(keyPairClient, client); locationKey = Number160.createHash("clients location"); data = new Data("client data"); futurePut = node.putDomainProtectedData(locationKey, data); @@ -146,7 +146,7 @@ public class P2PNodeTest { assertEquals("client data", futureGet.data().object()); // also other peers can read that data if they know the public key of the client - node = new P2PNode(keyPairOtherPeer, otherPeer); + node = new TomP2PNode(keyPairOtherPeer, otherPeer); futureGet = node.getDomainProtectedData(locationKey, keyPairClient.getPublic()); futureGet.awaitUninterruptibly(); assertTrue(futureGet.isSuccess()); @@ -168,7 +168,7 @@ public class P2PNodeTest { assertFalse(futurePut.isSuccess()); // he can read his prev. stored data - node = new P2PNode(keyPairOtherPeer, otherPeer); + node = new TomP2PNode(keyPairOtherPeer, otherPeer); futureGet = node.getDomainProtectedData(locationKey, keyPairOtherPeer.getPublic()); futureGet.awaitUninterruptibly(); assertTrue(futureGet.isSuccess()); @@ -226,7 +226,7 @@ public class P2PNodeTest { PeerDHT otherPeer = peers[2]; UtilsDHT2.perfectRouting(peers); - P2PNode node; + TomP2PNode node; final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA"); keyGen.initialize(1024); KeyPair keyPairClient = keyGen.genKeyPair(); @@ -243,7 +243,7 @@ public class P2PNodeTest { KeyPair keyPair1 = gen.generateKeyPair(); keyPairClient = keyPair1; - node = new P2PNode(keyPairClient, client); + node = new TomP2PNode(keyPairClient, client); locationKey = Number160.createHash("add to list clients location"); data = new Data("add to list client data1"); Data data_1 = data; @@ -298,7 +298,7 @@ public class P2PNodeTest { futurePut.awaitUninterruptibly(); assertTrue(futurePut.isSuccess()); - node = new P2PNode(keyPairOtherPeer, otherPeer); + node = new TomP2PNode(keyPairOtherPeer, otherPeer); futureGet = node.getDataMap(locationKey); futureGet.awaitUninterruptibly(); assertTrue(futureGet.isSuccess()); @@ -334,7 +334,7 @@ public class P2PNodeTest { // client removes his entry -> OK - node = new P2PNode(keyPairClient, client); + node = new TomP2PNode(keyPairClient, client); FutureRemove futureRemove = node.removeFromDataMap(locationKey, data_1); futureRemove.awaitUninterruptibly(); assertTrue(futureRemove.isSuccess()); @@ -375,7 +375,7 @@ public class P2PNodeTest { // otherPeer tries to removes client entry -> FAIL - node = new P2PNode(keyPairOtherPeer, otherPeer); + node = new TomP2PNode(keyPairOtherPeer, otherPeer); futureRemove = node.removeFromDataMap(locationKey, data_2); futureRemove.awaitUninterruptibly(); assertFalse(futureRemove.isSuccess()); diff --git a/src/test/java/io/bitsquare/util/Repeat.java b/src/test/java/io/bitsquare/util/Repeat.java index d67c8be70b..2e8501d892 100644 --- a/src/test/java/io/bitsquare/util/Repeat.java +++ b/src/test/java/io/bitsquare/util/Repeat.java @@ -18,7 +18,6 @@ package io.bitsquare.util; import java.lang.annotation.ElementType; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;