diff --git a/beast-base/src/assembly/package.xml b/beast-base/src/assembly/package.xml index f09968ba..3b01d986 100644 --- a/beast-base/src/assembly/package.xml +++ b/beast-base/src/assembly/package.xml @@ -3,10 +3,20 @@ xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.1 http://maven.apache.org/xsd/assembly-2.1.1.xsd"> + the beast.pkgmgmt module on the module path. + + Examples are shipped *inside the package* (not only in the release + bundle root) so that a BEAST.base point release can update them via the + package manager: seedBundledPackage()/the package manager extract them + to /BEAST.base/examples, which BeautiTabPane and + PackageHealthChecker discover by scanning getBeastDirectories(). The + curated subset mirrors what release/.../assemble-bundle.sh copies into + the bundle root. --> package zip @@ -18,8 +28,29 @@ ${project.basedir}/../version.xml . + + + ${project.build.directory}/${project.build.finalName}-sources.jar + . + BEAST.base.src.jar + + + + ${project.basedir}/src/test/resources/beast.base/examples + examples + + *.xml + spec/*.xml + nexus/** + + + + lib diff --git a/beast-base/src/main/java/beast/base/minimal/BeastMain.java b/beast-base/src/main/java/beast/base/minimal/BeastMain.java index a4cb8d3f..1598c22a 100644 --- a/beast-base/src/main/java/beast/base/minimal/BeastMain.java +++ b/beast-base/src/main/java/beast/base/minimal/BeastMain.java @@ -69,6 +69,12 @@ public static void printUsage(final Arguments arguments) { private static void printVersion() { Log.info("BEAST " + (new BEASTVersion()).getVersionString()); Log.info("---"); + // The same package can be discovered through more than one directory on + // the package path (e.g. BEAST.base is found both in the user package dir + // and via the bundle-root version.xml). List each package once, noting + // where it was found; later duplicates are reported as skipped, but only + // in verbose mode. + java.util.Set printed = new java.util.HashSet<>(); for (String jarDirName : PackageManager.getBeastDirectories()) { File versionFile = new File(jarDirName + "/version.xml"); if (versionFile.exists()) { @@ -77,9 +83,14 @@ private static void printVersion() { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document doc = factory.newDocumentBuilder().parse(versionFile); Element packageElement = doc.getDocumentElement(); - Log.info.print(packageElement.getAttribute("name") + " v" + packageElement.getAttribute("version")); - Log.debug.print(" " + jarDirName); - Log.info.print("\n"); + String nameAndVersion = packageElement.getAttribute("name") + " v" + packageElement.getAttribute("version"); + if (printed.add(nameAndVersion)) { + Log.info.print(nameAndVersion); + Log.debug.print(" (found in " + jarDirName + ")"); + Log.info.print("\n"); + } else { + Log.debug.println("Skipping duplicate " + nameAndVersion + " found in " + jarDirName); + } } catch (IOException| SAXException| ParserConfigurationException e) { Log.err(e.getMessage()); } diff --git a/beast-fx/src/assembly/package.xml b/beast-fx/src/assembly/package.xml index bdba2ffc..fc55e178 100644 --- a/beast-fx/src/assembly/package.xml +++ b/beast-fx/src/assembly/package.xml @@ -3,6 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.1 http://maven.apache.org/xsd/assembly-2.1.1.xsd"> + + ${project.build.directory}/${project.build.finalName}-sources.jar + . + BEAST.app.src.jar + diff --git a/beast-fx/src/main/java/beastfx/app/beast/BeastMain.java b/beast-fx/src/main/java/beastfx/app/beast/BeastMain.java index f87be3f8..1324fb38 100644 --- a/beast-fx/src/main/java/beastfx/app/beast/BeastMain.java +++ b/beast-fx/src/main/java/beastfx/app/beast/BeastMain.java @@ -103,6 +103,12 @@ public static void printUsage(final Arguments arguments) { private static void printVersion() { Log.info("BEAST " + (new BEASTVersion()).getVersionString()); Log.info("---"); + // The same package can be discovered through more than one directory on + // the package path (e.g. BEAST.base is found both in the user package dir + // and via the bundle-root version.xml). List each package once, noting + // where it was found; later duplicates are reported as skipped, but only + // in verbose mode. + java.util.Set printed = new java.util.HashSet<>(); for (String jarDirName : PackageManager.getBeastDirectories()) { File versionFile = new File(jarDirName + "/version.xml"); if (versionFile.exists()) { @@ -111,9 +117,14 @@ private static void printVersion() { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document doc = factory.newDocumentBuilder().parse(versionFile); Element packageElement = doc.getDocumentElement(); - Log.info.print(packageElement.getAttribute("name") + " v" + packageElement.getAttribute("version")); - Log.debug.print(" " + jarDirName); - Log.info.print("\n"); + String nameAndVersion = packageElement.getAttribute("name") + " v" + packageElement.getAttribute("version"); + if (printed.add(nameAndVersion)) { + Log.info.print(nameAndVersion); + Log.debug.print(" (found in " + jarDirName + ")"); + Log.info.print("\n"); + } else { + Log.debug.println("Skipping duplicate " + nameAndVersion + " found in " + jarDirName); + } } catch (IOException| SAXException| ParserConfigurationException e) { Log.err(e.getMessage()); } diff --git a/beast-pkgmgmt/src/main/java/beast/pkgmgmt/BEASTClassLoader.java b/beast-pkgmgmt/src/main/java/beast/pkgmgmt/BEASTClassLoader.java index c980753c..37a03720 100644 --- a/beast-pkgmgmt/src/main/java/beast/pkgmgmt/BEASTClassLoader.java +++ b/beast-pkgmgmt/src/main/java/beast/pkgmgmt/BEASTClassLoader.java @@ -76,6 +76,14 @@ public static Class forName(String className) throws ClassNotFoundException { ClassLoader loader = class2loaderMap.get(className); try { return Class.forName(className, false, loader); + } catch (ClassNotFoundException e) { + // The mapped loader cannot see this class. This happens when the + // provider was registered from a version.xml scan (via + // resolveLoaderFor → fallback system/context loader) before the + // owning package's plugin ModuleLayer was registered: the later + // putIfAbsent in registerPluginLayer() then cannot replace the + // stale fallback loader. Fall through to search the plugin layers + // and correct the mapping below. } catch (NoClassDefFoundError e) { String missing = e.getMessage(); if (missing != null && (missing.startsWith("beastfx/") || missing.startsWith("beastfx.") @@ -91,8 +99,15 @@ public static Class forName(String className) throws ClassNotFoundException { // 2. Plugin layers (external BEAST packages) for (ModuleLayer layer : pluginLayers) { for (Module module : layer.modules()) { + ClassLoader mcl = module.getClassLoader(); + if (mcl == null) continue; try { - return Class.forName(className, false, module.getClassLoader()); + Class c = Class.forName(className, false, mcl); + // Self-heal: cache the loader that actually resolved the + // class so subsequent lookups skip the failing mapped loader + // (and the exception-driven fall-through above). + class2loaderMap.put(className, mcl); + return c; } catch (ClassNotFoundException | NoClassDefFoundError e) { // try next module } @@ -559,6 +574,20 @@ private static ClassLoader resolveLoaderFor(String provider) { if (loader != null) return loader; } } + // Also consult already-registered plugin layers: a package's classes + // live in its own plugin ModuleLayer (e.g. beast.fx for the BEAUti + // input editors), not in the boot layer. Without this, providers listed + // in a version.xml would be mapped to the fallback system loader, which + // cannot load them, leaving forName() to fall through on every lookup. + for (ModuleLayer layer : pluginLayers) { + for (Module m : layer.modules()) { + java.lang.module.ModuleDescriptor desc = m.getDescriptor(); + if (desc != null && desc.packages().contains(pkg)) { + ClassLoader loader = m.getClassLoader(); + if (loader != null) return loader; + } + } + } return fallbackClassLoader(); } } diff --git a/beast-pkgmgmt/src/test/java/beast/pkgmgmt/ModuleLayerCrossDependencyTest.java b/beast-pkgmgmt/src/test/java/beast/pkgmgmt/ModuleLayerCrossDependencyTest.java index 8771cdcb..fa2d3449 100644 --- a/beast-pkgmgmt/src/test/java/beast/pkgmgmt/ModuleLayerCrossDependencyTest.java +++ b/beast-pkgmgmt/src/test/java/beast/pkgmgmt/ModuleLayerCrossDependencyTest.java @@ -9,12 +9,15 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import java.util.spi.ToolProvider; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -64,6 +67,47 @@ public void dependentPackageResolvesAgainstAnotherPluginLayer() throws Exception assertEquals("base+plugin", result, "cross-layer call should execute"); } + /** + * Regression test for the BEAUti "ClassNotFoundException: beastfx.app.inputeditor.*" + * failure. A package's service providers are listed in its version.xml. If a + * version.xml scan registers a provider (via addServices → resolveLoaderFor) + * before the owning package's plugin ModuleLayer is registered, the provider + * is mapped to the fallback system loader, which cannot load it. registerPluginLayer() + * uses putIfAbsent and so cannot replace that stale mapping. forName() must still + * resolve the class by falling through to the plugin layers. + */ + @Test + public void forNameHealsStaleFallbackLoaderMapping() throws Exception { + ToolProvider javac = ToolProvider.findFirst("javac").orElse(null); + Assumptions.assumeTrue(javac != null, "no javac tool available - skipping"); + + Path work = Files.createTempDirectory("stale-loader-test"); + + // A modular jar exporting a provider class, mimicking beast.fx's input editors. + Path editorJar = buildModuleJar(javac, work, "fxstaletest", null, + "module fxstaletest { exports fxstaletest; }", + "fxstaletest", "Editor", + "package fxstaletest; public class Editor { }"); + + // 1. Simulate the version.xml scan that runs before the plugin layer exists: + // the provider is mapped to the fallback system loader (cannot load it). + Map> services = Map.of( + "fxstaletest.InputEditor", Set.of("fxstaletest.Editor")); + BEASTClassLoader.classLoader.addServices("FxStaleTest", services); + + // 2. Register the package's real plugin layer. putIfAbsent leaves the + // stale fallback mapping from step 1 in place. + boolean loaded = PackageManager.createAndRegisterModuleLayer( + List.of(editorJar), null, "FxStaleTest", "1.0", "FxStaleTest"); + assertTrue(loaded, "provider module should load into a plugin layer"); + + // 3. Despite the stale mapping, forName must resolve the class via the + // plugin layer (previously threw ClassNotFoundException here). + Class editor = BEASTClassLoader.forName("fxstaletest.Editor"); + assertNotNull(editor); + assertEquals("fxstaletest.Editor", editor.getName()); + } + /** Compile a single-package module and pack it into a jar; return the jar path. */ private static Path buildModuleJar(ToolProvider javac, Path work, String moduleName, Path modulePathJar, String moduleInfo, diff --git a/release/Linux/assemble-bundle.sh b/release/Linux/assemble-bundle.sh index eeb14426..3c0e901e 100755 --- a/release/Linux/assemble-bundle.sh +++ b/release/Linux/assemble-bundle.sh @@ -152,21 +152,24 @@ else echo " WARNING: DensiTree.jar not found — densitree script will not work" fi -# ── Step 6: Copy examples ───────────────────────────────────────────────────── +# ── Step 6: Extract examples from the BEAST.base package zip ────────────────── +# The bundle-root examples/ are extracted from the same package zip seeded into +# the user dir (lib/packages/), so the example set has a single source of truth +# (beast-base/src/assembly/package.xml) and the bundle-root and packaged copies +# cannot drift. The bundle-root copy is kept so `beast -validate examples/...` +# works from the install dir before first-run seeding. echo "" -echo "==> Step 6: Copying examples..." -EXAMPLES_DIR="$REPO_ROOT/beast-base/src/test/resources/beast.base/examples" -if [ -d "$EXAMPLES_DIR" ]; then - find "$EXAMPLES_DIR" -maxdepth 1 -name "*.xml" -exec cp {} "$BUNDLE/examples/" \; - mkdir -p "$BUNDLE/examples/spec" - [ -d "$EXAMPLES_DIR/spec" ] && \ - find "$EXAMPLES_DIR/spec" -maxdepth 1 -name "*.xml" -exec cp {} "$BUNDLE/examples/spec/" \; - [ -d "$EXAMPLES_DIR/nexus" ] && cp -r "$EXAMPLES_DIR/nexus" "$BUNDLE/examples/" - EXAMPLE_COUNT=$(find "$BUNDLE/examples" -name "*.xml" | wc -l | tr -d ' ') - echo " Copied ${EXAMPLE_COUNT} example XML files (incl. spec/)" -else - echo " WARNING: examples not found at $EXAMPLES_DIR" -fi +echo "==> Step 6: Extracting examples from $(basename "$BASE_PKG_ZIP")..." +# Extract the full zip to a temp dir then copy examples/ — avoids unzip glob +# portability issues where 'examples/*' may not match subdirs on some platforms. +# Which subdirs are included/excluded is controlled by the include patterns in +# beast-base/src/assembly/package.xml (e.g. spec/*.xml excludes spec/beast2vs1/). +EXAMPLES_TMP=$(mktemp -d) +unzip -o -q "$BASE_PKG_ZIP" -d "$EXAMPLES_TMP" +cp -r "$EXAMPLES_TMP/examples/." "$BUNDLE/examples/" +rm -rf "$EXAMPLES_TMP" +EXAMPLE_COUNT=$(find "$BUNDLE/examples" -name "*.xml" | wc -l | tr -d ' ') +echo " Extracted ${EXAMPLE_COUNT} example XML files (incl. spec/)" # ── Step 7: Copy version.xml and docs ──────────────────────────────────────── echo "" diff --git a/release/Linux/linuxbin/applauncher b/release/Linux/linuxbin/applauncher index 759324fd..3b359171 100755 --- a/release/Linux/linuxbin/applauncher +++ b/release/Linux/linuxbin/applauncher @@ -44,11 +44,11 @@ else fi if [ -n "$BEAST_EXTRA_LIBS" ]; then - exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ + exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Djava.library.path="$BEAST_EXTRA_LIBS" -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.AppLauncherLauncher "$@" else - exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ + exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.AppLauncherLauncher "$@" fi diff --git a/release/Linux/linuxbin/beast b/release/Linux/linuxbin/beast index 16aae175..08fd0885 100755 --- a/release/Linux/linuxbin/beast +++ b/release/Linux/linuxbin/beast @@ -69,6 +69,6 @@ if [ -n "$BEAST_EXTRA_LIBS" ]; then fi fi -exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ +exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Djava.library.path="$LD_LIBRARY_PATH" -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.BeastLauncher "$@" diff --git a/release/Linux/linuxbin/beauti b/release/Linux/linuxbin/beauti index 29d61bb8..1efd8a24 100755 --- a/release/Linux/linuxbin/beauti +++ b/release/Linux/linuxbin/beauti @@ -25,6 +25,6 @@ JAVA_HOME="$BUNDLE_HOME/jre" export JAVA_HOME JAVA="$JAVA_HOME/bin/java" APP="$BUNDLE_HOME/lib" -exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ +exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.BeautiLauncher -capture "$@" diff --git a/release/Linux/linuxbin/loganalyser b/release/Linux/linuxbin/loganalyser index 99c03655..58a9beab 100755 --- a/release/Linux/linuxbin/loganalyser +++ b/release/Linux/linuxbin/loganalyser @@ -44,11 +44,11 @@ else fi if [ -n "$BEAST_EXTRA_LIBS" ]; then - exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ + exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Djava.library.path="$BEAST_EXTRA_LIBS" -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.AppLauncherLauncher beastfx.app.tools.LogAnalyser "$@" else - exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ + exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.AppLauncherLauncher beastfx.app.tools.LogAnalyser "$@" fi diff --git a/release/Linux/linuxbin/logcombiner b/release/Linux/linuxbin/logcombiner index ae1b372e..db047bb5 100755 --- a/release/Linux/linuxbin/logcombiner +++ b/release/Linux/linuxbin/logcombiner @@ -25,6 +25,6 @@ JAVA_HOME="$BUNDLE_HOME/jre" export JAVA_HOME JAVA="$JAVA_HOME/bin/java" APP="$BUNDLE_HOME/lib" -exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ +exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.LogCombinerLauncher "$@" diff --git a/release/Linux/linuxbin/packagemanager b/release/Linux/linuxbin/packagemanager index c5e5f517..620a6a19 100755 --- a/release/Linux/linuxbin/packagemanager +++ b/release/Linux/linuxbin/packagemanager @@ -25,6 +25,6 @@ JAVA_HOME="$BUNDLE_HOME/jre" export JAVA_HOME JAVA="$JAVA_HOME/bin/java" APP="$BUNDLE_HOME/lib" -exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ +exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.PackageManager "$@" diff --git a/release/Linux/linuxbin/treeannotator b/release/Linux/linuxbin/treeannotator index df815c5b..f8a16844 100755 --- a/release/Linux/linuxbin/treeannotator +++ b/release/Linux/linuxbin/treeannotator @@ -25,6 +25,6 @@ JAVA_HOME="$BUNDLE_HOME/jre" export JAVA_HOME JAVA="$JAVA_HOME/bin/java" APP="$BUNDLE_HOME/lib" -exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ +exec "$JAVA" --module-path "$APP" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.TreeAnnotatorLauncher "$@" diff --git a/release/Mac/build-sign-dmg.sh b/release/Mac/build-sign-dmg.sh index 633a21ae..812c886e 100755 --- a/release/Mac/build-sign-dmg.sh +++ b/release/Mac/build-sign-dmg.sh @@ -226,7 +226,8 @@ sed -i '' 's|^app\.mainclass=.*|app.mainmodule=beast.pkgmgmt/beast.pkgmgmt.launc # media) come along automatically. sed -i '' '/^\[JavaOptions\]/a\ java-options=--module-path=\$APPDIR\ -java-options=--add-modules=ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject +java-options=--add-modules=ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject\ +java-options=--enable-native-access=javafx.graphics,javafx.media,javafx.web ' "$BEAST_CFG" # jpackage may strip bin/java from the bundled runtime (it uses its own native @@ -295,12 +296,12 @@ build_wrapper_app() { local launch_cmd if [ -n "$extra_args" ]; then launch_cmd="exec \"\$BEAST_APP/runtime/Contents/Home/bin/java\" \\ - --module-path \"\$BEAST_APP/app\" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \\ + --module-path \"\$BEAST_APP/app\" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \\ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \\ -m $module_name/$main_class $extra_args \"\$@\"" else launch_cmd="exec \"\$BEAST_APP/runtime/Contents/Home/bin/java\" \\ - --module-path \"\$BEAST_APP/app\" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \\ + --module-path \"\$BEAST_APP/app\" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \\ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \\ -m $module_name/$main_class \"\$@\"" fi @@ -558,21 +559,15 @@ else fi # ── examples/ — example BEAST XML files ────────────────────────────────────── -EXAMPLES_DIR="$REPO_ROOT/beast-base/src/test/resources/beast.base/examples" -if [ -d "$EXAMPLES_DIR" ]; then - echo " Copying examples/..." - mkdir -p "$OUTPUT/examples" - # Copy top-level XML files - find "$EXAMPLES_DIR" -maxdepth 1 -name "*.xml" -exec cp {} "$OUTPUT/examples/" \; - # Copy nexus subdirectory - if [ -d "$EXAMPLES_DIR/nexus" ]; then - cp -r "$EXAMPLES_DIR/nexus" "$OUTPUT/examples/nexus" - fi - if [ -d "$EXAMPLES_DIR/spec" ]; then - cp -r "$EXAMPLES_DIR/spec" "$OUTPUT/examples/spec" - fi +# Extracted from the BEAST.base package zip seeded into the user dir +# (Contents/app/packages/), so the example set has a single source of truth +# (beast-base/src/assembly/package.xml) and the bundle-root and packaged copies +# cannot drift. The bundle-root copy is kept so `beast -validate examples/...` +# works from the install dir before first-run seeding. +if [ -n "$BASE_PKG_ZIP" ] && unzip -o -q "$BASE_PKG_ZIP" 'examples/*' -d "$OUTPUT"; then + echo " Extracted examples/ from $(basename "$BASE_PKG_ZIP")" else - echo " WARNING: $EXAMPLES_DIR not found — skipping examples/" + echo " WARNING: no examples found in BEAST.base package zip — skipping examples/" fi # ── README and LICENSE ───────────────────────────────────────────────────── diff --git a/release/Mac/macbin/applauncher b/release/Mac/macbin/applauncher index 2174ef5a..b40201ab 100755 --- a/release/Mac/macbin/applauncher +++ b/release/Mac/macbin/applauncher @@ -45,12 +45,12 @@ fi if [ -n "$BEAST_EXTRA_LIBS" ]; then "$JAVA" -Dlauncher.wait.for.exit=true \ - --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ + --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Djava.library.path="$BEAST_EXTRA_LIBS" -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.AppLauncherLauncher "$@" else "$JAVA" -Dlauncher.wait.for.exit=true \ - --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ + --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.AppLauncherLauncher "$@" fi diff --git a/release/Mac/macbin/beast b/release/Mac/macbin/beast index 44e65502..abe98497 100755 --- a/release/Mac/macbin/beast +++ b/release/Mac/macbin/beast @@ -71,6 +71,6 @@ if [ -n "$BEAST_EXTRA_LIBS" ]; then fi "$JAVA" -Dlauncher.wait.for.exit=true \ - --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ + --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Djava.library.path="$LD_LIBRARY_PATH" -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.BeastLauncher "$@" diff --git a/release/Mac/macbin/beauti b/release/Mac/macbin/beauti index d90de718..b5a1c14d 100755 --- a/release/Mac/macbin/beauti +++ b/release/Mac/macbin/beauti @@ -27,6 +27,6 @@ BEAST_APP="$BEAST/BEAST.app/Contents" export JAVA_HOME="$BEAST_APP/runtime/Contents/Home" JAVA="$JAVA_HOME/bin/java" "$JAVA" -Dlauncher.wait.for.exit=true \ - --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ + --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.BeautiLauncher -capture "$@" diff --git a/release/Mac/macbin/loganalyser b/release/Mac/macbin/loganalyser index c56529f6..169879a3 100755 --- a/release/Mac/macbin/loganalyser +++ b/release/Mac/macbin/loganalyser @@ -45,12 +45,12 @@ fi if [ -n "$BEAST_EXTRA_LIBS" ]; then "$JAVA" -Dlauncher.wait.for.exit=true \ - --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ + --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Djava.library.path="$BEAST_EXTRA_LIBS" -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.AppLauncherLauncher beastfx.app.tools.LogAnalyser "$@" else "$JAVA" -Dlauncher.wait.for.exit=true \ - --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ + --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.AppLauncherLauncher beastfx.app.tools.LogAnalyser "$@" fi diff --git a/release/Mac/macbin/logcombiner b/release/Mac/macbin/logcombiner index 7064c40e..525e84ac 100755 --- a/release/Mac/macbin/logcombiner +++ b/release/Mac/macbin/logcombiner @@ -27,6 +27,6 @@ BEAST_APP="$BEAST/BEAST.app/Contents" export JAVA_HOME="$BEAST_APP/runtime/Contents/Home" JAVA="$JAVA_HOME/bin/java" "$JAVA" -Dlauncher.wait.for.exit=true \ - --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ + --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.LogCombinerLauncher "$@" diff --git a/release/Mac/macbin/packagemanager b/release/Mac/macbin/packagemanager index e097f687..8d1012af 100755 --- a/release/Mac/macbin/packagemanager +++ b/release/Mac/macbin/packagemanager @@ -27,6 +27,6 @@ BEAST_APP="$BEAST/BEAST.app/Contents" export JAVA_HOME="$BEAST_APP/runtime/Contents/Home" JAVA="$JAVA_HOME/bin/java" "$JAVA" \ - --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ + --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.PackageManager "$@" diff --git a/release/Mac/macbin/treeannotator b/release/Mac/macbin/treeannotator index 9ce4c93a..87e6b82b 100755 --- a/release/Mac/macbin/treeannotator +++ b/release/Mac/macbin/treeannotator @@ -27,6 +27,6 @@ BEAST_APP="$BEAST/BEAST.app/Contents" export JAVA_HOME="$BEAST_APP/runtime/Contents/Home" JAVA="$JAVA_HOME/bin/java" "$JAVA" -Dlauncher.wait.for.exit=true \ - --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject \ + --module-path "$BEAST_APP/app" --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web \ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 \ -m beast.pkgmgmt/beast.pkgmgmt.launcher.TreeAnnotatorLauncher "$@" diff --git a/release/Windows/assemble-bundle.sh b/release/Windows/assemble-bundle.sh index 8e4647ab..8d37cee4 100644 --- a/release/Windows/assemble-bundle.sh +++ b/release/Windows/assemble-bundle.sh @@ -232,7 +232,7 @@ for cfg in "$BUNDLE/app/"*.cfg; do sed -i \ -e '/^app\.classpath/d' \ -e 's|^app\.mainclass=\(.*\)|app.mainmodule=beast.pkgmgmt/\1|' \ - -e '/^\[JavaOptions\]/a java-options=--module-path=$APPDIR\njava-options=--add-modules=ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject' \ + -e '/^\[JavaOptions\]/a java-options=--module-path=$APPDIR\njava-options=--add-modules=ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject\njava-options=--enable-native-access=javafx.graphics,javafx.media,javafx.web' \ "$cfg" done @@ -244,21 +244,24 @@ WINBIN_DIR="$SCRIPT_DIR/bat" mkdir -p "$BUNDLE/bat" cp "$WINBIN_DIR/"*.bat "$BUNDLE/bat/" -# ── Step 7: Copy examples ───────────────────────────────────────────────────── +# ── Step 7: Extract examples from the BEAST.base package zip ────────────────── +# The bundle-root examples/ are extracted from the same package zip seeded into +# the user dir (app/packages/), so the example set has a single source of truth +# (beast-base/src/assembly/package.xml) and the bundle-root and packaged copies +# cannot drift. The bundle-root copy is kept so `beast -validate examples/...` +# works from the install dir before first-run seeding. echo "" -echo "==> Step 7: Copying examples..." -EXAMPLES_DIR="$REPO_ROOT/beast-base/src/test/resources/beast.base/examples" -if [ -d "$EXAMPLES_DIR" ]; then - mkdir -p "$BUNDLE/examples/spec" - find "$EXAMPLES_DIR" -maxdepth 1 -name "*.xml" -exec cp {} "$BUNDLE/examples/" \; - [ -d "$EXAMPLES_DIR/spec" ] && \ - find "$EXAMPLES_DIR/spec" -maxdepth 1 -name "*.xml" -exec cp {} "$BUNDLE/examples/spec/" \; - [ -d "$EXAMPLES_DIR/nexus" ] && cp -r "$EXAMPLES_DIR/nexus" "$BUNDLE/examples/" - EXAMPLE_COUNT=$(find "$BUNDLE/examples" -name "*.xml" | wc -l | tr -d ' ') - echo " Copied ${EXAMPLE_COUNT} example XML files (incl. spec/)" -else - echo " WARNING: examples not found at $EXAMPLES_DIR" -fi +echo "==> Step 7: Extracting examples from $(basename "$BASE_PKG_ZIP")..." +# Extract the full zip to a temp dir then copy examples/ — avoids unzip glob +# portability issues where 'examples/*' may not match subdirs on some platforms. +# Which subdirs are included/excluded is controlled by the include patterns in +# beast-base/src/assembly/package.xml (e.g. spec/*.xml excludes spec/beast2vs1/). +EXAMPLES_TMP=$(mktemp -d) +unzip -o -q "$BASE_PKG_ZIP" -d "$EXAMPLES_TMP" +cp -r "$EXAMPLES_TMP/examples/." "$BUNDLE/examples/" +rm -rf "$EXAMPLES_TMP" +EXAMPLE_COUNT=$(find "$BUNDLE/examples" -name "*.xml" | wc -l | tr -d ' ') +echo " Extracted ${EXAMPLE_COUNT} example XML files (incl. spec/)" # ── Step 8: Copy version.xml and docs ──────────────────────────────────────── echo "" diff --git a/release/Windows/bat/applauncher.bat b/release/Windows/bat/applauncher.bat index 40b6720c..f8e2dc99 100644 --- a/release/Windows/bat/applauncher.bat +++ b/release/Windows/bat/applauncher.bat @@ -2,6 +2,6 @@ set "BUNDLE_HOME=%~dp0.." "%BUNDLE_HOME%\runtime\bin\java.exe" ^ --module-path "%BUNDLE_HOME%\app" ^ - --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject ^ + --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web ^ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 ^ -m beast.pkgmgmt/beast.pkgmgmt.launcher.AppLauncherLauncher %* \ No newline at end of file diff --git a/release/Windows/bat/beast.bat b/release/Windows/bat/beast.bat index e503399c..fde9b090 100644 --- a/release/Windows/bat/beast.bat +++ b/release/Windows/bat/beast.bat @@ -2,6 +2,6 @@ set "BUNDLE_HOME=%~dp0.." "%BUNDLE_HOME%\runtime\bin\java.exe" ^ --module-path "%BUNDLE_HOME%\app" ^ - --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject ^ + --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web ^ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 ^ -m beast.pkgmgmt/beast.pkgmgmt.launcher.BeastLauncher %* diff --git a/release/Windows/bat/beauti.bat b/release/Windows/bat/beauti.bat index 12b19ac3..0813eae2 100644 --- a/release/Windows/bat/beauti.bat +++ b/release/Windows/bat/beauti.bat @@ -2,6 +2,6 @@ set "BUNDLE_HOME=%~dp0.." "%BUNDLE_HOME%\runtime\bin\java.exe" ^ --module-path "%BUNDLE_HOME%\app" ^ - --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject ^ + --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web ^ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 ^ -m beast.pkgmgmt/beast.pkgmgmt.launcher.BeautiLauncher -capture %* \ No newline at end of file diff --git a/release/Windows/bat/loganalyser.bat b/release/Windows/bat/loganalyser.bat index 10a447cf..5bb25482 100644 --- a/release/Windows/bat/loganalyser.bat +++ b/release/Windows/bat/loganalyser.bat @@ -2,6 +2,6 @@ set "BUNDLE_HOME=%~dp0.." "%BUNDLE_HOME%\runtime\bin\java.exe" ^ --module-path "%BUNDLE_HOME%\app" ^ - --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject ^ + --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web ^ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 ^ -m beast.pkgmgmt/beast.pkgmgmt.launcher.AppLauncherLauncher beastfx.app.tools.LogAnalyser %* \ No newline at end of file diff --git a/release/Windows/bat/logcombiner.bat b/release/Windows/bat/logcombiner.bat index a0ab36ed..859f7e57 100644 --- a/release/Windows/bat/logcombiner.bat +++ b/release/Windows/bat/logcombiner.bat @@ -2,6 +2,6 @@ set "BUNDLE_HOME=%~dp0.." "%BUNDLE_HOME%\runtime\bin\java.exe" ^ --module-path "%BUNDLE_HOME%\app" ^ - --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject ^ + --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web ^ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 ^ -m beast.pkgmgmt/beast.pkgmgmt.launcher.LogCombinerLauncher %* \ No newline at end of file diff --git a/release/Windows/bat/packagemanager.bat b/release/Windows/bat/packagemanager.bat index a2292f39..c3f26e8d 100644 --- a/release/Windows/bat/packagemanager.bat +++ b/release/Windows/bat/packagemanager.bat @@ -2,6 +2,6 @@ set "BUNDLE_HOME=%~dp0.." "%BUNDLE_HOME%\runtime\bin\java.exe" ^ --module-path "%BUNDLE_HOME%\app" ^ - --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject ^ + --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web ^ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 ^ -m beast.pkgmgmt/beast.pkgmgmt.PackageManager %* \ No newline at end of file diff --git a/release/Windows/bat/treeannotator.bat b/release/Windows/bat/treeannotator.bat index 6b9fe944..449a2140 100644 --- a/release/Windows/bat/treeannotator.bat +++ b/release/Windows/bat/treeannotator.bat @@ -2,6 +2,6 @@ set "BUNDLE_HOME=%~dp0.." "%BUNDLE_HOME%\runtime\bin\java.exe" ^ --module-path "%BUNDLE_HOME%\app" ^ - --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject ^ + --add-modules ALL-MODULE-PATH,javafx.controls,javafx.fxml,javafx.swing,javafx.web,jdk.jsobject --enable-native-access=javafx.graphics,javafx.media,javafx.web ^ -Xss256m -Xmx8g -Duser.language=en -Dfile.encoding=UTF-8 ^ -m beast.pkgmgmt/beast.pkgmgmt.launcher.TreeAnnotatorLauncher %* \ No newline at end of file