From b4ec2150739c6e1dfc1d4da45c31dd20e0bc06dd Mon Sep 17 00:00:00 2001 From: Matthew Larson Date: Mon, 6 Jul 2026 09:57:32 -0500 Subject: [PATCH] Add bundled filter plugin directory to HDF5 plugin search path Datasets written with the HDF5 filter plugins bundled in an HDFView installation could not be read unless the user manually added the plugin directory under User Options. Trying to open such a dataset failed because the library had no registered plugin path pointing at the bundled filters (#477). This happened because HDFView never established a plugin-path policy of its own. At startup it read back whatever paths the HDF5 native library already had, via ViewProperties.loadPluginPaths() -> H5Plugins.getPluginPaths() -> H5PLget(). Those paths were just the defaults compiled into the native jarhdf5 library at compile time, persisting github-runner specific paths into the published builds. HDFView takes a prefix-built HDF5 library and relocates it into a jpackage bundle at $APPDIR. HDF5 has no $ORIGIN-relative plugin discovery, so the prefix-relative default points at a path that does not exist on the end user's machine. Installers copy the bundled filters into /plugin (e.g. /lib/app/plugin on Linux, where jpackage sets hdfview.root to $APPDIR; see hdfview/pom.xml), a location the library's compiled-in defaults can never name. Because only the running app knows its actual install location, the correct path can only be supplied at runtime, by the application. This PR gives HDFView an explicit plugin-path policy in initPluginPaths(), called once at startup. It loads the library's existing paths, then resolves /plugin and, if that directory exists and is not already registered, prepends it via ViewProperties.prependPluginPath() -> H5PLprepend() so the bundled filters take precedence over stale/system defaults. The path is recomputed from hdfview.root on every launch, so it should be accurate across multiple installs and reinstalls. It should also do no harm when no such directory exists. The prefix-relative default remains in the library-reported list but is harmless, since the correct location is present and searched first. Fixes #477 --- hdfview/src/main/java/hdf/view/HDFView.java | 43 ++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/hdfview/src/main/java/hdf/view/HDFView.java b/hdfview/src/main/java/hdf/view/HDFView.java index 2138a469..f0c63af9 100644 --- a/hdfview/src/main/java/hdf/view/HDFView.java +++ b/hdfview/src/main/java/hdf/view/HDFView.java @@ -292,7 +292,7 @@ public HDFView(String root, String startPath) } if (FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5) != null) - ViewProperties.loadPluginPaths(); + initPluginPaths(); treeViews = ViewProperties.getTreeViewList(); metaDataViews = ViewProperties.getMetaDataViewList(); @@ -304,6 +304,47 @@ public HDFView(String root, String startPath) log.debug("Constructor exit"); } + /** + * Establishes the HDF5 filter plugin search paths for this HDFView session. + * + * The search list is the + * bundled install directory followed by whatever paths the HDF5 library already knows + * (its compiled-in defaults plus any HDF5_PLUGIN_PATH entries). Users can + * further adjust the list through the User Options dialog. + * + * The bundled directory must be added at runtime because a jpackage installation is + * relocatable: filter plugins ship at /plugin (e.g. + * /lib/app/plugin on Linux, where hdfview.root resolves to + * $APPDIR), but the HDF5 library only supports absolute, build-time plugin + * paths, so its defaults never point at the actual install location. + */ + private void initPluginPaths() + { + // Start from the paths the HDF5 library already has registered. + ViewProperties.loadPluginPaths(); + + if (rootDir == null) + return; + + File pluginDir = new File(rootDir, "plugin"); + if (!pluginDir.isDirectory()) { + log.debug("No bundled plugin directory at {}", pluginDir.getAbsolutePath()); + return; + } + + String pluginPath = pluginDir.getAbsolutePath(); + for (String existing : ViewProperties.getPluginPaths()) { + if (pluginPath.equals(existing)) { + log.debug("Bundled plugin path {} already present", pluginPath); + return; + } + } + + // Prepend so the bundled filters take precedence over system defaults. + ViewProperties.prependPluginPath(pluginPath); + log.debug("Added bundled plugin path {}", pluginPath); + } + /** * Creates HDFView with a given size, and opens the given files in the viewer. *