mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-11-02 12:26:45 +00:00
jpms related changes for v1.4.2-beta
This commit is contained in:
parent
1208baf00e
commit
7f178b5f67
8 changed files with 132 additions and 26 deletions
|
@ -5,7 +5,7 @@ plugins {
|
|||
id 'org.beryx.jlink' version '2.22.0'
|
||||
}
|
||||
|
||||
def sparrowVersion = '1.4.1'
|
||||
def sparrowVersion = '1.4.2'
|
||||
def os = org.gradle.internal.os.OperatingSystem.current()
|
||||
def osName = os.getFamilyName()
|
||||
if(os.macOsX) {
|
||||
|
@ -50,7 +50,7 @@ dependencies {
|
|||
exclude group: 'org.slf4j'
|
||||
}
|
||||
implementation('org.jdbi:jdbi3-sqlobject:3.20.0')
|
||||
implementation('org.flywaydb:flyway-core:7.10.1-SNAPSHOT')
|
||||
implementation('org.flywaydb:flyway-core:7.10.5-SNAPSHOT')
|
||||
implementation('org.fxmisc.richtext:richtextfx:0.10.4')
|
||||
implementation('no.tornado:tornadofx-controls:1.0.4')
|
||||
implementation('com.google.zxing:javase:3.4.0')
|
||||
|
@ -138,6 +138,8 @@ jlink {
|
|||
requires 'com.fasterxml.jackson.databind'
|
||||
requires 'jdk.crypto.cryptoki'
|
||||
requires 'java.management'
|
||||
uses 'org.flywaydb.core.extensibility.FlywayExtension'
|
||||
uses 'org.flywaydb.core.internal.database.DatabaseType'
|
||||
}
|
||||
|
||||
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages', '--ignore-signing-information', '--exclude-files', '**.png']
|
||||
|
@ -161,7 +163,8 @@ jlink {
|
|||
"--add-opens=javafx.graphics/com.sun.javafx.application=com.sparrowwallet.sparrow",
|
||||
"--add-opens=java.base/java.net=com.sparrowwallet.sparrow",
|
||||
"--add-reads=com.sparrowwallet.merged.module=java.desktop",
|
||||
"--add-reads=com.sparrowwallet.merged.module=java.sql"]
|
||||
"--add-reads=com.sparrowwallet.merged.module=java.sql",
|
||||
"--add-reads=com.sparrowwallet.merged.module=com.sparrowwallet.sparrow"]
|
||||
|
||||
if(os.macOsX) {
|
||||
jvmArgs += "--add-opens=javafx.graphics/com.sun.glass.ui.mac=com.sparrowwallet.merged.module"
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.4.1</string>
|
||||
<string>1.4.2</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<!-- See https://developer.apple.com/app-store/categories/ for list of AppStore categories -->
|
||||
|
|
|
@ -12,7 +12,7 @@ public class AboutController {
|
|||
private Label title;
|
||||
|
||||
public void initializeView() {
|
||||
title.setText(MainApp.APP_NAME + " " + MainApp.APP_VERSION);
|
||||
title.setText(MainApp.APP_NAME + " " + MainApp.APP_VERSION + MainApp.APP_VERSION_SUFFIX);
|
||||
}
|
||||
|
||||
public void setStage(Stage stage) {
|
||||
|
|
|
@ -31,7 +31,8 @@ import java.util.stream.Collectors;
|
|||
public class MainApp extends Application {
|
||||
public static final String APP_ID = "com.sparrowwallet.sparrow";
|
||||
public static final String APP_NAME = "Sparrow";
|
||||
public static final String APP_VERSION = "1.4.1";
|
||||
public static final String APP_VERSION = "1.4.2";
|
||||
public static final String APP_VERSION_SUFFIX = "-beta";
|
||||
public static final String APP_HOME_PROPERTY = "sparrow.home";
|
||||
public static final String NETWORK_ENV_PROPERTY = "SPARROW_NETWORK";
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ public class Hwi {
|
|||
String hwiPath = hwiExecutable.getAbsolutePath();
|
||||
if(command.isTestFirst() && (hwiPath.contains(tmpDir) || hwiPath.startsWith(homeDir.getAbsolutePath())) && (!hwiPath.contains(HWI_VERSION_DIR) || !testHwi(hwiExecutable))) {
|
||||
if(Platform.getCurrent() == Platform.OSX) {
|
||||
deleteDirectory(hwiExecutable.getParentFile());
|
||||
IOUtils.deleteDirectory(hwiExecutable.getParentFile());
|
||||
} else {
|
||||
hwiExecutable.delete();
|
||||
}
|
||||
|
@ -339,17 +339,6 @@ public class Hwi {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean deleteDirectory(File directoryToBeDeleted) {
|
||||
File[] allContents = directoryToBeDeleted.listFiles();
|
||||
if (allContents != null) {
|
||||
for (File file : allContents) {
|
||||
deleteDirectory(file);
|
||||
}
|
||||
}
|
||||
|
||||
return directoryToBeDeleted.delete();
|
||||
}
|
||||
|
||||
public static File newDirectory(File destinationDir, ZipEntry zipEntry, Set<PosixFilePermission> setFilePermissions) throws IOException {
|
||||
String destDirPath = destinationDir.getCanonicalPath();
|
||||
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
package com.sparrowwallet.sparrow.io;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class IOUtils {
|
||||
public static FileType getFileType(File file) {
|
||||
|
@ -38,4 +47,75 @@ public class IOUtils {
|
|||
|
||||
return FileType.UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* List directory contents for a resource folder. Not recursive.
|
||||
* This is basically a brute-force implementation.
|
||||
* Works for regular files, JARs and Java modules.
|
||||
*
|
||||
* @param clazz Any java class that lives in the same place as the resources you want.
|
||||
* @param path Should end with "/", but not start with one.
|
||||
* @return Just the name of each member item, not the full paths.
|
||||
* @throws URISyntaxException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String[] getResourceListing(Class clazz, String path) throws URISyntaxException, IOException {
|
||||
URL dirURL = clazz.getClassLoader().getResource(path);
|
||||
if(dirURL != null && dirURL.getProtocol().equals("file")) {
|
||||
/* A file path: easy enough */
|
||||
return new File(dirURL.toURI()).list();
|
||||
}
|
||||
|
||||
if(dirURL == null) {
|
||||
/*
|
||||
* In case of a jar file, we can't actually find a directory.
|
||||
* Have to assume the same jar as clazz.
|
||||
*/
|
||||
String me = clazz.getName().replace(".", "/")+".class";
|
||||
dirURL = clazz.getClassLoader().getResource(me);
|
||||
}
|
||||
|
||||
if(dirURL.getProtocol().equals("jar")) {
|
||||
/* A JAR path */
|
||||
String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); //strip out only the JAR file
|
||||
JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
|
||||
Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
|
||||
Set<String> result = new HashSet<String>(); //avoid duplicates in case it is a subdirectory
|
||||
while(entries.hasMoreElements()) {
|
||||
String name = entries.nextElement().getName();
|
||||
if(name.startsWith(path)) { //filter according to the path
|
||||
String entry = name.substring(path.length());
|
||||
int checkSubdir = entry.indexOf("/");
|
||||
if (checkSubdir >= 0) {
|
||||
// if it is a subdirectory, we just return the directory name
|
||||
entry = entry.substring(0, checkSubdir);
|
||||
}
|
||||
result.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return result.toArray(new String[result.size()]);
|
||||
}
|
||||
|
||||
if(dirURL.getProtocol().equals("jrt")) {
|
||||
java.nio.file.FileSystem jrtFs = FileSystems.newFileSystem(URI.create("jrt:/"), Collections.emptyMap());
|
||||
Path resourcePath = jrtFs.getPath("modules/com.sparrowwallet.sparrow", path);
|
||||
return Files.list(resourcePath).map(filePath -> filePath.getFileName().toString()).toArray(String[]::new);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Cannot list files for URL " + dirURL);
|
||||
}
|
||||
|
||||
public static boolean deleteDirectory(File directory) {
|
||||
try {
|
||||
Files.walk(directory.toPath())
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.map(Path::toFile)
|
||||
.forEach(File::delete);
|
||||
} catch(IOException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.sparrowwallet.sparrow.io.db;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.common.io.Files;
|
||||
import com.sparrowwallet.drongo.Utils;
|
||||
import com.sparrowwallet.drongo.crypto.Argon2KeyDeriver;
|
||||
import com.sparrowwallet.drongo.crypto.AsymmetricKeyDeriver;
|
||||
|
@ -29,6 +30,7 @@ import java.io.*;
|
|||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -46,6 +48,7 @@ public class DbPersistence implements Persistence {
|
|||
public static final byte[] HEADER_MAGIC_1 = "SPRW1\n".getBytes(StandardCharsets.UTF_8);
|
||||
private static final String H2_USER = "sa";
|
||||
private static final String H2_PASSWORD = "";
|
||||
public static final String MIGRATION_RESOURCES_DIR = "com/sparrowwallet/sparrow/sql/";
|
||||
|
||||
private HikariDataSource dataSource;
|
||||
private AsymmetricKeyDeriver keyDeriver;
|
||||
|
@ -299,8 +302,9 @@ public class DbPersistence implements Persistence {
|
|||
}
|
||||
|
||||
private void migrate(Storage storage, String schema, ECKey encryptionKey) throws StorageException {
|
||||
File migrationDir = getMigrationDir();
|
||||
try {
|
||||
Flyway flyway = getFlyway(storage, schema, getFilePassword(encryptionKey));
|
||||
Flyway flyway = getFlyway(storage, schema, getFilePassword(encryptionKey), migrationDir);
|
||||
flyway.migrate();
|
||||
} catch(FlywayValidateException e) {
|
||||
log.error("Failed to open wallet file. Validation error during schema migration.", e);
|
||||
|
@ -308,20 +312,22 @@ public class DbPersistence implements Persistence {
|
|||
} catch(FlywayException e) {
|
||||
log.error("Failed to open wallet file. ", e);
|
||||
throw new StorageException("Failed to open wallet file.\n" + e.getMessage(), e);
|
||||
} finally {
|
||||
IOUtils.deleteDirectory(migrationDir);
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanAndMigrate(Storage storage, String schema, String password) throws StorageException {
|
||||
File migrationDir = getMigrationDir();
|
||||
try {
|
||||
boolean existing = (dataSource == null);
|
||||
Flyway flyway = getFlyway(storage, schema, password);
|
||||
if(existing) {
|
||||
flyway.clean();
|
||||
}
|
||||
Flyway flyway = getFlyway(storage, schema, password, migrationDir);
|
||||
flyway.clean();
|
||||
flyway.migrate();
|
||||
} catch(FlywayException e) {
|
||||
log.error("Failed to save wallet file.", e);
|
||||
throw new StorageException("Failed to save wallet file.\n" + e.getMessage(), e);
|
||||
} finally {
|
||||
IOUtils.deleteDirectory(migrationDir);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -504,8 +510,30 @@ public class DbPersistence implements Persistence {
|
|||
return jdbi;
|
||||
}
|
||||
|
||||
private Flyway getFlyway(Storage storage, String schema, String password) throws StorageException {
|
||||
return Flyway.configure().dataSource(getDataSource(storage, password)).locations("com/sparrowwallet/sparrow/sql").schemas(schema).load();
|
||||
private Flyway getFlyway(Storage storage, String schema, String password, File resourcesDir) throws StorageException {
|
||||
return Flyway.configure().dataSource(getDataSource(storage, password)).locations("filesystem:" + resourcesDir.getAbsolutePath()).schemas(schema).failOnMissingLocations(true).load();
|
||||
}
|
||||
|
||||
//Flyway does not support JPMS yet, so the migration files are extracted to a temp dir in order to avoid classloader encapsulation issues
|
||||
private File getMigrationDir() {
|
||||
File migrationDir = Files.createTempDir();
|
||||
try {
|
||||
String[] files = IOUtils.getResourceListing(DbPersistence.class, MIGRATION_RESOURCES_DIR);
|
||||
for(String name : files) {
|
||||
File targetFile = new File(migrationDir, name);
|
||||
try(InputStream inputStream = DbPersistence.class.getResourceAsStream("/" + MIGRATION_RESOURCES_DIR + name)) {
|
||||
if(inputStream != null) {
|
||||
java.nio.file.Files.copy(inputStream, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
} else {
|
||||
log.error("Could not load resource at /" + MIGRATION_RESOURCES_DIR + name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
log.error("Could not extract migration resources", e);
|
||||
}
|
||||
|
||||
return migrationDir;
|
||||
}
|
||||
|
||||
private HikariDataSource getDataSource(Storage storage, String password) throws StorageException {
|
||||
|
@ -518,11 +546,15 @@ public class DbPersistence implements Persistence {
|
|||
|
||||
private HikariDataSource createDataSource(File walletFile, String password) throws StorageException {
|
||||
try {
|
||||
Class.forName("org.h2.Driver");
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setJdbcUrl(getUrl(walletFile, password));
|
||||
config.setUsername(H2_USER);
|
||||
config.setPassword(password == null ? H2_PASSWORD : password + " " + H2_PASSWORD);
|
||||
return new HikariDataSource(config);
|
||||
} catch(ClassNotFoundException e) {
|
||||
log.error("Cannot find H2 driver", e);
|
||||
throw new StorageException("Cannot find H2 driver", e);
|
||||
} catch(HikariPool.PoolInitializationException e) {
|
||||
if(e.getMessage() != null && e.getMessage().contains("Database may be already in use")) {
|
||||
log.error("Wallet file may already be in use. Make sure the application is not running elsewhere.", e);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<logger name="sun.net.www.protocol.http.HttpURLConnection" level="INFO" />
|
||||
<logger name="h2database" level="ERROR" />
|
||||
<logger name="com.zaxxer.hikari.HikariDataSource" level="WARN" />
|
||||
<logger name="com.zaxxer.hikari.pool.HikariPool" level="ERROR" />
|
||||
<logger name="org.flywaydb.core.internal.command.DbValidate" level="WARN" />
|
||||
<logger name="org.flywaydb.core.internal.command.DbMigrate" level="WARN" />
|
||||
<logger name="org.flywaydb.core.internal.command.DbClean" level="ERROR" />
|
||||
|
|
Loading…
Reference in a new issue