diff --git a/pom.xml b/pom.xml index c09cd7c3..386a04aa 100644 --- a/pom.xml +++ b/pom.xml @@ -115,7 +115,7 @@ - + org.apache.maven.plugins maven-dependency-plugin @@ -131,11 +131,14 @@ - + org.apache.maven.plugins maven-surefire-plugin 3.3.0 + + true + @@ -173,7 +176,8 @@ org.openjfx javafx-graphics ${javafx.version} - + + jakarta.xml.bind jakarta.xml.bind-api @@ -239,7 +243,7 @@ commons-io commons-io 2.17.0 - + org.apache.logging.log4j log4j-core diff --git a/src/main/java/org/hypernomicon/Const.java b/src/main/java/org/hypernomicon/Const.java index 5d724623..db0e7a40 100644 --- a/src/main/java/org/hypernomicon/Const.java +++ b/src/main/java/org/hypernomicon/Const.java @@ -56,6 +56,7 @@ public final class Const public static final String HDB_DEFAULT_FILENAME = "database.hdb", + BLANK_DB_RESOURCE_NAME = "resources/blank_db.zip", PREF_KEY_SETTINGS_VERSION = "settingsVersion", PREF_KEY_NOTIFY_USER_NOT_LINKED = "notifyUnlinked", diff --git a/src/main/java/org/hypernomicon/dialogs/LockedDlgCtrlr.java b/src/main/java/org/hypernomicon/dialogs/LockedDlgCtrlr.java index 22578c3a..bcbc3b66 100644 --- a/src/main/java/org/hypernomicon/dialogs/LockedDlgCtrlr.java +++ b/src/main/java/org/hypernomicon/dialogs/LockedDlgCtrlr.java @@ -24,7 +24,6 @@ import javafx.scene.control.Label; import javafx.scene.control.TextArea; -import org.apache.commons.lang3.exception.ExceptionUtils; import org.hypernomicon.HyperTask.HyperThread; import org.hypernomicon.InterComputerMsg; import org.hypernomicon.util.DesktopUtil; @@ -130,19 +129,17 @@ else if (sentMsg.getType() == hmtEchoRequest) //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- - public LockedDlgCtrlr(String title, Throwable e) + public LockedDlgCtrlr(String title, String text) { super("LockedDlg", title, true); otherHostName = ""; otherCompName = ""; - String stacktrace = ExceptionUtils.getStackTrace(e); - - taOutput.setText(stacktrace); + taOutput.setText(text); btnTryTerminate.setText("Copy to Clipboard"); - btnTryTerminate.setOnAction(event -> copyToClipboard(stacktrace)); + btnTryTerminate.setOnAction(event -> copyToClipboard(text)); setAllVisible(false, btnTryComm, btnOverride, btnStop, lblSeconds); } diff --git a/src/main/java/org/hypernomicon/util/UIUtil.java b/src/main/java/org/hypernomicon/util/UIUtil.java index a4af5c72..13ce3039 100644 --- a/src/main/java/org/hypernomicon/util/UIUtil.java +++ b/src/main/java/org/hypernomicon/util/UIUtil.java @@ -30,6 +30,7 @@ import javafx.beans.value.ObservableDoubleValue; import org.apache.commons.lang3.SystemUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.mutable.MutableBoolean; import org.controlsfx.control.MasterDetailPane; import org.hypernomicon.dialogs.LockedDlgCtrlr; @@ -634,12 +635,20 @@ private static void scalePropertiesForDPI(DoubleProperty... props) } } +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + + public static void showLongMessage(String title, String text) + { + new LockedDlgCtrlr(title, text).showModal(); + } + //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- public static void showStackTrace(Throwable e) { - new LockedDlgCtrlr("Error", e).showModal(); + showLongMessage("Error", ExceptionUtils.getStackTrace(e)); } //--------------------------------------------------------------------------- diff --git a/src/main/java/org/hypernomicon/util/Util.java b/src/main/java/org/hypernomicon/util/Util.java index 870eed97..cba58bb9 100644 --- a/src/main/java/org/hypernomicon/util/Util.java +++ b/src/main/java/org/hypernomicon/util/Util.java @@ -21,6 +21,8 @@ import org.hypernomicon.HyperTask.HyperThread; import org.hypernomicon.util.filePath.FilePath; +import static org.hypernomicon.Const.*; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -40,9 +42,11 @@ import java.nio.file.AccessDeniedException; import java.nio.file.FileSystemException; import java.nio.file.Files; +import java.security.CodeSource; import java.security.DigestOutputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.security.ProtectionDomain; import java.text.NumberFormat; import java.time.Instant; import java.time.ZoneId; @@ -67,6 +71,8 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -779,14 +785,44 @@ public static String convertToEnglishCharsWithMap(String input, List po public static String manifestValue(String key) { - URL url = App.class.getResource("/META-INF/MANIFEST.MF"); + URL jarUrl; - if (url != null) try + try + { + jarUrl = nullSwitch(nullSwitch(App.class.getProtectionDomain(), null, ProtectionDomain::getCodeSource), null, CodeSource::getLocation); + + if (jarUrl != null) + { + try (InputStream jarStream = jarUrl.openStream()) + { + if (jarStream != null) try (JarInputStream jis = new JarInputStream(jarStream)) + { + Manifest manifest = jis.getManifest(); + + return manifest == null ? "" : nullSwitch(manifest.getMainAttributes(), "", attributes -> safeStr(attributes.getValue(key))); + } + } + } + } + catch (SecurityException | IOException e) { - URLConnection c = url.openConnection(); + noOp(); + } + + // Security exception likely happened so try less reliable method - if (c instanceof JarURLConnection jarURLConnection) - return safeStr(nullSwitch(jarURLConnection.getManifest(), "", manifest -> manifest.getMainAttributes().getValue(key))); + jarUrl = App.class.getResource(BLANK_DB_RESOURCE_NAME); // Get the URL for a resource that will only exist in the Hypernomicon jar file. + // Most jar files will have META-INF/MANIFEST.MF so we are likely to get the + if (jarUrl != null) try // wrong URL if we search for that resource name (even though it is the one we + { // really want, from the Hypernomicon jar file). + URLConnection conn = jarUrl.openConnection(); + + if (conn instanceof JarURLConnection jarURLConnection) + { + Manifest manifest = jarURLConnection.getManifest(); + + return manifest == null ? "" : nullSwitch(manifest.getMainAttributes(), "", attributes -> safeStr(attributes.getValue(key))); + } } catch (IOException e) { noOp(); } diff --git a/src/main/java/org/hypernomicon/view/MainCtrlr.java b/src/main/java/org/hypernomicon/view/MainCtrlr.java index 6c6e68e9..95497c59 100644 --- a/src/main/java/org/hypernomicon/view/MainCtrlr.java +++ b/src/main/java/org/hypernomicon/view/MainCtrlr.java @@ -1695,7 +1695,7 @@ private boolean createNewDB(FilePath rootPath) { FilePath srcFilePath = null; - try (ZipInputStream zis = new ZipInputStream(App.class.getResourceAsStream("resources/blank_db.zip"))) + try (ZipInputStream zis = new ZipInputStream(App.class.getResourceAsStream(BLANK_DB_RESOURCE_NAME))) { ZipEntry entry; diff --git a/src/test/java/org/hypernomicon/NewDBTest.java b/src/test/java/org/hypernomicon/NewDBTest.java index 1935c40a..39cc4cd7 100644 --- a/src/test/java/org/hypernomicon/NewDBTest.java +++ b/src/test/java/org/hypernomicon/NewDBTest.java @@ -54,7 +54,7 @@ class NewDBTest @Test void newDBTemplateTest() { - try (ZipInputStream zis = new ZipInputStream(App.class.getResourceAsStream("resources/blank_db.zip"))) + try (ZipInputStream zis = new ZipInputStream(App.class.getResourceAsStream(BLANK_DB_RESOURCE_NAME))) { ZipEntry entry;