From 61b6f26e60e6f346077082ea5527631c0d66e2e6 Mon Sep 17 00:00:00 2001 From: Darius Maitia Date: Thu, 19 Dec 2024 11:48:06 -0300 Subject: [PATCH] Native loading refactor (#162) * Alignment: bytes package * Alignment: encoding update * Alignment: config package * Alignment: replacing all exceptions with ZError * Alignment: ext package * Alignment: jni callbacks * Alignment: config * Alignment: JNIKeyExpr * Alignment: JNIPublisher * Alignment: JNIQuery * Alignment: JNIScout * Alignment: JNISession * Alignment JNIZBytes & JNIZenohId * Alignment: KeyExpr & SetIntersectionLevel * Alignment: pubsub package * Alignment: Publisher & qos package * Alignment: query package - wip * Alignment: adding scouting package * Alignment: removing Value * Alignment: logger * Alignmment: Zenoh.kt - wip * Alignment: publisher - adding encoding and reliability to builder * Alignment: subscriber * Alignment: sample * Alignment: query & reply - wip * Alignment: Put & Session * Alignment: fix 'IntoSelector' * Alignment: updating zenoh-jni * Alignment: wip - converting tests to java tests. Added config tests. * Alignment: wip - converting tests to java tests. Added delete test. * Alignment: wip - converting tests to java tests. Added encoding tests. * Alignment: wip - converting tests to java tests. Added get tests. * Alignment: wip - converting tests to java tests. Added key expr tests. * Alignment: wip - converting tests to java tests. Added parameters tests. * Alignment: wip - converting tests to java tests. Added publisher tests. * Alignment: wip - converting tests to java tests. Added Queryable tests. * Alignment: wip - converting tests to java tests. Added Put tests. * Alignment: wip - Added Scouting tests + adding scouting builder. * Alignment: wrapping up scouting, closing queue upon scout close. * Alignment: adding selector tests * Alignment: fix SessionInfo + adding tests * Alignment: fix Scouting queue test * amend! Alignment: fix SessionInfo + adding tests Alignment: fix SessionInfo + adding tests * Alignment: session tests * Alignment: user attachment tests * Alignment: subscriber tests * Alignment: removing the zenoh-ext package (to be added later in another PR) * Alignment: Publisher config params * Alignment: Subscriber config params * Alignment: Queryable config params * Alignment: Subscriber config params refactor * Alignment: Queryable declaration and Query.reply config params. * Alignment: Get config params * Alignment: Subscriber config params refactor * Fix config test * Alignment - Scouting config params * Alignment: adding Liveliness * Gitignore update * Alignment: fix logging * Alignment: publisher put and delete config param * Alignment: examples - adding picocli for CLI args * Alignment: examples - adding missing examples * Alignment: examples - adding ping and pong examples * Alignment: examples refactor + refactor queryable config logic * Alignment: fix publisher put encoding fallback * Alignment: removing SubscriberConfig.kt * Alignment: renaming PublisherConfig to PublisherOptions * Alignment: renaming DeleteConfig to DeleteOptions and removing 'builder' functions in it. * Alignment: renaming GetConfig to GetOptions and removing 'builder' functions in it. * Alignment: renaming PutConfig to PutOptions and removing 'builder' functions in it. * Alignment: renaming ReplyConfig to ReplyOptions and removing 'builder' functions in it. * Alignment: renaming ReplyDelConfig to ReplyDelOptions and removing 'builder' functions in it. * Alignment: renaming ReplyErrConfig to ReplyErrOptions and removing 'builder' functions in it. * Alignment: renaming QueryableConfig to QueryableOptions and removing 'builder' functions in it. * Alignment: renaming ScoutConfig to ScoutOptions and removing 'builder' functions in it. * Alignment: renaming Liveliness.SubscriberConfig + renaming variables * Alignment: queryable options refactor * Alignment: removing Resolvable * Alignment: splitting Queryable, Subscriber and Get into Handler and Callback subclasses + tidying up documentation. * Alignment: removing JNIZBytes * Alignment: removing unused kotlin json dependency * Alignment: options refactor on QoS param * Native loading refactor Aligning with zenoh-kotlin's native lib loading logic: - Adding extra checks for determining the platform on top of which zenoh-java is running - Defaulting javaClass's class loader in case the system class loader fails to find the native lib --- .../src/jvmMain/kotlin/io/zenoh/Target.kt | 2 +- .../src/jvmMain/kotlin/io/zenoh/Zenoh.kt | 38 +++++++++++++------ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/zenoh-java/src/jvmMain/kotlin/io/zenoh/Target.kt b/zenoh-java/src/jvmMain/kotlin/io/zenoh/Target.kt index 4bb087ee..0e58c219 100644 --- a/zenoh-java/src/jvmMain/kotlin/io/zenoh/Target.kt +++ b/zenoh-java/src/jvmMain/kotlin/io/zenoh/Target.kt @@ -14,7 +14,7 @@ package io.zenoh -enum class Target { +internal enum class Target { WINDOWS_X86_64_MSVC, LINUX_X86_64, LINUX_AARCH64, diff --git a/zenoh-java/src/jvmMain/kotlin/io/zenoh/Zenoh.kt b/zenoh-java/src/jvmMain/kotlin/io/zenoh/Zenoh.kt index 11ae638c..593e451d 100644 --- a/zenoh-java/src/jvmMain/kotlin/io/zenoh/Zenoh.kt +++ b/zenoh-java/src/jvmMain/kotlin/io/zenoh/Zenoh.kt @@ -27,7 +27,7 @@ import java.util.zip.ZipInputStream internal actual object ZenohLoad { private const val ZENOH_LIB_NAME = "zenoh_jni" - init { + init { // Try first to load the local native library for cases in which the module was built locally, // otherwise try to load from the JAR. if (tryLoadingLocalLibrary().isFailure) { @@ -45,24 +45,33 @@ internal actual object ZenohLoad { */ private fun determineTarget(): Result = runCatching { val osName = System.getProperty("os.name").lowercase() - val osArch = System.getProperty("os.arch") + val osArch = System.getProperty("os.arch").lowercase() val target = when { osName.contains("win") -> when { - osArch.contains("x86_64") || osArch.contains("amd64") -> Target.WINDOWS_X86_64_MSVC - else -> throw UnsupportedOperationException("Unsupported architecture: $osArch") + osArch.contains("x86_64") || osArch.contains("amd64") || osArch.contains("x64") -> + Target.WINDOWS_X86_64_MSVC + else -> throw UnsupportedOperationException("Unsupported architecture on Windows: $osArch") } - osName.contains("mac") -> when { - osArch.contains("x86_64") || osArch.contains("amd64") -> Target.APPLE_X86_64 - osArch.contains("aarch64") -> Target.APPLE_AARCH64 - else -> throw UnsupportedOperationException("Unsupported architecture: $osArch") + osName.contains("mac") || osName.contains("darwin") || osName.contains("os x") -> when { + osArch.contains("x86_64") || osArch.contains("amd64") || osArch.contains("x64") -> + Target.APPLE_X86_64 + + osArch.contains("aarch64") || osArch.contains("arm64") -> + Target.APPLE_AARCH64 + + else -> throw UnsupportedOperationException("Unsupported architecture on macOS: $osArch") } osName.contains("nix") || osName.contains("nux") || osName.contains("aix") -> when { - osArch.contains("x86_64") || osArch.contains("amd64") -> Target.LINUX_X86_64 - osArch.contains("aarch64") -> Target.LINUX_AARCH64 - else -> throw UnsupportedOperationException("Unsupported architecture: $osArch") + osArch.contains("x86_64") || osArch.contains("amd64") || osArch.contains("x64") -> + Target.LINUX_X86_64 + + osArch.contains("aarch64") || osArch.contains("arm64") -> + Target.LINUX_AARCH64 + + else -> throw UnsupportedOperationException("Unsupported architecture on Linux/Unix: $osArch") } else -> throw UnsupportedOperationException("Unsupported platform: $osName") @@ -108,7 +117,9 @@ internal actual object ZenohLoad { } private fun loadLibraryAsInputStream(target: Target): Result = runCatching { - val libUrl = ClassLoader.getSystemClassLoader().getResourceAsStream("$target/$target.zip")!! + val targetName = "$target/$target.zip" + val libUrl = ClassLoader.getSystemClassLoader().getResourceAsStream(targetName) + ?: javaClass.classLoader.getResourceAsStream(targetName)!! val uncompressedLibFile = unzipLibrary(libUrl) return Result.success(FileInputStream(uncompressedLibFile.getOrThrow())) } @@ -145,6 +156,9 @@ internal actual object ZenohLoad { */ private fun tryLoadingLocalLibrary(): Result = runCatching { val lib = ClassLoader.getSystemClassLoader().findLibraryStream(ZENOH_LIB_NAME) + ?: javaClass.classLoader.findLibraryStream( + ZENOH_LIB_NAME + ) if (lib != null) { loadZenohJNI(lib) } else {