fixed app dir problem with update to gradle.

This commit is contained in:
Manfred Karrer 2014-08-28 18:24:42 +02:00
parent fb7397eb48
commit fb89f087f0
18 changed files with 206 additions and 242 deletions

View File

@ -1,9 +0,0 @@
<component name="CopyrightManager">
<copyright>
<option name="notice" value="This file is part of Bitsquare.&#10;&#10;Bitsquare is free software: you can redistribute it and/or modify it&#10;under the terms of the GNU Affero General Public License as published by&#10;the Free Software Foundation, either version 3 of the License, or (at&#10;your option) any later version.&#10;&#10;Bitsquare is distributed in the hope that it will be useful, but WITHOUT&#10;ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or&#10;FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public&#10;License for more details.&#10;&#10;You should have received a copy of the GNU Affero General Public License&#10;along with Bitsquare. If not, see &lt;http://www.gnu.org/licenses/&gt;." />
<option name="keyword" value="GNU Affero General Public License" />
<option name="allowReplaceKeyword" value="" />
<option name="myName" value="Bitsquare Affero GPLv3" />
<option name="myLocal" value="true" />
</copyright>
</component>

View File

@ -1,3 +1,3 @@
<component name="CopyrightManager">
<settings default="Bitsquare Affero GPLv3" />
<settings default="" />
</component>

23
Development-notes.md Normal file
View File

@ -0,0 +1,23 @@
## UI Architecure pattern:
We use the Presentation Model pattern which has some similarities with MVVM (Silverlight, WPF) as we use data
bindings, though there are differences in the way the view and the "code behind" is organized (different framework
support).
We don't use the term controller for the JavaFX controller it has too much association with the classical MVC
controller.
View: FXML or code based View
CodeBehind (CB): JavaFX controller associated with FXML View
Presentation Model (PM)
Model: Domain data
* State is stored in the presenter.
* Logic is stored in presenter.
* Presenter represents a abstract view of the UI.
* Presenter is not aware of the view.
* View is aware of the presenter.
* View is completely isolated from the model.
## References:
[Presentation Model](http://martinfowler.com/eaaDev/PresentationModel.html)
[Model View ViewModel - MVVM](http://msdn.microsoft.com/en-us/magazine/dd419663.aspx)

View File

@ -28,14 +28,12 @@ import io.bitsquare.persistence.Persistence;
import io.bitsquare.settings.Settings;
import io.bitsquare.user.User;
import io.bitsquare.util.AWTSystemTray;
import io.bitsquare.util.AppDirectoryUtil;
import com.google.common.base.Throwables;
import com.google.inject.Guice;
import com.google.inject.Injector;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
@ -48,6 +46,8 @@ import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lighthouse.files.AppDirectory;
public class BitSquare extends Application {
private static final Logger log = LoggerFactory.getLogger(BitSquare.class);
@ -61,7 +61,7 @@ public class BitSquare extends Application {
public static void main(String[] args) {
Profiler.init();
Profiler.printMsgWithTime("BitSquare.main called with args " + Arrays.asList(args).toString());
if (args != null && args.length > 0) APP_NAME = args[0];
if (args.length > 0) APP_NAME = APP_NAME + "_" + args[0];
launch(args);
}
@ -82,8 +82,7 @@ public class BitSquare extends Application {
Thread.currentThread().setUncaughtExceptionHandler((thread, throwable) -> Popups.handleUncaughtExceptions
(Throwables.getRootCause(throwable)));
AppDirectoryUtil.setStorageDirectory(
new File(AppDirectoryUtil.getApplicationDirectory().getCanonicalPath() + "/data"));
AppDirectory.initAppDir(APP_NAME);
// currently there is not SystemTray support for java fx (planned for version 3) so we use the old AWT
AWTSystemTray.createSystemTray(primaryStage);

View File

@ -22,7 +22,6 @@ import io.bitsquare.btc.listeners.BalanceListener;
import io.bitsquare.btc.listeners.ConfidenceListener;
import io.bitsquare.crypto.CryptoFacade;
import io.bitsquare.persistence.Persistence;
import io.bitsquare.util.AppDirectoryUtil;
import com.google.bitcoin.core.Address;
import com.google.bitcoin.core.AddressFormatException;
@ -78,6 +77,8 @@ import javafx.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lighthouse.files.AppDirectory;
import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
/**
@ -139,7 +140,7 @@ public class WalletFacade {
Threading.USER_THREAD = Platform::runLater;
// If seed is non-null it means we are restoring from backup.
walletAppKit = new WalletAppKit(params, AppDirectoryUtil.getStorageDirectory(), WALLET_PREFIX) {
walletAppKit = new WalletAppKit(params, AppDirectory.dir().toFile(), WALLET_PREFIX) {
@Override
protected void onSetupCompleted() {
// Don't make the user wait for confirmations for now, as the intention is they're sending it
@ -223,8 +224,8 @@ public class WalletFacade {
wallet.addEventListener(walletEventListener);
Serializable serializable = persistence.read(this, "addressEntryList");
List<AddressEntry> persistedAddressEntryList = (List<AddressEntry>) serializable;
if (serializable instanceof List) {
List<AddressEntry> persistedAddressEntryList = (List<AddressEntry>) serializable;
for (AddressEntry persistedAddressEntry : persistedAddressEntryList) {
persistedAddressEntry.setDeterministicKey(
(DeterministicKey) wallet.findKeyFromPubHash(persistedAddressEntry.getPubKeyHash()));

View File

@ -22,7 +22,7 @@ import io.bitsquare.gui.CachedViewController;
import io.bitsquare.gui.NavigationItem;
import io.bitsquare.gui.ViewController;
import io.bitsquare.gui.components.ValidatingTextField;
import io.bitsquare.gui.trade.createoffer.CreateOfferCodeBehind;
import io.bitsquare.gui.trade.createoffer.CreateOfferCB;
import io.bitsquare.gui.trade.orderbook.OrderBookController;
import io.bitsquare.gui.trade.takeoffer.TakeOfferController;
import io.bitsquare.trade.Direction;
@ -46,7 +46,7 @@ public class TradeController extends CachedViewController {
private static final Logger log = LoggerFactory.getLogger(TradeController.class);
protected OrderBookController orderBookController;
protected CreateOfferCodeBehind createOfferCodeBehind;
protected CreateOfferCB createOfferCodeBehind;
protected TakeOfferController takeOfferController;
protected GuiceFXMLLoader orderBookLoader;
@ -76,7 +76,7 @@ public class TradeController extends CachedViewController {
// TODO find better solution
// Textfield focus out triggers validation, use runLater as quick fix...
((TabPane) root).getSelectionModel().selectedIndexProperty().addListener((observableValue) ->
Platform.runLater(() -> ValidatingTextField.hidePopover()));
Platform.runLater(ValidatingTextField::hidePopover));
}

View File

@ -43,31 +43,34 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Code behind (FXML Controller is part of View, not a classical MVC controller):
* Code behind (We don't call it controller as controller is associated with the classical MVC controller):
* <p>
* Creates Presenter and passes Model from DI to Presenter. Does not hold a reference to Model
* - Knows the presentation model, does not know the model
* - Has no logic and no state
* <p>
* - Setup binding from Presenter to View elements (also bidirectional - Inputs). Binding are only to presenters
* properties, not logical bindings or cross-view element bindings.
* - Listen to UI events (Action) from View and call method in Presenter.
* - Is entry node for hierarchical view graphs. Passes method calls to Presenter. Calls methods on sub views.
* - Creates presentation model and passes model from Guice injection to the presenter. Does not hold any reference to the model.
* //TODO is there a better way for DI of model?
* - Setup binding from presenter to view elements (also bidirectional - used for input data). Binding are only to plain
* presenter properties. There are no logical bindings or cross-view element bindings.
* - Listens to UI events (Actions) from view and calls method in presentation model.
* - Is entry node for view graph and responsible for navigation and creation of new views.
* - Passes application API method calls to Presenter. Calls application methods on sub views.
* - Handle lifecycle and self removal from scene graph.
* - Non declarative (dynamic) view definitions (if it gets larger, then user a ViewBuilder)
* - Has no logic and no state, only view elements and a presenter reference!
* - Can contain non-declarative (dynamic) view definitions (if it gets larger, then use a dedicated ViewBuilder)
* <p>
* View:
* - Mostly declared in FXML. Dynamic parts are declared in Controller. If more view elements need to be defined in
* code then use ViewBuilder.
* - Typically declared in FXML. Dynamic parts are declared in Controller. If more view elements need to be defined in
* code then use a ViewBuilder.
* <p>
* Optional ViewBuilder:
* - Replacement for FXML view definitions.
* ViewBuilder (optional):
* - Additionally or instead of FXML view. If no FXML then controller setup need to be handles by ViewBuilder.
* <p>
* Note: Don't assign the root node as it is defined in the base class!
*/
public class CreateOfferCodeBehind extends CachedViewController {
private static final Logger log = LoggerFactory.getLogger(CreateOfferCodeBehind.class);
public class CreateOfferCB extends CachedViewController {
private static final Logger log = LoggerFactory.getLogger(CreateOfferCB.class);
private final CreateOfferPresenter presenter;
private final CreateOfferPM pm;
@FXML private Label buyLabel, confirmationLabel, txTitleLabel, collateralLabel;
@FXML private ValidatingTextField amountTextField, minAmountTextField, priceTextField, volumeTextField;
@ -86,8 +89,8 @@ public class CreateOfferCodeBehind extends CachedViewController {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public CreateOfferCodeBehind(CreateOfferModel model) {
presenter = new CreateOfferPresenter(model);
public CreateOfferCB(CreateOfferModel model) {
pm = new CreateOfferPM(model);
}
@ -99,17 +102,18 @@ public class CreateOfferCodeBehind extends CachedViewController {
public void initialize(URL url, ResourceBundle rb) {
super.initialize(url, rb);
presenter.onViewInitialized();
pm.onViewInitialized();
balanceTextField.setup(presenter.getWalletFacade(), presenter.address.get());
balanceTextField.setup(pm.getWalletFacade(), pm.address.get());
}
@Override
public void deactivate() {
super.deactivate();
presenter.deactivate();
pm.deactivate();
//TODO check that again
((TradeController) parentController).onCreateOfferViewRemoved();
}
@ -117,7 +121,7 @@ public class CreateOfferCodeBehind extends CachedViewController {
public void activate() {
super.activate();
presenter.activate();
pm.activate();
setupBindings();
setupListeners();
@ -130,7 +134,7 @@ public class CreateOfferCodeBehind extends CachedViewController {
///////////////////////////////////////////////////////////////////////////////////////////
public void setOrderBookFilter(OrderBookFilter orderBookFilter) {
presenter.setOrderBookFilter(orderBookFilter);
pm.setOrderBookFilter(orderBookFilter);
}
@ -140,12 +144,12 @@ public class CreateOfferCodeBehind extends CachedViewController {
@FXML
public void onPlaceOffer() {
presenter.placeOffer();
pm.placeOffer();
}
@FXML
public void onClose() {
presenter.close();
pm.close();
TabPane tabPane = ((TabPane) (root.getParent().getParent()));
tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem());
@ -158,26 +162,26 @@ public class CreateOfferCodeBehind extends CachedViewController {
private void setupListeners() {
volumeTextField.focusedProperty().addListener((o, oldValue, newValue) -> {
presenter.onFocusOutVolumeTextField(oldValue, newValue, volumeTextField.getText());
volumeTextField.setText(presenter.volume.get());
pm.onFocusOutVolumeTextField(oldValue, newValue, volumeTextField.getText());
volumeTextField.setText(pm.volume.get());
});
amountTextField.focusedProperty().addListener((o, oldValue, newValue) -> {
presenter.onFocusOutAmountTextField(oldValue, newValue);
amountTextField.setText(presenter.amount.get());
pm.onFocusOutAmountTextField(oldValue, newValue);
amountTextField.setText(pm.amount.get());
});
priceTextField.focusedProperty().addListener((o, oldValue, newValue) -> {
presenter.onFocusOutPriceTextField(oldValue, newValue);
priceTextField.setText(presenter.price.get());
pm.onFocusOutPriceTextField(oldValue, newValue);
priceTextField.setText(pm.price.get());
});
minAmountTextField.focusedProperty().addListener((o, oldValue, newValue) -> {
presenter.onFocusOutMinAmountTextField(oldValue, newValue);
minAmountTextField.setText(presenter.minAmount.get());
pm.onFocusOutMinAmountTextField(oldValue, newValue);
minAmountTextField.setText(pm.minAmount.get());
});
presenter.needsInputValidation.addListener((o, oldValue, newValue) -> {
pm.needsInputValidation.addListener((o, oldValue, newValue) -> {
if (newValue) {
amountTextField.reValidate();
minAmountTextField.reValidate();
@ -186,67 +190,67 @@ public class CreateOfferCodeBehind extends CachedViewController {
}
});
presenter.showWarningInvalidBtcDecimalPlaces.addListener((o, oldValue, newValue) -> {
pm.showWarningInvalidBtcDecimalPlaces.addListener((o, oldValue, newValue) -> {
if (newValue) {
Popups.openWarningPopup("Warning", "The amount you have entered exceeds the number of allowed decimal" +
" places.\nThe amount has been adjusted to 4 decimal places.");
presenter.showWarningInvalidBtcDecimalPlaces.set(false);
pm.showWarningInvalidBtcDecimalPlaces.set(false);
}
});
presenter.showWarningInvalidFiatDecimalPlaces.addListener((o, oldValue, newValue) -> {
pm.showWarningInvalidFiatDecimalPlaces.addListener((o, oldValue, newValue) -> {
if (newValue) {
Popups.openWarningPopup("Warning", "The amount you have entered exceeds the number of allowed decimal" +
" places.\nThe amount has been adjusted to 2 decimal places.");
presenter.showWarningInvalidFiatDecimalPlaces.set(false);
pm.showWarningInvalidFiatDecimalPlaces.set(false);
}
});
presenter.showWarningInvalidBtcFractions.addListener((o, oldValue, newValue) -> {
pm.showWarningInvalidBtcFractions.addListener((o, oldValue, newValue) -> {
if (newValue) {
Popups.openWarningPopup("Warning", "The total volume you have entered leads to invalid fractional " +
"Bitcoin amounts.\nThe amount has been adjusted and a new total volume be calculated from it.");
presenter.showWarningInvalidBtcFractions.set(false);
volumeTextField.setText(presenter.volume.get());
pm.showWarningInvalidBtcFractions.set(false);
volumeTextField.setText(pm.volume.get());
}
});
presenter.requestPlaceOfferFailed.addListener((o, oldValue, newValue) -> {
pm.requestPlaceOfferFailed.addListener((o, oldValue, newValue) -> {
if (newValue) {
Popups.openErrorPopup("Error", "An error occurred when placing the offer.\n" +
presenter.requestPlaceOfferErrorMessage);
presenter.requestPlaceOfferFailed.set(false);
pm.requestPlaceOfferErrorMessage);
pm.requestPlaceOfferFailed.set(false);
}
});
}
private void setupBindings() {
buyLabel.textProperty().bind(presenter.directionLabel);
amountTextField.textProperty().bindBidirectional(presenter.amount);
priceTextField.textProperty().bindBidirectional(presenter.price);
volumeTextField.textProperty().bindBidirectional(presenter.volume);
buyLabel.textProperty().bind(pm.directionLabel);
amountTextField.textProperty().bindBidirectional(pm.amount);
priceTextField.textProperty().bindBidirectional(pm.price);
volumeTextField.textProperty().bindBidirectional(pm.volume);
minAmountTextField.textProperty().bindBidirectional(presenter.minAmount);
collateralLabel.textProperty().bind(presenter.collateralLabel);
collateralTextField.textProperty().bind(presenter.collateral);
totalToPayTextField.textProperty().bind(presenter.totalToPay);
minAmountTextField.textProperty().bindBidirectional(pm.minAmount);
collateralLabel.textProperty().bind(pm.collateralLabel);
collateralTextField.textProperty().bind(pm.collateral);
totalToPayTextField.textProperty().bind(pm.totalToPay);
addressTextField.amountAsCoinProperty().bind(presenter.totalToPayAsCoin);
addressTextField.paymentLabelProperty().bind(presenter.paymentLabel);
addressTextField.addressProperty().bind(presenter.addressAsString);
addressTextField.amountAsCoinProperty().bind(pm.totalToPayAsCoin);
addressTextField.paymentLabelProperty().bind(pm.paymentLabel);
addressTextField.addressProperty().bind(pm.addressAsString);
bankAccountTypeTextField.textProperty().bind(presenter.bankAccountType);
bankAccountCurrencyTextField.textProperty().bind(presenter.bankAccountCurrency);
bankAccountCountyTextField.textProperty().bind(presenter.bankAccountCounty);
bankAccountTypeTextField.textProperty().bind(pm.bankAccountType);
bankAccountCurrencyTextField.textProperty().bind(pm.bankAccountCurrency);
bankAccountCountyTextField.textProperty().bind(pm.bankAccountCounty);
acceptedCountriesTextField.textProperty().bind(presenter.acceptedCountries);
acceptedLanguagesTextField.textProperty().bind(presenter.acceptedLanguages);
totalFeesTextField.textProperty().bind(presenter.totalFees);
transactionIdTextField.textProperty().bind(presenter.transactionId);
acceptedCountriesTextField.textProperty().bind(pm.acceptedCountries);
acceptedLanguagesTextField.textProperty().bind(pm.acceptedLanguages);
totalFeesTextField.textProperty().bind(pm.totalFees);
transactionIdTextField.textProperty().bind(pm.transactionId);
placeOfferButton.visibleProperty().bind(presenter.isPlaceOfferButtonVisible);
placeOfferButton.disableProperty().bind(presenter.isPlaceOfferButtonDisabled);
closeButton.visibleProperty().bind(presenter.isCloseButtonVisible);
placeOfferButton.visibleProperty().bind(pm.isPlaceOfferButtonVisible);
placeOfferButton.disableProperty().bind(pm.isPlaceOfferButtonDisabled);
closeButton.visibleProperty().bind(pm.isCloseButtonVisible);
//TODO
/* progressIndicator.visibleProperty().bind(viewModel.isOfferPlacedScreen);
@ -280,8 +284,8 @@ public class CreateOfferCodeBehind extends CachedViewController {
ValidationHelper.setupMinAmountInRangeOfAmountValidation(amountTextField,
minAmountTextField,
presenter.amount,
presenter.minAmount,
pm.amount,
pm.minAmount,
amountValidator,
minAmountValidator);
}

View File

@ -43,18 +43,18 @@ import static io.bitsquare.gui.util.BSFormatter.*;
import static javafx.beans.binding.Bindings.createStringBinding;
/**
* Presenter:
* Presentation model:
* Knows Model, does not know the View (CodeBehind)
* <p>
* - Holds data and state of the View (formatting,...)
* - Receive user input via method calls from CodeBehind.
* - Validates input, applies business logic and converts input to Model.
* - Format model data to properties used for binding from the view.
* - Listen to updates from Model via Bindings.
* - Is testable
* - Format model data to properties used for binding from the view (The view setup the bindings).
* - Listen to updates from Model via Bindings (The PM setup the bindings to the model).
* - Can be used for unit testing
*/
class CreateOfferPresenter {
private static final Logger log = LoggerFactory.getLogger(CreateOfferPresenter.class);
class CreateOfferPM {
private static final Logger log = LoggerFactory.getLogger(CreateOfferPM.class);
private CreateOfferModel model;
@ -95,7 +95,7 @@ class CreateOfferPresenter {
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
CreateOfferPresenter(CreateOfferModel model) {
CreateOfferPM(CreateOfferModel model) {
this.model = model;
}

View File

@ -25,7 +25,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.trade.createoffer.CreateOfferCodeBehind"
<AnchorPane fx:id="root" fx:controller="io.bitsquare.gui.trade.createoffer.CreateOfferCB"
prefHeight="500" prefWidth="800" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0"
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"
xmlns:fx="http://javafx.com/fxml">

View File

@ -25,7 +25,7 @@ import io.bitsquare.gui.MainController;
import io.bitsquare.gui.NavigationItem;
import io.bitsquare.gui.ViewController;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.trade.createoffer.CreateOfferCodeBehind;
import io.bitsquare.gui.trade.createoffer.CreateOfferCB;
import io.bitsquare.gui.trade.takeoffer.TakeOfferController;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.gui.util.ImageUtil;
@ -229,7 +229,7 @@ public class OrderBookController extends CachedViewController {
createOfferButton.setDisable(true);
ViewController nextController = parentController.loadViewAndGetChildController(NavigationItem.CREATE_OFFER);
if (nextController != null)
((CreateOfferCodeBehind) nextController).setOrderBookFilter(orderBookFilter);
((CreateOfferCB) nextController).setOrderBookFilter(orderBookFilter);
}
else {
showRegistrationDialog();

View File

@ -70,6 +70,7 @@ public class BSFormatter {
static {
//useMilliBitFormat(true);
setLocale(Locale.US);
}

View File

@ -17,9 +17,6 @@
package io.bitsquare.msg;
import io.bitsquare.BitSquare;
import io.bitsquare.util.AppDirectoryUtil;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@ -61,6 +58,8 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lighthouse.files.AppDirectory;
/**
* The fully bootstrapped P2PNode which is responsible himself for his availability in the messaging system. It saves
* for instance the IP address periodically.
@ -70,12 +69,8 @@ import org.slf4j.LoggerFactory;
public class P2PNode {
private static final Logger log = LoggerFactory.getLogger(P2PNode.class);
private Thread bootstrapToLocalhostThread;
private Thread bootstrapToServerThread;
private KeyPair keyPair;
private final Boolean useDiskStorage;
private final SeedNodeAddress.StaticSeedNodeAddresses defaultStaticSeedNodeAddresses;
private MessageBroker messageBroker;
private PeerAddress storedPeerAddress;
@ -90,11 +85,9 @@ public class P2PNode {
@Inject
public P2PNode(BootstrappedPeerFactory bootstrappedPeerFactory,
@Named("useDiskStorage") Boolean useDiskStorage,
@Named("defaultSeedNode") SeedNodeAddress.StaticSeedNodeAddresses defaultStaticSeedNodeAddresses) {
@Named("useDiskStorage") Boolean useDiskStorage) {
this.bootstrappedPeerFactory = bootstrappedPeerFactory;
this.useDiskStorage = useDiskStorage;
this.defaultStaticSeedNodeAddresses = defaultStaticSeedNodeAddresses;
}
// for unit testing
@ -105,7 +98,6 @@ public class P2PNode {
messageBroker = (message, peerAddress) -> {
};
useDiskStorage = false;
defaultStaticSeedNodeAddresses = SeedNodeAddress.StaticSeedNodeAddresses.LOCALHOST;
}
@ -300,20 +292,13 @@ public class P2PNode {
private void useDiscStorage(boolean useDiscStorage) {
if (useDiscStorage) {
try {
File path = new File(AppDirectoryUtil.getStorageDirectory().getCanonicalPath() + "/" + BitSquare
.getAppName() + "_tomP2P");
if (!path.exists()) {
boolean created = path.mkdir();
if (!created)
throw new RuntimeException("Could not create the directory '" + path + "'");
}
storage = new StorageDisk(Number160.ZERO, path, new DSASignatureFactory());
} catch (IOException e) {
e.printStackTrace();
File path = new File(AppDirectory.dir().toFile() + "/tomP2P");
if (!path.exists()) {
boolean created = path.mkdir();
if (!created)
throw new RuntimeException("Could not create the directory '" + path + "'");
}
storage = new StorageDisk(Number160.ZERO, path, new DSASignatureFactory());
}
else {
storage = new StorageMemory();

View File

@ -1,98 +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 <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.util;
import java.io.File;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AppDirectoryUtil {
private static final Logger log = LoggerFactory.getLogger(AppDirectoryUtil.class);
private static File storageDirectory;
static {
useApplicationDirectory();
log.info("Default application data directory = " + storageDirectory);
}
public static File getStorageDirectory() {
return storageDirectory;
}
public static void setStorageDirectory(File directory) {
storageDirectory = directory;
log.info("User defined application data directory = " + directory);
createDirIfNotExists();
}
public static void useApplicationDirectory() {
setStorageDirectory(getApplicationDirectory());
}
public static void useSystemApplicationDataDirectory() {
setStorageDirectory(getSystemApplicationDataDirectory());
}
public static File getApplicationDirectory() {
File executionRoot =
new File(AppDirectoryUtil.class.getProtectionDomain().getCodeSource().getLocation().getFile());
try {
log.trace("executionRoot " + executionRoot.getCanonicalPath());
// check if it is packed into a mac app (e.g.: "$HOME/Desktop/bitsquare.app/Contents/Java/bitsquare.jar")
if (executionRoot.getCanonicalPath().endsWith(".app/Contents/Java/bitsquare.jar") &&
System.getProperty("os.name").startsWith("Mac"))
return executionRoot.getParentFile().getParentFile().getParentFile().getParentFile();
else if (executionRoot.getCanonicalPath().endsWith(File.separator + "target" + File.separator + "classes"))
return executionRoot.getParentFile(); // dev e.g.:
// $HOME/Documents/_intellij/bitsquare/target/classes -> use target as root
else if (executionRoot.getCanonicalPath().endsWith(File.separator + "bitsquare.jar"))
return executionRoot.getParentFile(); // dev with jar e.g.:
// $HOME/Documents/_intellij/bitsquare/out/artifacts/bitsquare2/bitsquare.jar -> use target as root
else
return executionRoot;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static File getSystemApplicationDataDirectory() {
String osName = System.getProperty("os.name");
if (osName != null && osName.startsWith("Windows"))
return new File(System.getenv("APPDATA") + File.separator + "BitSquare");
else if (osName != null && osName.startsWith("Mac"))
return new File(System.getProperty("user.home") + "/Library/Application Support/BitSquare");
else
return new File(System.getProperty("user.home") + File.separator + "BitSquare");
}
private static void createDirIfNotExists() {
if (!storageDirectory.exists()) {
boolean created = storageDirectory.mkdir();
if (!created)
throw new RuntimeException(
"Could not create the application data directory of '" + storageDirectory + "'");
}
}
}

View File

@ -25,15 +25,17 @@ import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lighthouse.files.AppDirectory;
public class FileUtil {
private static final Logger log = LoggerFactory.getLogger(FileUtil.class);
public static File getFile(String name, String suffix) {
return new File(AppDirectoryUtil.getStorageDirectory(), name + "." + suffix);
return new File(AppDirectory.dir().toFile(), name + "." + suffix);
}
public static File getTempFile(String prefix) throws IOException {
return File.createTempFile("temp_" + prefix, null, AppDirectoryUtil.getStorageDirectory());
return File.createTempFile("temp_" + prefix, null, AppDirectory.dir().toFile());
}
public static void writeTempFileToFile(File tempFile, File file) throws IOException {

View File

@ -0,0 +1,56 @@
package lighthouse.files;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static com.google.common.base.Preconditions.checkNotNull;
// TODO update to open source file when its released
/** Manages the directory where the app stores all its files. */
public class AppDirectory {
public static Path getUserDataDir() {
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
return Paths.get(System.getenv("APPDATA"));
} else if (os.contains("mac")) {
return Paths.get(System.getProperty("user.home"), "Library", "Application Support");
} else {
// Linux and other similar systems, we hope (not Android).
return Paths.get(System.getProperty("user.home"), ".local", "share");
}
}
public static Path getUserDataDir(String appName) {
return getUserDataDir().resolve(appName);
}
public static Path initAppDir(String appName) throws IOException {
AppDirectory.appName = appName;
Path dir = dir();
if (!Files.exists(dir))
Files.createDirectory(dir);
else if (!Files.isWritable(dir))
throw new IOException("App directory is not writeable");
return dir;
}
private static String appName;
private static Path dir;
public static Path dir() {
if (dir == null)
return getUserDataDir(appName);
else
return dir;
}
public static void overrideAppDir(Path newDir) {
dir = checkNotNull(newDir);
}
}

View File

@ -31,24 +31,24 @@
<logger name="io.netty.channel" level="WARN"/>
<logger name="io.netty.buffer" level="WARN"/>
<!--
<logger name="io.bitsquare.gui.ViewController" level="OFF"/>
<logger name="io.bitsquare.gui.CachedViewController" level="OFF"/>
<logger name="io.bitsquare.gui.util.Profiler" level="OFF"/>
<logger name="com.google.bitcoin.core.Wallet" level="OFF"/>
<logger name="com.google.bitcoin.core.MemoryPool" level="OFF"/>
<logger name="com.google.bitcoin.net.discovery.DnsDiscovery" level="OFF"/>
<logger name="com.google.bitcoin.core.DownloadListener" level="OFF"/>
<logger name="com.google.bitcoin.core.TransactionOutput" level="OFF"/>
<logger name="com.google.bitcoin.core.BitcoinSerializer" level="OFF"/>
<logger name="com.google.bitcoin.core.Peer" level="OFF"/>
<logger name="com.google.bitcoin.core.PeerGroup" level="OFF"/>
<logger name="com.google.bitcoin.core.PeerSocketHandler" level="OFF"/>
<logger name="com.google.bitcoin.net.NioClientManager" level="OFF"/>
<logger name="com.google.bitcoin.net.ConnectionHandler" level="OFF"/>
-->
<!--
<logger name="com.google.bitcoin.core.Wallet" level="OFF"/>
<logger name="com.google.bitcoin.core.MemoryPool" level="OFF"/>
<logger name="com.google.bitcoin.net.discovery.DnsDiscovery" level="OFF"/>
<logger name="com.google.bitcoin.core.DownloadListener" level="OFF"/>
<logger name="com.google.bitcoin.core.TransactionOutput" level="OFF"/>
<logger name="com.google.bitcoin.core.BitcoinSerializer" level="OFF"/>
<logger name="com.google.bitcoin.core.Peer" level="OFF"/>
<logger name="com.google.bitcoin.core.PeerGroup" level="OFF"/>
<logger name="com.google.bitcoin.core.PeerSocketHandler" level="OFF"/>
<logger name="com.google.bitcoin.net.NioClientManager" level="OFF"/>
<logger name="com.google.bitcoin.net.ConnectionHandler" level="OFF"/>
-->
</configuration>

View File

@ -18,7 +18,7 @@
package io.bitsquare;
import io.bitsquare.btc.RestrictionsTest;
import io.bitsquare.gui.trade.createoffer.CreateOfferPresenterTest;
import io.bitsquare.gui.trade.createoffer.CreateOfferPMTest;
import io.bitsquare.gui.util.BSFormatterTest;
import io.bitsquare.gui.util.BitSquareConverterTest;
import io.bitsquare.gui.util.BitSquareNumberValidatorTest;
@ -36,7 +36,7 @@ import org.junit.runners.Suite;
P2PNodeTest.class,
FiatValidatorTest.class,
RestrictionsTest.class,
CreateOfferPresenterTest.class,
CreateOfferPMTest.class,
BSFormatterTest.class
})

View File

@ -33,8 +33,8 @@ import org.slf4j.LoggerFactory;
import static org.junit.Assert.*;
public class CreateOfferPresenterTest {
private static final Logger log = LoggerFactory.getLogger(CreateOfferPresenterTest.class);
public class CreateOfferPMTest {
private static final Logger log = LoggerFactory.getLogger(CreateOfferPMTest.class);
@Test
public void testBindings() {
@ -43,7 +43,7 @@ public class CreateOfferPresenterTest {
BSFormatter.setLocale(Locale.US);
BSFormatter.setFiatCurrencyCode("USD");
CreateOfferPresenter presenter = new CreateOfferPresenter(model);
CreateOfferPM presenter = new CreateOfferPM(model);
presenter.onViewInitialized();
model.collateralAsLong.set(100);