Skip to content

Commit

Permalink
Merge branch 'Development'
Browse files Browse the repository at this point in the history
  • Loading branch information
ManfredKarrer committed Aug 8, 2016
2 parents ef46e50 + 1718f83 commit be32c57
Show file tree
Hide file tree
Showing 91 changed files with 1,336 additions and 312 deletions.
2 changes: 1 addition & 1 deletion common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>io.bitsquare</groupId>
<version>0.4.9.2</version>
<version>0.4.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion common/src/main/java/io/bitsquare/app/Version.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class Version {
private static final Logger log = LoggerFactory.getLogger(Version.class);

// The application versions
public static final String VERSION = "0.4.9.2";
public static final String VERSION = "0.4.9.3";

// The version nr. for the objects sent over the network. A change will break the serialization of old objects.
// If objects are used for both network and database the network version is applied.
Expand Down
7 changes: 3 additions & 4 deletions common/src/main/java/io/bitsquare/common/crypto/Hash.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,14 @@ public class Hash {
* @return Hash of data
*/
public static byte[] getHash(byte[] data) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA-256", "BC");
MessageDigest digest = MessageDigest.getInstance("SHA-256", "BC");
digest.update(data, 0, data.length);
return digest.digest();
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
log.error("Could not create MessageDigest for hash. " + e.getMessage());
throw new RuntimeException(e);
}
digest.update(data, 0, data.length);
return digest.digest();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ private boolean fileExists(KeyEntry keyEntry) {
}

public KeyPair loadKeyPair(KeyEntry keyEntry) {
FileUtil.rollingBackup(storageDir, keyEntry.getFileName() + ".key");
FileUtil.rollingBackup(storageDir, keyEntry.getFileName() + ".key", 20);
// long now = System.currentTimeMillis();
try {
KeyFactory keyFactory = KeyFactory.getInstance(keyEntry.getAlgorithm(), "BC");
Expand Down
48 changes: 28 additions & 20 deletions common/src/main/java/io/bitsquare/storage/FileManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ public synchronized void removeAndBackupFile(String fileName) throws IOException
renameTempFileToFile(storageFile, corruptedFile);
}

public synchronized void backupFile(String fileName) throws IOException {
FileUtil.rollingBackup(dir, fileName);
public synchronized void backupFile(String fileName, int numMaxBackupFiles) throws IOException {
FileUtil.rollingBackup(dir, fileName, numMaxBackupFiles);
}

///////////////////////////////////////////////////////////////////////////////////////////
Expand All @@ -171,30 +171,36 @@ private synchronized void saveToFile(T serializable, File dir, File storageFile)
File tempFile = null;
FileOutputStream fileOutputStream = null;
ObjectOutputStream objectOutputStream = null;
PrintWriter printWriter = null;
try {
if (!dir.exists())
if (!dir.mkdir())
log.warn("make dir failed");

tempFile = File.createTempFile("temp", null, dir);

// Don't use auto closeable resources in try() as we would need too many try/catch clauses (for tempFile)
// and we need to close it
// manually before replacing file with temp file
fileOutputStream = new FileOutputStream(tempFile);
objectOutputStream = new ObjectOutputStream(fileOutputStream);

objectOutputStream.writeObject(serializable);
// Attempt to force the bits to hit the disk. In reality the OS or hard disk itself may still decide
// to not write through to physical media for at least a few seconds, but this is the best we can do.
fileOutputStream.flush();
fileOutputStream.getFD().sync();

// Close resources before replacing file with temp file because otherwise it causes problems on windows
// when rename temp file
fileOutputStream.close();
objectOutputStream.close();

tempFile.deleteOnExit();
if (serializable instanceof PlainTextWrapper) {
// When we dump json files we don't want to safe it as java serialized string objects, so we use PrintWriter instead.
printWriter = new PrintWriter(tempFile);
printWriter.println(((PlainTextWrapper) serializable).plainText);
} else {
// Don't use auto closeable resources in try() as we would need too many try/catch clauses (for tempFile)
// and we need to close it
// manually before replacing file with temp file
fileOutputStream = new FileOutputStream(tempFile);
objectOutputStream = new ObjectOutputStream(fileOutputStream);

objectOutputStream.writeObject(serializable);
// Attempt to force the bits to hit the disk. In reality the OS or hard disk itself may still decide
// to not write through to physical media for at least a few seconds, but this is the best we can do.
fileOutputStream.flush();
fileOutputStream.getFD().sync();

// Close resources before replacing file with temp file because otherwise it causes problems on windows
// when rename temp file
fileOutputStream.close();
objectOutputStream.close();
}
renameTempFileToFile(tempFile, storageFile);
} catch (Throwable t) {
log.error("storageFile " + storageFile.toString());
Expand All @@ -212,6 +218,8 @@ private synchronized void saveToFile(T serializable, File dir, File storageFile)
objectOutputStream.close();
if (fileOutputStream != null)
fileOutputStream.close();
if (printWriter != null)
printWriter.close();
} catch (IOException e) {
// We swallow that
e.printStackTrace();
Expand Down
34 changes: 23 additions & 11 deletions common/src/main/java/io/bitsquare/storage/FileUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,16 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.*;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

public class FileUtil {
private static final Logger log = LoggerFactory.getLogger(FileUtil.class);
/** Number of copies to keep in backup directory. */
private static final int KEPT_BACKUPS = 10;

public static void rollingBackup(File dir, String fileName) {
public static void rollingBackup(File dir, String fileName, int numMaxBackupFiles) {
if (dir.exists()) {
File backupDir = new File(Paths.get(dir.getAbsolutePath(), "backup").toString());
if (!backupDir.exists())
Expand All @@ -39,7 +35,7 @@ public static void rollingBackup(File dir, String fileName) {
try {
Files.copy(origFile, backupFile);

pruneBackup(backupFileDir);
pruneBackup(backupFileDir, numMaxBackupFiles);
} catch (IOException e) {
log.error("Backup key failed: " + e.getMessage());
e.printStackTrace();
Expand All @@ -48,22 +44,22 @@ public static void rollingBackup(File dir, String fileName) {
}
}

private static void pruneBackup(File backupDir) {
private static void pruneBackup(File backupDir, int numMaxBackupFiles) {
if (backupDir.isDirectory()) {
File[] files = backupDir.listFiles();
if (files != null) {
List<File> filesList = Arrays.asList(files);
if (filesList.size() > KEPT_BACKUPS) {
if (filesList.size() > numMaxBackupFiles) {
filesList.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));
File file = filesList.get(0);
if (file.isFile()) {
if (!file.delete())
log.error("Failed to delete file: " + file);
else
pruneBackup(backupDir);
pruneBackup(backupDir, numMaxBackupFiles);

} else {
pruneBackup(new File(Paths.get(backupDir.getAbsolutePath(), file.getName()).toString()));
pruneBackup(new File(Paths.get(backupDir.getAbsolutePath(), file.getName()).toString()), numMaxBackupFiles);
}
}
}
Expand All @@ -80,4 +76,20 @@ public static void deleteDirectory(File file) throws IOException {
if (file.exists() && !file.delete())
throw new FileNotFoundException("Failed to delete file: " + file);
}

public static void resourceToFile(String resourcePath, File destinationFile) throws ResourceNotFoundException, IOException {
InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream(resourcePath);
if (inputStream == null)
throw new ResourceNotFoundException(resourcePath);

try (FileOutputStream fileOutputStream = new FileOutputStream(destinationFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
throw e;
}
}
}
18 changes: 18 additions & 0 deletions common/src/main/java/io/bitsquare/storage/PlainTextWrapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.bitsquare.storage;

import java.io.Serializable;

/**
* Used to wrap a plaintext string to distinguish at file storage and safe it as plain text instead of a serialized java object.
*/
public class PlainTextWrapper implements Serializable {
// That object is not saved to disc it is only of type Serializable to support the persistent framework.
// SerialVersionUID has no relevance here.
private static final long serialVersionUID = 0;

public final String plainText;

public PlainTextWrapper(String plainText) {
this.plainText = plainText;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.bitsquare.storage;

public class ResourceNotFoundException extends Exception {
public ResourceNotFoundException(String path) {
super("Resource not found: path = " + path);
}
}
14 changes: 13 additions & 1 deletion common/src/main/java/io/bitsquare/storage/Storage.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public interface DataBaseCorruptionHandler {
private File storageFile;
private T serializable;
private String fileName;
private int numMaxBackupFiles = 10;


///////////////////////////////////////////////////////////////////////////////////////////
Expand All @@ -76,6 +77,13 @@ public Storage(@Named(DIR_KEY) File dir) {
this.dir = dir;
}

@Nullable
public void initWithFileName(String fileName) {
this.fileName = fileName;
storageFile = new File(dir, fileName);
fileManager = new FileManager<>(dir, storageFile, 300);
}

@Nullable
public T initAndGetPersistedWithFileName(String fileName) {
this.fileName = fileName;
Expand Down Expand Up @@ -108,6 +116,10 @@ public void queueUpForSave(long delayInMilli) {
queueUpForSave(serializable, delayInMilli);
}

public void setNumMaxBackupFiles(int numMaxBackupFiles) {
this.numMaxBackupFiles = numMaxBackupFiles;
}

// Save delayed and on a background thread
private void queueUpForSave(T serializable) {
if (serializable != null) {
Expand Down Expand Up @@ -152,7 +164,7 @@ private T getPersisted() {

// If we did not get any exception we can be sure the data are consistent so we make a backup
now = System.currentTimeMillis();
fileManager.backupFile(fileName);
fileManager.backupFile(fileName, numMaxBackupFiles);
log.trace("Backup {} completed in {}msec", storageFile, System.currentTimeMillis() - now);

return persistedObject;
Expand Down
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>io.bitsquare</groupId>
<version>0.4.9.2</version>
<version>0.4.9.3</version>
</parent>

<artifactId>core</artifactId>
Expand Down
8 changes: 6 additions & 2 deletions core/src/main/java/io/bitsquare/app/BitsquareEnvironment.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public static void setDefaultAppName(String defaultAppName) {
private final String logLevel;
private BitcoinNetwork bitcoinNetwork;
private final String btcSeedNodes, seedNodes, ignoreDevMsg, useTorForBtc, useTorForHttp,
myAddress, banList, dumpStatistics, socks5ProxyBtcAddress, socks5ProxyHttpAddress;
myAddress, banList, dumpStatistics, maxMemory, socks5ProxyBtcAddress, socks5ProxyHttpAddress;

public BitsquareEnvironment(OptionSet options) {
this(new JOptCommandLinePropertySource(BITSQUARE_COMMANDLINE_PROPERTY_SOURCE_NAME, checkNotNull(
Expand Down Expand Up @@ -141,7 +141,10 @@ protected BitsquareEnvironment(PropertySource commandLineProperties) {
dumpStatistics = commandLineProperties.containsProperty(CoreOptionKeys.DUMP_STATISTICS) ?
(String) commandLineProperties.getProperty(CoreOptionKeys.DUMP_STATISTICS) :
"";

maxMemory = commandLineProperties.containsProperty(CoreOptionKeys.MAX_MEMORY) ?
(String) commandLineProperties.getProperty(CoreOptionKeys.MAX_MEMORY) :
"";

seedNodes = commandLineProperties.containsProperty(NetworkOptionKeys.SEED_NODES_KEY) ?
(String) commandLineProperties.getProperty(NetworkOptionKeys.SEED_NODES_KEY) :
"";
Expand Down Expand Up @@ -239,6 +242,7 @@ private PropertySource<?> defaultProperties() {
setProperty(CoreOptionKeys.IGNORE_DEV_MSG_KEY, ignoreDevMsg);
setProperty(CoreOptionKeys.DUMP_STATISTICS, dumpStatistics);
setProperty(CoreOptionKeys.APP_NAME_KEY, appName);
setProperty(CoreOptionKeys.MAX_MEMORY, maxMemory);
setProperty(CoreOptionKeys.USER_DATA_DIR_KEY, userDataDir);

setProperty(BtcOptionKeys.BTC_SEED_NODES, btcSeedNodes);
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/io/bitsquare/app/BitsquareExecutable.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ protected void customizeOptionParsing(OptionParser parser) {
.withRequiredArg();
parser.accepts(CoreOptionKeys.APP_NAME_KEY, description("Application name", DEFAULT_APP_NAME))
.withRequiredArg();
parser.accepts(CoreOptionKeys.MAX_MEMORY, description("Max. permitted memory (used only at headless versions)", 600))
.withRequiredArg();
parser.accepts(CoreOptionKeys.APP_DATA_DIR_KEY, description("Application data directory", DEFAULT_APP_DATA_DIR))
.withRequiredArg();
parser.accepts(CoreOptionKeys.IGNORE_DEV_MSG_KEY, description("If set to true all signed messages from Bitsquare developers are ignored " +
Expand Down
1 change: 1 addition & 0 deletions core/src/main/java/io/bitsquare/app/CoreOptionKeys.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ public class CoreOptionKeys {
public static final String USER_DATA_DIR_KEY = "userDataDir";
public static final String APP_NAME_KEY = "appName";
public static final String APP_DATA_DIR_KEY = "appDataDir";
public static final String MAX_MEMORY = "maxMemory";
}
29 changes: 22 additions & 7 deletions core/src/main/java/io/bitsquare/arbitration/DisputeResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public enum Reason {
public final String tradeId;
public final int traderId;
private DisputeFeePolicy disputeFeePolicy;

private Winner winner;
private Reason reason;
private boolean tamperProofEvidence;
private boolean idVerification;
private boolean screenCast;
Expand All @@ -70,8 +71,6 @@ public enum Reason {
private String arbitratorAddressAsString;
private byte[] arbitratorPubKey;
private long closeDate;
private Winner winner;
private Reason reason;

transient private BooleanProperty tamperProofEvidenceProperty = new SimpleBooleanProperty();
transient private BooleanProperty idVerificationProperty = new SimpleBooleanProperty();
Expand Down Expand Up @@ -251,23 +250,40 @@ public boolean equals(Object o) {
if (tradeId != null ? !tradeId.equals(that.tradeId) : that.tradeId != null) return false;
if (disputeFeePolicy != that.disputeFeePolicy) return false;
if (reason != that.reason) return false;

if (disputeFeePolicy != null && that.disputeFeePolicy != null && disputeFeePolicy.ordinal() != that.disputeFeePolicy.ordinal())
return false;
else if ((disputeFeePolicy == null && that.disputeFeePolicy != null) || (disputeFeePolicy != null && that.disputeFeePolicy == null))
return false;

if (reason != null && that.reason != null && reason.ordinal() != that.reason.ordinal())
return false;
else if ((reason == null && that.reason != null) || (reason != null && that.reason == null))
return false;

if (winner != null && that.winner != null && winner.ordinal() != that.winner.ordinal())
return false;
else if ((winner == null && that.winner != null) || (winner != null && that.winner == null))
return false;

if (summaryNotes != null ? !summaryNotes.equals(that.summaryNotes) : that.summaryNotes != null) return false;
if (disputeCommunicationMessage != null ? !disputeCommunicationMessage.equals(that.disputeCommunicationMessage) : that.disputeCommunicationMessage != null)
return false;
if (!Arrays.equals(arbitratorSignature, that.arbitratorSignature)) return false;
if (arbitratorAddressAsString != null ? !arbitratorAddressAsString.equals(that.arbitratorAddressAsString) : that.arbitratorAddressAsString != null)
return false;
if (!Arrays.equals(arbitratorPubKey, that.arbitratorPubKey)) return false;
return winner == that.winner;
return true;

}

@Override
public int hashCode() {
int result = tradeId != null ? tradeId.hashCode() : 0;
result = 31 * result + traderId;
result = 31 * result + (disputeFeePolicy != null ? disputeFeePolicy.hashCode() : 0);
result = 31 * result + (reason != null ? reason.hashCode() : 0);
result = 31 * result + (disputeFeePolicy != null ? disputeFeePolicy.ordinal() : 0);
result = 31 * result + (reason != null ? reason.ordinal() : 0);
result = 31 * result + (winner != null ? winner.ordinal() : 0);
result = 31 * result + (tamperProofEvidence ? 1 : 0);
result = 31 * result + (idVerification ? 1 : 0);
result = 31 * result + (screenCast ? 1 : 0);
Expand All @@ -280,7 +296,6 @@ public int hashCode() {
result = 31 * result + (arbitratorAddressAsString != null ? arbitratorAddressAsString.hashCode() : 0);
result = 31 * result + (arbitratorPubKey != null ? Arrays.hashCode(arbitratorPubKey) : 0);
result = 31 * result + (int) (closeDate ^ (closeDate >>> 32));
result = 31 * result + (winner != null ? winner.hashCode() : 0);
return result;
}
}
Loading

0 comments on commit be32c57

Please sign in to comment.