From b63b98bea2e2a0e280666cf167ec25f757e58991 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Sat, 7 Jun 2025 05:17:03 -0500 Subject: [PATCH 1/4] platform/util: PropertiesController interface and DefaultPropertiesProvider --- .../platform/NativeDynamicLibrary.java | 6 +- .../util/DefaultPropertiesProvider.java | 94 ++++++ .../platform/util/PropertiesController.java | 277 ++++++++++++++++++ .../util/PropertiesControllerNamespace.java | 101 +++++++ .../platform/util/PropertiesProvider.java | 58 +--- 5 files changed, 478 insertions(+), 58 deletions(-) create mode 100644 snaploader/src/main/java/electrostatic4j/snaploader/platform/util/DefaultPropertiesProvider.java create mode 100644 snaploader/src/main/java/electrostatic4j/snaploader/platform/util/PropertiesController.java create mode 100644 snaploader/src/main/java/electrostatic4j/snaploader/platform/util/PropertiesControllerNamespace.java diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java b/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java index 695712e..e9b31c1 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java @@ -38,7 +38,7 @@ import electrostatic4j.snaploader.filesystem.DirectoryPath; import electrostatic4j.snaploader.platform.util.NativeVariant; import electrostatic4j.snaploader.platform.util.PlatformPredicate; -import electrostatic4j.snaploader.platform.util.PropertiesProvider; +import electrostatic4j.snaploader.platform.util.DefaultPropertiesProvider; /** * Represents a filesystem to a platform-specific binary inside @@ -170,7 +170,7 @@ public String getPlatformDirectory() { * @return a string representing the library path within the jar compression */ public String getCompressedLibrary() { - return platformDirectory + PropertiesProvider.ZIP_FILE_SEPARATOR.getSystemProperty() + libraryFile; + return platformDirectory + DefaultPropertiesProvider.ZIP_FILE_SEPARATOR.getSystemProperty() + libraryFile; } /** @@ -180,7 +180,7 @@ public String getCompressedLibrary() { */ public String getExtractedLibrary() { return directoryPath.getPath() - + PropertiesProvider.FILE_SEPARATOR.getSystemProperty() + libraryFile; + + DefaultPropertiesProvider.FILE_SEPARATOR.getSystemProperty() + libraryFile; } /** diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/platform/util/DefaultPropertiesProvider.java b/snaploader/src/main/java/electrostatic4j/snaploader/platform/util/DefaultPropertiesProvider.java new file mode 100644 index 0000000..344a4cb --- /dev/null +++ b/snaploader/src/main/java/electrostatic4j/snaploader/platform/util/DefaultPropertiesProvider.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2023-2025, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'Electrostatic-Sandbox' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package electrostatic4j.snaploader.platform.util; + +/** + * Provides platform-dependent system properties for the current running machine. + * + * @author pavl_g + */ +public enum DefaultPropertiesProvider implements PropertiesProvider { + + /** + * Provides a string representation for the absolute directory + * of the current user directory. + */ + USER_DIR(System.getProperty("user.dir")), + + /** + * Provides a string representation for the absolute directory + * of the user home. + */ + USER_HOME(System.getProperty("user.home")), + + /** + * Provides a string representation for the platform-dependent filesystem separator. + */ + FILE_SEPARATOR(System.getProperty("file.separator")), + + /** + * Provides a string representation for the filesystem separator of the Zip specification. + */ + ZIP_FILE_SEPARATOR("/"), + + /** + * Provides a string representation for the absolute path of the + * java interpreter binary. + */ + JAVA_HOME(System.getProperty("java.home")), + + SYSTEM_DIR(System.getProperty("jsnaploader.library.path")), + + CLASS_PATH(System.getProperty("java.class.path")); + + private final String systemProperty; + + /** + * Instantiates a platform-dependent property object. + * + * @param systemProperty the string representation of the platform-dependent property + */ + DefaultPropertiesProvider(String systemProperty) { + this.systemProperty = systemProperty; + } + + /** + * Retrieves the platform-dependent property. + * + * @return a string representation for the platform-dependent property + */ + @Override + public String getSystemProperty() { + return systemProperty; + } +} diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/platform/util/PropertiesController.java b/snaploader/src/main/java/electrostatic4j/snaploader/platform/util/PropertiesController.java new file mode 100644 index 0000000..f2b0769 --- /dev/null +++ b/snaploader/src/main/java/electrostatic4j/snaploader/platform/util/PropertiesController.java @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2023-2025, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'Electrostatic-Sandbox' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package electrostatic4j.snaploader.platform.util; + +import java.nio.file.FileSystems; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.function.Function; + +/** + * Controls a Java System property via a property provider. + * + * @author pavl_g. + */ +public interface PropertiesController { + + /** + * Retrieves the associated properties provider. + * + * @return the associated properties provider object (non-null). + */ + PropertiesProvider getProvider(); + + /** + * Retrieves the key for the properties provider object. + * + * @return the key of the properties provider object (non-null). + */ + String getKey(); + + /** + * Retrieves the delimiter for the properties provider object. + *

+ * A delimiter is utilized by the provider to separate values + * (e.g., the colon character ':'). + *

+ * + * @return the delimiter in String format (non-null). + */ + char getDelimiter(); + + /** + * Initializes this property controller with the proper values. + */ + default void initialize() { + if (getProvider() == null || getDelimiter() == '\0' + || getKey() == null) { + throw new IllegalStateException("Properties Controller corrupted state!"); + } + if (getProvider().getSystemProperty() != null) { + return ; + } + System.setProperty(getKey(), ""); + } + + /** + * De-init this property controller to NULL. + */ + default void deInitialize() { + if (getProvider() == null || getDelimiter() == '\0' + || getKey() == null) { + throw new IllegalStateException("Properties Controller corrupted state!"); + } + if (getProvider().getSystemProperty() == null) { + return ; + } + System.clearProperty(getKey()); + } + + /** + * Iterates over the available delimited paths from this property. + *

+ * Note: the return of this inscribed function should provide a + * post-processing modifications to the 'word' literal; in most + * cases its an empty string, but could be otherwise a meaningful + * prefix for the next word (e.g., forward or back slash). + *

+ * + * @param function a function to execute on each time the iteration + * samples (i.e., when a delimited path is found). + * @param the type of the path object. + */ + default + void iterate(Function function) { + if (getProvider() == null || getDelimiter() == '\0' + || getKey() == null || function == null) { + throw new IllegalStateException("Properties Controller corrupted state!"); + } + + final String value = System.getProperty(getKey()); + String word = ""; + for (int i = 0; i < value.length(); i++) { + if (value.charAt(i) != getDelimiter()) { + word += value.charAt(i); + // sample on the last item + if ((i + 1) != value.length()) { + continue; + } + } + word = function.apply((T) FileSystems.getDefault().getPath(word)); + } + } + + /** + * Converts paths from this property controller concrete object + * to a contiguous buffer of paths. + * + * @return a contiguous buffer of paths. + * @throws IllegalStateException thrown if the controller has corrupted dependencies. + */ + default Path[] toList() throws IllegalStateException { + if (getProvider() == null || getDelimiter() == '\0' || getKey() == null) { + throw new IllegalStateException("Properties Controller corrupted state!"); + } + + final ArrayList paths = new ArrayList<>(); + final String value = System.getProperty(getKey()); + String word = ""; + for (int i = 0; i < value.length(); i++) { + if (value.charAt(i) != getDelimiter()) { + word += value.charAt(i); + // sample on the last item + if ((i + 1) != value.length()){ + continue; + } + } + paths.add(FileSystems.getDefault().getPath(word)); + // post-processing increment count + word = ""; + } + return paths.toArray(new Path[paths.size()]); + } + + /** + * Adds a path value to a system property. + * + * @param path a platform-independent wrapper object for a path (absolute or relative). + * @throws IllegalArgumentException thrown if the path object is corrupted. + * @throws IllegalStateException thrown if the controller has corrupted dependencies. + */ + default void addSystemPath(Path path) throws IllegalArgumentException, + IllegalStateException { + // preprocessing automata -- Input Validation States + if (path == null) { + throw new IllegalArgumentException("Cannot add a null path!"); + } + if (getProvider() == null || getDelimiter() == '\0' || getKey() == null) { + throw new IllegalStateException("Properties Controller corrupted state!"); + } + // preprocessing automata -- Automatically allocate new path appendices States + final String value = System.getProperty(getKey()); + final String newValue = value + getDelimiter() + path; + // processing automata -- Set the new value State + System.setProperty(getKey(), newValue); + } + + /** + * Retrieves a path from a path list of this property or throws + * {@link NoSuchFileException}. + * + * @param index the index of the required path. + * @return the required path or NULL if the path is not found. + * @throws IllegalStateException thrown if the controller has corrupted dependencies. + * @throws NoSuchFileException thrown if the Path queried for wasn't found. + */ + default Path get(int index) throws IllegalStateException, NoSuchFileException { + if (getProvider() == null || getDelimiter() == '\0' || getKey() == null) { + throw new IllegalStateException("Properties Controller corrupted state!"); + } + // preprocessing automata -- Substring delimited values + final String value = System.getProperty(getKey()); + String word = ""; + int pathCount = 0; + for (int i = 0; i < value.length(); i++) { + if (value.charAt(i) != getDelimiter()) { + word += value.charAt(i); + // sample on the last item + if ((i + 1) != value.length()){ + continue; + } + } + if (pathCount == index) { + return FileSystems.getDefault().getPath(word); + } + // post-processing increment count + word = ""; + pathCount++; + } + throw new NoSuchFileException("Cannot find the required file!s"); + } + + /** + * Searches and removes a path from the system paths adjusting the system property. + * + * @param path the path to query and remove. + * @throws IllegalArgumentException thrown if the path object is corrupted. + * @throws IllegalStateException thrown if the controller has corrupted dependencies. + * @throws NoSuchFileException thrown if the Path queried wasn't found. + */ + default void removeSystemPath(Path path) throws IllegalArgumentException, + IllegalStateException, + NoSuchFileException { + // preprocessing automata -- Input Validation States + if (path == null) { + throw new IllegalArgumentException("Cannot remove a null path!"); + } + if (getProvider() == null || getDelimiter() == '\0' || getKey() == null) { + throw new IllegalStateException("Properties Controller corrupted state!"); + } + // preprocessing automata -- Initializing local variables + final String value = System.getProperty(getKey()); + String newValue = ""; // initialize the new value automatically here + String word = ""; + int count = 0; + + // processing automata -- Exclude the path from the list of paths + for (int i = 0; i < value.length(); i++) { + if (value.charAt(i) != getDelimiter()) { + word += value.charAt(i); + // sample on the last item + if ((i + 1) != value.length()){ + continue; + } + } + // test equality for removal + if (word.equals(path.toString())) { + word = ""; + count++; + continue; + } + // test to append a delimiter + if (!newValue.isEmpty()) { + newValue += getDelimiter(); + } + newValue += word; + word = ""; // reset the intermediate + } + // post-processing automata -- Setting the new value State + if (count > 0) { + System.setProperty(getKey(), newValue); + return ; + } + // post-processing automata -- Failure signaling + throw new NoSuchFileException("Cannot find the required file!"); + } +} diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/platform/util/PropertiesControllerNamespace.java b/snaploader/src/main/java/electrostatic4j/snaploader/platform/util/PropertiesControllerNamespace.java new file mode 100644 index 0000000..2c58b4c --- /dev/null +++ b/snaploader/src/main/java/electrostatic4j/snaploader/platform/util/PropertiesControllerNamespace.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2023-2025, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'Electrostatic-Sandbox' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package electrostatic4j.snaploader.platform.util; + +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; + +/** + * Provides a namespace grouping properties controllers {@link PropertiesController} concrete objects. + * + * @author pavl_g. + */ +public final class PropertiesControllerNamespace { + + /** + * Cannot instantiate; Utility Class. + */ + private PropertiesControllerNamespace() { + throw new UnsupportedOperationException("Utility class"); + } + + /** + * A factorized singleton implementation for the Java path system controller to + * control the Java System loading path for native DLL (i.e., adds and removes paths). + */ + public static final PropertiesController systemDirectoryController = new PropertiesController() { + + @Override + public PropertiesProvider getProvider() { + return DefaultPropertiesProvider.SYSTEM_DIR; + } + + @Override + public String getKey() { + return "jsnaploader.library.path"; + } + + @Override + public char getDelimiter() { + return ':'; + } + + @Override + public void initialize() { + if (getProvider().getSystemProperty() != null) { + return ; + } + System.setProperty(getKey(), System.getProperty("java.library.path")); + } + + @Override + public void deInitialize() { + PropertiesController.super.deInitialize(); + } + + @Override + public void addSystemPath(Path path) throws IllegalArgumentException, IllegalStateException { + PropertiesController.super.addSystemPath(path); + } + + @Override + public void removeSystemPath(Path path) throws IllegalArgumentException, IllegalStateException, NoSuchFileException { + PropertiesController.super.removeSystemPath(path); + } + + @Override + public String toString() { + return System.getProperty(getKey()); + } + }; +} diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/platform/util/PropertiesProvider.java b/snaploader/src/main/java/electrostatic4j/snaploader/platform/util/PropertiesProvider.java index 7a8122f..493fb62 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/platform/util/PropertiesProvider.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/platform/util/PropertiesProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader + * Copyright (c) 2023-2025, The Electrostatic-Sandbox Distributed Simulation Framework, jSnapLoader * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,58 +32,6 @@ package electrostatic4j.snaploader.platform.util; -/** - * Provides platform-dependent system properties for the current running machine. - * - * @author pavl_g - */ -public enum PropertiesProvider { - - /** - * Provides a string representation for the absolute directory - * of the current user directory. - */ - USER_DIR(System.getProperty("user.dir")), - - /** - * Provides a string representation for the absolute directory - * of the user home. - */ - USER_HOME(System.getProperty("user.home")), - - /** - * Provides a string representation for the platform-dependent filesystem separator. - */ - FILE_SEPARATOR(System.getProperty("file.separator")), - - /** - * Provides a string representation for the filesystem separator of the Zip specification. - */ - ZIP_FILE_SEPARATOR("/"), - - /** - * Provides a string representation for the absolute path of the - * java interpreter binary. - */ - JAVA_HOME(System.getProperty("java.home")); - - private final String systemProperty; - - /** - * Instantiates a platform-dependent property object. - * - * @param systemProperty the string representation of the platform-dependent property - */ - PropertiesProvider(String systemProperty) { - this.systemProperty = systemProperty; - } - - /** - * Retrieves the platform-dependent property. - * - * @return a string representation for the platform-dependent property - */ - public String getSystemProperty() { - return systemProperty; - } +public interface PropertiesProvider { + String getSystemProperty(); } From 253728a2a6a11818948bd106fcfc317177508ad4 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Sat, 7 Jun 2025 05:18:06 -0500 Subject: [PATCH 2/4] NativeDynamicLibrary: introduced an accessor to the library file --- .../snaploader/platform/NativeDynamicLibrary.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java b/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java index e9b31c1..b252cc7 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/platform/NativeDynamicLibrary.java @@ -183,6 +183,10 @@ public String getExtractedLibrary() { + DefaultPropertiesProvider.FILE_SEPARATOR.getSystemProperty() + libraryFile; } + public String getLibraryFile() { + return libraryFile; + } + /** * Tests whether the native library is extracted to the specified extraction directory. * From bbb356439498e93948b6903b78c923a069c70447 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Sat, 7 Jun 2025 05:18:53 -0500 Subject: [PATCH 3/4] Applied API changes --- .../snaploader/NativeBinaryLoader.java | 38 +++++++++++++++++-- .../snaploader/filesystem/DirectoryPath.java | 8 ++-- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java index bcbc63c..1731998 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/NativeBinaryLoader.java @@ -32,7 +32,9 @@ package electrostatic4j.snaploader; +import java.io.File; import java.io.IOException; +import java.nio.file.FileSystems; import java.util.Arrays; import java.util.List; import java.util.jar.JarFile; @@ -45,6 +47,8 @@ import electrostatic4j.snaploader.library.LibraryLocator; import electrostatic4j.snaploader.platform.NativeDynamicLibrary; import electrostatic4j.snaploader.platform.util.NativeVariant; +import electrostatic4j.snaploader.platform.util.PropertiesControllerNamespace; +import electrostatic4j.snaploader.platform.util.PropertiesController; import electrostatic4j.snaploader.throwable.LoadingRetryExhaustionException; import electrostatic4j.snaploader.throwable.UnSupportedSystemError; import electrostatic4j.snaploader.util.CallingStackMetaData; @@ -89,11 +93,15 @@ public class NativeBinaryLoader { protected int numberOfLoadingFailure = 0; + private LoadingCriterion loadingCriterion; // cache the loading criterion for system controller use + /** * Instantiates a native dynamic library loader to extract and load a system-specific native dynamic library. */ public NativeBinaryLoader(final LibraryInfo libraryInfo) { this.libraryInfo = libraryInfo; + // initialize the system controller object + PropertiesControllerNamespace.systemDirectoryController.initialize(); } /** @@ -176,14 +184,17 @@ public NativeBinaryLoader loadLibrary(LoadingCriterion criterion) throws Excepti } // commands and loads the library from the system directories if (NativeVariant.Os.isAndroid() || criterion == LoadingCriterion.SYSTEM_LOAD) { - loadSystemBinary(); + loadSystemBinary(nativeDynamicLibrary); + loadingCriterion = LoadingCriterion.SYSTEM_LOAD; return this; } if (criterion == LoadingCriterion.INCREMENTAL_LOADING && nativeDynamicLibrary.isExtracted()) { loadBinary(nativeDynamicLibrary, criterion); + loadingCriterion = LoadingCriterion.INCREMENTAL_LOADING; return this; } cleanExtractBinary(nativeDynamicLibrary); + loadingCriterion = LoadingCriterion.CLEAN_EXTRACTION; return this; } @@ -196,6 +207,10 @@ public NativeDynamicLibrary getNativeDynamicLibrary() { return nativeDynamicLibrary; } + public PropertiesController getSystemDirectoryController() { + return PropertiesControllerNamespace.systemDirectoryController; + } + /** * Enables the logging for this object, default value is false. * @@ -271,12 +286,27 @@ public NativeBinaryLoader setMaxNumberOfLoadingFailure(int maxNumberOfLoadingFai } /** - * Loads a native binary from the system directories into the process virtual + * Loads a native binary from the customized system directories into the process virtual * address space using the library basename in a platform-dependent way. */ - protected void loadSystemBinary() { + protected void loadSystemBinary(NativeDynamicLibrary dynamicLibrary) { + SnapLoaderLogger.log(Level.INFO, getClass().getName(), "loadSystemBinary", "Loading library from the system: " + + Arrays.toString(PropertiesControllerNamespace.systemDirectoryController.toList())); try { - System.loadLibrary(libraryInfo.getBaseName()); + // use custom system directories for desktop ONLY! + if (NativeVariant.Os.isDesktop()) { + PropertiesControllerNamespace.systemDirectoryController.iterate(path -> { + final File lib = new File(FileSystems.getDefault() + .getPath(path.toString(), + dynamicLibrary.getLibraryFile()).toString()); + if (lib.exists()) { + System.load(lib.getAbsolutePath()); + } + return ""; + }); + } else { + System.loadLibrary(libraryInfo.getBaseName()); + } SnapLoaderLogger.log(Level.INFO, getClass().getName(), "loadSystemBinary", "Successfully loaded library from the system: " + libraryInfo.getBaseName()); if (nativeBinaryLoadingListener != null) { diff --git a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/DirectoryPath.java b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/DirectoryPath.java index 3e560aa..fd758e9 100644 --- a/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/DirectoryPath.java +++ b/snaploader/src/main/java/electrostatic4j/snaploader/filesystem/DirectoryPath.java @@ -32,7 +32,7 @@ package electrostatic4j.snaploader.filesystem; -import electrostatic4j.snaploader.platform.util.PropertiesProvider; +import electrostatic4j.snaploader.platform.util.DefaultPropertiesProvider; /** * A class denotes and provides a directory absolute path. @@ -45,13 +45,13 @@ public final class DirectoryPath { * An alias object for the current working directory absolute path. */ public static final DirectoryPath USER_DIR = - new DirectoryPath(PropertiesProvider.USER_DIR.getSystemProperty()); + new DirectoryPath(DefaultPropertiesProvider.USER_DIR.getSystemProperty()); /** * An alias object for the root user home directory absolute path. */ public static final DirectoryPath USER_HOME = - new DirectoryPath(PropertiesProvider.USER_HOME.getSystemProperty()); + new DirectoryPath(DefaultPropertiesProvider.USER_HOME.getSystemProperty()); /** * When combined with the @@ -85,7 +85,7 @@ public DirectoryPath(final String root, final String... entries) { if (entry == null) { continue; } - path = getPath() + PropertiesProvider.FILE_SEPARATOR.getSystemProperty() + entry; + path = getPath() + DefaultPropertiesProvider.FILE_SEPARATOR.getSystemProperty() + entry; } } From e47b390656d1b42642739523f00cd8a86e6682c8 Mon Sep 17 00:00:00 2001 From: pavl-g Date: Sat, 7 Jun 2025 05:19:19 -0500 Subject: [PATCH 4/4] snaploader-examples: applied API changes --- .../snaploader/examples/TestBasicFeatures.java | 6 +++--- .../snaploader/examples/TestBasicFeatures2.java | 6 +++--- .../snaploader/examples/TestFilesystemException.java | 7 +++---- .../snaploader/examples/TestFilesystemMemoryLeak.java | 6 +++--- .../snaploader/examples/TestNativeDllLoader.java | 6 +++--- .../examples/TestRetryExhaustionException.java | 6 +++--- .../snaploader/examples/TestZipExtractor.java | 6 +++--- .../snaploader/examples/api/NativeDllLoader.java | 9 +++++++++ 8 files changed, 30 insertions(+), 22 deletions(-) diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBasicFeatures.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBasicFeatures.java index bd4674c..ea9aaea 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBasicFeatures.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBasicFeatures.java @@ -39,7 +39,7 @@ import electrostatic4j.snaploader.platform.NativeDynamicLibrary; import electrostatic4j.snaploader.platform.util.NativeVariant; import electrostatic4j.snaploader.platform.util.PlatformPredicate; -import electrostatic4j.snaploader.platform.util.PropertiesProvider; +import electrostatic4j.snaploader.platform.util.DefaultPropertiesProvider; import electrostatic4j.snaploader.LoadingCriterion; /** @@ -92,7 +92,7 @@ protected static void printDetails(NativeBinaryLoader loader) { } protected static DirectoryPath getLibrariesAbsolutePath() { - return new DirectoryPath(PropertiesProvider.USER_DIR.getSystemProperty(), "libs"); + return new DirectoryPath(DefaultPropertiesProvider.USER_DIR.getSystemProperty(), "libs"); } protected static DirectoryPath getJarFilePath() { @@ -101,7 +101,7 @@ protected static DirectoryPath getJarFilePath() { protected static String getNativeDynamicLibraryPath() { return getLibrariesAbsolutePath().getPath() + - PropertiesProvider.FILE_SEPARATOR.getSystemProperty() + + DefaultPropertiesProvider.FILE_SEPARATOR.getSystemProperty() + "lib" + getLibraryBaseName() + ".so"; } diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBasicFeatures2.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBasicFeatures2.java index 8be00b9..ad4837b 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBasicFeatures2.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestBasicFeatures2.java @@ -42,7 +42,7 @@ import electrostatic4j.snaploader.platform.NativeDynamicLibrary; import electrostatic4j.snaploader.platform.util.NativeVariant; import electrostatic4j.snaploader.platform.util.PlatformPredicate; -import electrostatic4j.snaploader.platform.util.PropertiesProvider; +import electrostatic4j.snaploader.platform.util.DefaultPropertiesProvider; import electrostatic4j.snaploader.LoadingCriterion; /** @@ -55,8 +55,8 @@ public final class TestBasicFeatures2 { public static void main(String[] args) throws Exception { - final Path compressionPath = Paths.get(PropertiesProvider.USER_DIR.getSystemProperty(), "libs", TestBasicFeatures.getJarFile()); - final Path extractionPath = Files.createDirectories(Paths.get(PropertiesProvider.USER_DIR.getSystemProperty(), "libs", + final Path compressionPath = Paths.get(DefaultPropertiesProvider.USER_DIR.getSystemProperty(), "libs", TestBasicFeatures.getJarFile()); + final Path extractionPath = Files.createDirectories(Paths.get(DefaultPropertiesProvider.USER_DIR.getSystemProperty(), "libs", NativeVariant.OS_NAME.getProperty(), NativeVariant.OS_ARCH.getProperty())); final LibraryInfo libraryInfo = new LibraryInfo(new DirectoryPath(compressionPath.toString()), new DirectoryPath("lib/placeholder"), diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestFilesystemException.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestFilesystemException.java index 60b3605..4f99c7e 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestFilesystemException.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestFilesystemException.java @@ -8,17 +8,16 @@ import electrostatic4j.snaploader.platform.util.DefaultDynamicLibraries; import electrostatic4j.snaploader.platform.util.NativeVariant; import electrostatic4j.snaploader.platform.util.PlatformPredicate; -import electrostatic4j.snaploader.platform.util.PropertiesProvider; +import electrostatic4j.snaploader.platform.util.DefaultPropertiesProvider; -import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public final class TestFilesystemException { public static void main(String[] args) throws Exception { - final Path compressionPath = Paths.get(PropertiesProvider.USER_DIR.getSystemProperty(), "libs", TestBasicFeatures.getJarFile()); - final Path extractionPath = Files.createDirectories(Paths.get(PropertiesProvider.USER_DIR.getSystemProperty(), "libs", + final Path compressionPath = Paths.get(DefaultPropertiesProvider.USER_DIR.getSystemProperty(), "libs", TestBasicFeatures.getJarFile()); + final Path extractionPath = Files.createDirectories(Paths.get(DefaultPropertiesProvider.USER_DIR.getSystemProperty(), "libs", NativeVariant.OS_NAME.getProperty(), NativeVariant.OS_ARCH.getProperty())); final LibraryInfo libraryInfo = new LibraryInfo(new DirectoryPath(compressionPath.toString()), new DirectoryPath("lib/placeholder"), diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestFilesystemMemoryLeak.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestFilesystemMemoryLeak.java index 4e28724..3eb4b4d 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestFilesystemMemoryLeak.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestFilesystemMemoryLeak.java @@ -35,7 +35,7 @@ import electrostatic4j.snaploader.filesystem.FileExtractionListener; import electrostatic4j.snaploader.filesystem.FileExtractor; import electrostatic4j.snaploader.filesystem.FileLocator; -import electrostatic4j.snaploader.platform.util.PropertiesProvider; +import electrostatic4j.snaploader.platform.util.DefaultPropertiesProvider; import electrostatic4j.snaploader.util.SnapLoaderLogger; import java.util.logging.Level; import java.util.logging.Logger; @@ -78,12 +78,12 @@ public void onExtractionFinalization(FileExtractor fileExtractor, FileLocator fi protected static String getZipAbsolutePath() { return TestBasicFeatures.getLibrariesAbsolutePath().getPath() + - PropertiesProvider.FILE_SEPARATOR.getSystemProperty() + "jmelogo700.zip"; + DefaultPropertiesProvider.FILE_SEPARATOR.getSystemProperty() + "jmelogo700.zip"; } protected static String getExtractionPath() { return TestBasicFeatures.getLibrariesAbsolutePath().getPath() + - PropertiesProvider.FILE_SEPARATOR.getSystemProperty() + getFilePath(); + DefaultPropertiesProvider.FILE_SEPARATOR.getSystemProperty() + getFilePath(); } protected static String getFilePath() { diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestNativeDllLoader.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestNativeDllLoader.java index 3f77d51..4c24276 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestNativeDllLoader.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestNativeDllLoader.java @@ -12,8 +12,8 @@ public final class TestNativeDllLoader { public static void main(String[] args) throws Exception { final NativeDynamicLibrary[] baseLibs = new NativeDynamicLibrary[] { DefaultDynamicLibraries.ANDROID_ALL, - new NativeDynamicLibrary("linux/x86-64/com/github/stephengoldd", PlatformPredicate.LINUX_X86_64), - new NativeDynamicLibrary("windows/x86-64/com/github/stephengoldd", PlatformPredicate.WIN_X86_64), + new NativeDynamicLibrary("linux/x86-64/com/github/stephengold", PlatformPredicate.LINUX_X86_64), + new NativeDynamicLibrary("windows/x86-64/com/github/stephengold", PlatformPredicate.WIN_X86_64), }; final NativeDynamicLibrary[] cpuEnhancedLibs = new NativeDynamicLibrary[]{ @@ -24,7 +24,7 @@ public static void main(String[] args) throws Exception { "avx", "avx2", "sse4_1", "sse4_2")), }; final LibraryInfo info = new LibraryInfo(new DirectoryPath("linux/x86-64/com/github/stephengold"), - "joltjnid", DirectoryPath.USER_DIR); + "joltjni", DirectoryPath.USER_DIR); final NativeDllLoader nativeDllLoader = new NativeDllLoader(baseLibs, cpuEnhancedLibs, info, true, true); nativeDllLoader.loadCpuEnhancedLibs(LoadingCriterion.INCREMENTAL_LOADING); } diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestRetryExhaustionException.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestRetryExhaustionException.java index 70de1ee..98aac4c 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestRetryExhaustionException.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestRetryExhaustionException.java @@ -43,7 +43,7 @@ import electrostatic4j.snaploader.platform.util.DefaultDynamicLibraries; import electrostatic4j.snaploader.platform.util.NativeVariant; import electrostatic4j.snaploader.platform.util.PlatformPredicate; -import electrostatic4j.snaploader.platform.util.PropertiesProvider; +import electrostatic4j.snaploader.platform.util.DefaultPropertiesProvider; /** * Tests retry exhaustion on a broken library. @@ -53,8 +53,8 @@ public class TestRetryExhaustionException { public static void main(String[] args) throws Exception { - final Path compressionPath = Paths.get(PropertiesProvider.USER_DIR.getSystemProperty(), "libs", "corrupted-lib.jar"); - final Path extractionPath = Files.createDirectories(Paths.get(PropertiesProvider.USER_DIR.getSystemProperty(), "libs", + final Path compressionPath = Paths.get(DefaultPropertiesProvider.USER_DIR.getSystemProperty(), "libs", "corrupted-lib.jar"); + final Path extractionPath = Files.createDirectories(Paths.get(DefaultPropertiesProvider.USER_DIR.getSystemProperty(), "libs", NativeVariant.OS_NAME.getProperty(), NativeVariant.OS_ARCH.getProperty())); final LibraryInfo libraryInfo = new LibraryInfo(new DirectoryPath(compressionPath.toString()), new DirectoryPath("lib/placeholder"), diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestZipExtractor.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestZipExtractor.java index f03cf65..2089a1e 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestZipExtractor.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/TestZipExtractor.java @@ -35,7 +35,7 @@ import electrostatic4j.snaploader.filesystem.FileExtractionListener; import electrostatic4j.snaploader.filesystem.FileExtractor; import electrostatic4j.snaploader.filesystem.FileLocator; -import electrostatic4j.snaploader.platform.util.PropertiesProvider; +import electrostatic4j.snaploader.platform.util.DefaultPropertiesProvider; import electrostatic4j.snaploader.throwable.FilesystemResourceScavengingException; import java.util.zip.ZipFile; @@ -80,12 +80,12 @@ public void onExtractionFinalization(FileExtractor fileExtractor, FileLocator fi protected static String getZipAbsolutePath() { return TestBasicFeatures.getLibrariesAbsolutePath().getPath() + - PropertiesProvider.FILE_SEPARATOR.getSystemProperty() + "jmelogo700.zip"; + DefaultPropertiesProvider.FILE_SEPARATOR.getSystemProperty() + "jmelogo700.zip"; } protected static String getExtractionPath() { return TestBasicFeatures.getLibrariesAbsolutePath().getPath() + - PropertiesProvider.FILE_SEPARATOR.getSystemProperty() + getFilePath(); + DefaultPropertiesProvider.FILE_SEPARATOR.getSystemProperty() + getFilePath(); } protected static String getFilePath() { diff --git a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/api/NativeDllLoader.java b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/api/NativeDllLoader.java index c62ad8d..f5bb372 100644 --- a/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/api/NativeDllLoader.java +++ b/snaploader-examples/src/main/java/electrostatic4j/snaploader/examples/api/NativeDllLoader.java @@ -348,4 +348,13 @@ protected void signalImminentFailure(CallingStackMetaData callingStackMetaData) // signal an imminent failure and crash the application Runtime.getRuntime().exit(-callingStackMetaData.getErrorCause().hashCode()); } + + /** + * Retrieves the associated native binary loader object. + * + * @return a native binary loader object that is associated wtih this object. + */ + public NativeBinaryLoader getLoader() { + return loader; + } }