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;