diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aceb5f2e..74c7833f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,14 @@ jobs: with: distribution: temurin java-version: 11 - + + - uses: nttld/setup-ndk@v1 + id: setup-ndk + with: + ndk-version: r26 + add-to-path: false + link-to-sdk: true + - name: Install Rust uses: actions-rs/toolchain@v1 with: @@ -53,9 +60,5 @@ jobs: working-directory: zenoh-jni run: cargo build --verbose - - name: Cargo Test - working-directory: zenoh-jni - run: cargo test --verbose -- --nocapture - - - name: Gradle Build - run: gradle build --scan + - name: Gradle Test + run: gradle jvmTest --info diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dd2f88d7..364bcd88 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,6 +27,13 @@ jobs: distribution: temurin java-version: 11 + - uses: nttld/setup-ndk@v1 + id: setup-ndk + with: + ndk-version: r26 + add-to-path: false + link-to-sdk: true + - name: Install Rust uses: actions-rs/toolchain@v1 with: @@ -48,12 +55,8 @@ jobs: working-directory: zenoh-jni run: cargo build --verbose - - name: Cargo Test - working-directory: zenoh-jni - run: cargo test --verbose -- --nocapture - - - name: Gradle Build - run: gradle build --scan + - name: Gradle Test + run: gradle jvmTest --info build_doc_and_deploy: name: Build and Deploy Documentation @@ -65,9 +68,7 @@ jobs: uses: gradle/gradle-build-action@v2 - name: Build doc - run: | - cd zenoh-kotlin - gradle dokkaHtml + run: gradle dokkaHtml - name: Deploy doc uses: peaceiris/actions-gh-pages@v3 diff --git a/README.md b/README.md index a500a921..be9688ad 100644 --- a/README.md +++ b/README.md @@ -16,14 +16,15 @@ Zenoh (pronounce _/zeno/_) unifies data in motion, data at rest and computations Check the website [zenoh.io](http://zenoh.io) and the [roadmap](https://github.com/eclipse-zenoh/roadmap) for more detailed information. + ---- -# Kotlin API +# Kotlin Kotlin API This repository provides a Kotlin binding based on the main [Zenoh implementation written in Rust](https://github.com/eclipse-zenoh/zenoh). -The code relies on native code written in Rust and communicates with it via the Java Native Interface (JNI). +The code relies on the Zenoh JNI native library, which written in Rust and communicates with the Kotlin layer via the Java Native Interface (JNI). ## Documentation @@ -41,61 +42,113 @@ Basically: * Rust ([Installation guide](https://doc.rust-lang.org/cargo/getting-started/installation.html)) * Kotlin ([Installation guide](https://kotlinlang.org/docs/getting-started.html#backend)) * Gradle ([Installation guide](https://gradle.org/install/)) +* Android SDK ([Installation guide](https://developer.android.com/about/versions/11/setup-sdk)) -## Step by step +## Android Android -### Building zenoh-jni +In order to use these bindings in a native Android project, what we will do is to build them as an Android NDK Library, +publishing it into Maven local for us to be able to easily import it in our project. -Since Zenoh-Kotlin relies on a native rust interface that communicates with Zenoh, first you need to build it. +It is required to have the [NDK (native development kit)](https://developer.android.com/ndk) installed, since we are going to compile Zenoh JNI for multiple +android native targets. +It can be set up by using Android Studio (go to `Preferences > Appearance & Behavior > System settings > Android SDK > SDK Tools` and tick the NDK box), +or alternatively it can be found [here](https://developer.android.com/ndk/downloads). -Find the code in this repository on [here](/zenoh-jni): +The native platforms we are going to target are the following ones: +``` +- x86 +- x86_64 +- arm +- arm64 +``` +Therefore, if they are not yet already added to the Rust toolchain, run: ```bash -cd zenoh-jni +rustup target add armv7-linux-androideabi; \ +rustup target add i686-linux-android; \ +rustup target add aarch64-linux-android; \ +rustup target add x86_64-linux-android ``` -The let's build it with Cargo: +to install them. + +So, in order to publish the library onto Maven Local, run: ```bash -cargo build --release +gradle publishAndroidReleasePublicationToMavenLocal ``` -This will generate a library under `/target/release` named: -* MacOS: `libzenoh_jni.dylib` -* Linux: `libzenoh_jni.so` -* Windows: `libzenoh_jni.dll` +This will first trigger the compilation of the Zenoh-JNI for the previously mentioned targets, and secondly will +publish the library, containing the native binaries. -This file needs to be discoverable by the JVM. Therefore, `zenoh_jni` library should also be on the `java.library.path`. Thus depending on your -system make sure to install it at the proper place. +You should now be able to see the package under `~/.m2/repository/io/zenoh/zenoh-kotlin-android/0.10.0-rc` +with the following files: +``` +zenoh-kotlin-android-0.10.0-rc-sources.jar +zenoh-kotlin-android-0.10.0-rc.aar +zenoh-kotlin-android-0.10.0-rc.module +zenoh-kotlin-android-0.10.0-rc.pom +``` -For MacOS and Unix-like operating systems, the library is expected to be found under `/usr/local/lib`. -For Windows users you may want to add the location of the library to your `$PATH` environment variable. +Now the library is published on maven local, let's now see how to import it into an Android project. -:warning: Note that failure to make `zenoh_jni` discoverable will cause the kotlin tests fail during the kotlin build process and -any further intent to use this library will result in an error during runtime, due to an `UnsatisfiedLinkError`. +First, we need to indicate we want to look into mavenLocal for our library, so in your top level `build.gradle.kts` you need to specify +the `mavenLocal` repository: +```agsl +repositories { + mavenCentral() + ... + mavenLocal() // We add this line +} +``` -### Building Kotlin! +Then in your app's `build.gradle.kts` filen add the dependency: +``` +implementation("io.zenoh:zenoh-kotlin-android:0.10.0-rc") +``` -Now let's go to the [zenoh-kotlin subdirectory](zenoh-kotlin) of this repository. +And finally, do not forget to add the required internet permissions on your manifest! -```bash -cd zenoh-kotlin +``` + + ``` +And that was it! You can now import the code from the `io.zenoh` package and use it at your will. -It is best to build and run using the `gradle` wrapper, thus type: +## JVM JVM - $ gradle wrapper +To publish a library for a JVM project into Maven local, run + +```bash +gradle publishJvmPublicationToMavenLocal +``` -Then you can build by simply: +This will first, trigger the compilation of Zenoh-JNI, and second publish the library into maven local, containing the native library +as a resource that will be loaded during runtime. - $ ./gradlew build +:warning: The native library will be compiled against the default rustup target on your machine, so although it may work fine +for you on your desktop, the generated publication may not be working on another computer with a different operating system and/or a different cpu architecture. +This is different from Android in the fact that Android provides an in build mechanism to dynamically load native libraries depending on the CPU's architecture, while +for JVM it's not the case and that logic must be implemented. Building against multiple targets and loading them dynamically is one of our short term goals. +Once we have published the package, we should be able to find it under `~/.m2/repository/io/zenoh/zenoh-kotlin-jvm/0.10.0-rc`. +Finally, in the `build.gradle.kts` file of the project where you intend to use this library, add mavenLocal to the list of repositories and add zenoh-kotlin as a dependency: -That was it! We now can build our first Kotlin app using Zenoh! +``` +repositories { + mavenCentral() + mavenLocal() +} + +dependencies { + testImplementation(kotlin("test")) + implementation("io.zenoh:zenoh-kotlin-jvm:0.10.0-rc") +} +``` -### Building the documentation +## Building the documentation Because it's a Kotlin project, we use [Dokka](https://kotlinlang.org/docs/dokka-introduction.html) to generate the documentation. @@ -104,6 +157,31 @@ In order to build it, run: gradle zenoh-kotlin:dokkaHtml ``` +## Running the tests + +To run the tests, run: + +```bash +gradle jvmTest +``` + +This will compile the native library on debug mode (if not already available) and run the tests afterward against the JVM target. +Running the tests against the Android target (by using `gradle testDebugUnitTest`) is equivalent to running them against the JVM one, since they are common +tests executed locally as Unit tests. + +## Logging + +Rust logs are propagated when setting the property `zenoh.logger=debug` (using RUST_LOG=debug will result in nothing) + +For instance running the ZPub test as follows: + +```bash +gradle -Pzenoh.logger=debug ZPub +``` + +causes the logs to appear in standard output. + +The log levels are the ones from Rust: `trace`, `info`, `debug`, `error` and `warn`. --- @@ -120,6 +198,10 @@ For instance in order to run the [ZPub](examples/src/main/kotlin/io.zenoh/ZPub.k You can find more info about these examples on the [examples README file](/examples/README.md). + + + + ---- # :warning: Considerations & Future work diff --git a/android-robot.png b/android-robot.png new file mode 100644 index 00000000..162313da Binary files /dev/null and b/android-robot.png differ diff --git a/build.gradle.kts b/build.gradle.kts index 072f5bcf..ab3c317b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,20 +12,30 @@ // ZettaScale Zenoh Team, // + +buildscript { + repositories { + google() + } + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0") + classpath("org.mozilla.rust-android-gradle:plugin:0.9.3") + classpath("com.android.tools.build:gradle:7.4.2") + } +} + plugins { - kotlin("jvm") version "1.9.0" - id("org.jetbrains.dokka") version "1.8.20" + id("com.android.library") version "7.4.2" apply false + id("org.jetbrains.kotlin.android") version "1.9.10" apply false + id("org.jetbrains.kotlin.multiplatform") version "1.9.0" apply false + id("org.mozilla.rust-android-gradle.rust-android") version "0.9.3" apply false + id("org.jetbrains.dokka") version "1.8.20" apply false + id("com.adarshr.test-logger") version "3.2.0" apply false } subprojects { - apply(plugin = "kotlin") - apply(plugin = "org.jetbrains.dokka") - - kotlin { - jvmToolchain(11) - } - repositories { + google() mavenCentral() } } diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 12698a2c..3b1eadff 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -15,6 +15,14 @@ group = "io.zenoh" version = "0.11.0-dev" +plugins { + kotlin("jvm") +} + +kotlin { + jvmToolchain(11) +} + dependencies { implementation(project(":zenoh-kotlin")) implementation("commons-net:commons-net:3.9.0") @@ -35,10 +43,11 @@ tasks { examples.forEach { example -> register(example, JavaExec::class) { + dependsOn("CompileZenohJNI") description = "Run the $example example" mainClass.set("io.zenoh.${example}Kt") classpath(sourceSets["main"].runtimeClasspath) - val zenohPaths = "/usr/local/lib:../zenoh-jni/target/release" + val zenohPaths = "../zenoh-jni/target/release" val defaultJvmArgs = arrayListOf("-Djava.library.path=$zenohPaths") val loggerLvl = project.findProperty("zenoh.logger")?.toString() if (loggerLvl != null) { @@ -49,3 +58,9 @@ tasks { } } } + +tasks.register("CompileZenohJNI") { + project.exec { + commandLine("cargo", "build", "--release", "--manifest-path", "../zenoh-jni/Cargo.toml") + } +} diff --git a/jvm.png b/jvm.png new file mode 100644 index 00000000..07f1b123 Binary files /dev/null and b/jvm.png differ diff --git a/kotlin-logo.png b/kotlin-logo.png new file mode 100644 index 00000000..b78e63a0 Binary files /dev/null and b/kotlin-logo.png differ diff --git a/settings.gradle.kts b/settings.gradle.kts index 16eef7dc..6126e8ce 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -12,10 +12,18 @@ // ZettaScale Zenoh Team, // +pluginManagement { + repositories { + gradlePluginPortal() + mavenCentral() + google() + } +} rootProject.name = "zenoh-kotlin" include(":zenoh-kotlin") include(":examples") +include(":zenoh-jni") plugins { id("org.gradle.toolchains.foojay-resolver-convention") version("0.4.0") diff --git a/zenoh-kotlin/build.gradle.kts b/zenoh-kotlin/build.gradle.kts index 3fe849b1..91486dde 100644 --- a/zenoh-kotlin/build.gradle.kts +++ b/zenoh-kotlin/build.gradle.kts @@ -16,17 +16,154 @@ group = "io.zenoh" version = "0.11.0-dev" plugins { - id("com.adarshr.test-logger") version "3.2.0" + id("com.android.library") + kotlin("multiplatform") + id("com.adarshr.test-logger") + id("org.jetbrains.dokka") + id("org.mozilla.rust-android-gradle.rust-android") + `maven-publish` } -dependencies { - testImplementation(kotlin("test")) - implementation("commons-net:commons-net:3.9.0") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") +android { + namespace = "io.zenoh" + compileSdk = 30 + + ndkVersion = "26.0.10792818" + + defaultConfig { + minSdk = 30 + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + buildTypes { + getByName("release") { + isMinifyEnabled = false + } + getByName("debug") { + isMinifyEnabled = false + } + } + sourceSets { + getByName("main") { + manifest.srcFile("src/androidMain/AndroidManifest.xml") + } + } + publishing { + singleVariant("release") { + withSourcesJar() + withJavadocJar() + } + } +} + +cargo { + pythonCommand = "python3" + module = "../zenoh-jni" + libname = "zenoh-jni" + targetIncludes = arrayOf("libzenoh_jni.so") + targetDirectory = "../zenoh-jni/target/" + profile = "release" + targets = arrayListOf( + "arm", + "arm64", + "x86", + "x86_64", + ) +} + +kotlin { + jvmToolchain(11) + jvm { + compilations.all { + kotlinOptions.jvmTarget = "11" + } + testRuns["test"].executionTask.configure { + val zenohPaths = "../zenoh-jni/target/release:../zenoh-jni/target/debug" + jvmArgs("-Djava.library.path=$zenohPaths") + } + } + androidTarget { + publishLibraryVariants("release") + } + + @Suppress("Unused") sourceSets { + val commonMain by getting { + dependencies { + implementation("commons-net:commons-net:3.9.0") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + } + } + val commonTest by getting { + dependencies { + implementation(kotlin("test")) + } + } + val androidUnitTest by getting { + dependencies { + implementation(kotlin("test-junit")) + } + } + val jvmMain by getting { + resources.srcDir("../zenoh-jni/target/release").include(arrayListOf("*.dylib", "*.so", "*.dll")) + } + val jvmTest by getting { + resources.srcDir("../zenoh-jni/target/debug").include(arrayListOf("*.dylib", "*.so", "*.dll")) + } + } +} + +tasks.withType { + doFirst { + buildZenohJNI(BuildMode.DEBUG) + + // The line below is added for the Android Unit tests which are equivalent to the JVM tests. + // For them to work we need to specify the path to the native library as a system property and not as a jvmArg. + systemProperty("java.library.path", "../zenoh-jni/target/debug") + } +} + +tasks.whenObjectAdded { + if ((this.name == "mergeDebugJniLibFolders" || this.name == "mergeReleaseJniLibFolders")) { + this.dependsOn("cargoBuild") + this.inputs.dir(buildDir.resolve("rustJniLibs/android")) + } +} + +tasks.named("compileKotlinJvm") { + doFirst { + buildZenohJNI(BuildMode.RELEASE) + } +} + +fun buildZenohJNI(mode: BuildMode = BuildMode.DEBUG) { + val cargoCommand = mutableListOf("cargo", "build") + + if (mode == BuildMode.RELEASE) { + cargoCommand.add("--release") + } + + val result = project.exec { + commandLine(*(cargoCommand.toTypedArray()), "--manifest-path", "../zenoh-jni/Cargo.toml") + } + + if (result.exitValue != 0) { + throw GradleException("Failed to build Zenoh-JNI.") + } } -tasks.test { - useJUnitPlatform() - val zenohPaths = "/usr/local/lib:../zenoh-jni/target/release:../zenoh-jni/target/debug" - jvmArgs("-Djava.library.path=$zenohPaths") +enum class BuildMode { + DEBUG { + override fun toString(): String { + return "debug" + } + }, + RELEASE { + override fun toString(): String { + return "release" + } + } } diff --git a/zenoh-kotlin/src/androidMain/AndroidManifest.xml b/zenoh-kotlin/src/androidMain/AndroidManifest.xml new file mode 100644 index 00000000..4fb03756 --- /dev/null +++ b/zenoh-kotlin/src/androidMain/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/Zenoh.kt b/zenoh-kotlin/src/androidMain/kotlin/io.zenoh/Zenoh.kt similarity index 95% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/Zenoh.kt rename to zenoh-kotlin/src/androidMain/kotlin/io.zenoh/Zenoh.kt index c2d32a31..dd9d3567 100644 --- a/zenoh-kotlin/src/main/kotlin/io/zenoh/Zenoh.kt +++ b/zenoh-kotlin/src/androidMain/kotlin/io.zenoh/Zenoh.kt @@ -18,7 +18,7 @@ package io.zenoh * Static singleton class to load the Zenoh native library once and only once, as well as the logger in function of the * log level configuration. */ -internal class Zenoh private constructor() { +internal actual class Zenoh private actual constructor() { companion object { private const val ZENOH_LIB_NAME = "zenoh_jni" diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/Config.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/Config.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/Config.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/Config.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/Logger.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/Logger.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/Logger.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/Logger.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/Resolvable.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/Resolvable.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/Resolvable.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/Resolvable.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/Session.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/Session.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/Session.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/Session.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/SessionDeclaration.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/SessionDeclaration.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/SessionDeclaration.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/SessionDeclaration.kt diff --git a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/Zenoh.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/Zenoh.kt new file mode 100644 index 00000000..ef6bebbc --- /dev/null +++ b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/Zenoh.kt @@ -0,0 +1,21 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +package io.zenoh + +/** + * Static singleton class to load the Zenoh native library once and only once, as well as the logger in function of the + * log level configuration. + */ +internal expect class Zenoh private constructor() diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/ZenohType.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/ZenohType.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/ZenohType.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/ZenohType.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/exceptions/JNIException.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/exceptions/JNIException.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/exceptions/JNIException.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/exceptions/JNIException.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/exceptions/KeyExprException.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/exceptions/KeyExprException.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/exceptions/KeyExprException.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/exceptions/KeyExprException.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/exceptions/SessionException.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/exceptions/SessionException.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/exceptions/SessionException.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/exceptions/SessionException.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/handlers/Callback.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/handlers/Callback.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/handlers/Callback.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/handlers/Callback.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/handlers/ChannelHandler.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/handlers/ChannelHandler.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/handlers/ChannelHandler.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/handlers/ChannelHandler.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/handlers/Handler.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/handlers/Handler.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/handlers/Handler.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/handlers/Handler.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/jni/JNIKeyExpr.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIKeyExpr.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/jni/JNIKeyExpr.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIKeyExpr.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/jni/JNIPublisher.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIPublisher.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/jni/JNIPublisher.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIPublisher.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/jni/JNIQuery.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIQuery.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/jni/JNIQuery.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIQuery.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/jni/JNIQueryable.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIQueryable.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/jni/JNIQueryable.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIQueryable.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/jni/JNISession.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNISession.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/jni/JNISession.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNISession.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/jni/JNISubscriber.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNISubscriber.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/jni/JNISubscriber.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNISubscriber.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/jni/callbacks/JNIGetCallback.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/callbacks/JNIGetCallback.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/jni/callbacks/JNIGetCallback.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/callbacks/JNIGetCallback.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/jni/callbacks/JNIQueryableCallback.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/callbacks/JNIQueryableCallback.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/jni/callbacks/JNIQueryableCallback.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/callbacks/JNIQueryableCallback.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/jni/callbacks/JNISubscriberCallback.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/callbacks/JNISubscriberCallback.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/jni/callbacks/JNISubscriberCallback.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/callbacks/JNISubscriberCallback.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/keyexpr/IntoKeyExpr.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/keyexpr/IntoKeyExpr.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/keyexpr/IntoKeyExpr.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/keyexpr/IntoKeyExpr.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/keyexpr/KeyExpr.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/keyexpr/KeyExpr.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/keyexpr/KeyExpr.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/keyexpr/KeyExpr.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/prelude/Encoding.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/prelude/Encoding.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/prelude/Encoding.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/prelude/Encoding.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/prelude/SampleKind.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/prelude/SampleKind.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/prelude/SampleKind.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/prelude/SampleKind.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/publication/CongestionControl.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/publication/CongestionControl.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/publication/CongestionControl.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/publication/CongestionControl.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/publication/Delete.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/publication/Delete.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/publication/Delete.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/publication/Delete.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/publication/Priority.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/publication/Priority.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/publication/Priority.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/publication/Priority.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/publication/Publisher.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/publication/Publisher.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/publication/Publisher.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/publication/Publisher.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/publication/Put.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/publication/Put.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/publication/Put.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/publication/Put.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/query/ConsolidationMode.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/query/ConsolidationMode.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/query/ConsolidationMode.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/query/ConsolidationMode.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/query/Get.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/query/Get.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/query/Get.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/query/Get.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/query/QueryTarget.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/query/QueryTarget.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/query/QueryTarget.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/query/QueryTarget.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/query/Reply.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/query/Reply.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/query/Reply.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/query/Reply.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/queryable/Query.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/queryable/Query.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/queryable/Query.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/queryable/Query.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/queryable/Queryable.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/queryable/Queryable.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/queryable/Queryable.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/queryable/Queryable.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/sample/Sample.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/sample/Sample.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/sample/Sample.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/sample/Sample.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/selector/IntoSelector.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/selector/IntoSelector.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/selector/IntoSelector.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/selector/IntoSelector.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/selector/Selector.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/selector/Selector.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/selector/Selector.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/selector/Selector.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/subscriber/Reliability.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/subscriber/Reliability.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/subscriber/Reliability.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/subscriber/Reliability.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/subscriber/Subscriber.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/subscriber/Subscriber.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/subscriber/Subscriber.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/subscriber/Subscriber.kt diff --git a/zenoh-kotlin/src/main/kotlin/io/zenoh/value/Value.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/value/Value.kt similarity index 100% rename from zenoh-kotlin/src/main/kotlin/io/zenoh/value/Value.kt rename to zenoh-kotlin/src/commonMain/kotlin/io/zenoh/value/Value.kt diff --git a/zenoh-kotlin/src/test/kotlin/io/zenoh/DeleteTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/DeleteTest.kt similarity index 97% rename from zenoh-kotlin/src/test/kotlin/io/zenoh/DeleteTest.kt rename to zenoh-kotlin/src/commonTest/kotlin/io/zenoh/DeleteTest.kt index b16ef692..82140552 100644 --- a/zenoh-kotlin/src/test/kotlin/io/zenoh/DeleteTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/DeleteTest.kt @@ -17,7 +17,7 @@ package io.zenoh import io.zenoh.keyexpr.intoKeyExpr import io.zenoh.prelude.SampleKind import io.zenoh.sample.Sample -import org.junit.jupiter.api.Test +import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotNull diff --git a/zenoh-kotlin/src/test/kotlin/io/zenoh/GetTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/GetTest.kt similarity index 93% rename from zenoh-kotlin/src/test/kotlin/io/zenoh/GetTest.kt rename to zenoh-kotlin/src/commonTest/kotlin/io/zenoh/GetTest.kt index 040ae5e5..7c9f2954 100644 --- a/zenoh-kotlin/src/test/kotlin/io/zenoh/GetTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/GetTest.kt @@ -27,11 +27,11 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import org.apache.commons.net.ntp.TimeStamp -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Test import java.time.Duration import java.util.* import kotlin.test.assertEquals +import kotlin.test.assertTrue +import kotlin.test.Test class GetTest { @@ -60,12 +60,11 @@ class GetTest { val sessionB = Session.open().getOrThrow() sessionB.get(keyExpr).with { reply: Reply -> - Assertions.assertTrue(reply is Reply.Success) - val receivedSample = (reply as Reply.Success).sample - Assertions.assertEquals(value, receivedSample.value) - Assertions.assertEquals(kind, receivedSample.kind) - Assertions.assertEquals(keyExpr, receivedSample.keyExpr) - Assertions.assertEquals(timeStamp, receivedSample.timestamp) + assertTrue(reply is Reply.Success) + assertEquals(value, reply.sample.value) + assertEquals(kind, reply.sample.kind) + assertEquals(keyExpr, reply.sample.keyExpr) + assertEquals(timeStamp, reply.sample.timestamp) }.timeout(Duration.ofMillis(1000)).res() Thread.sleep(1000) diff --git a/zenoh-kotlin/src/test/kotlin/io/zenoh/KeyExprTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/KeyExprTest.kt similarity index 96% rename from zenoh-kotlin/src/test/kotlin/io/zenoh/KeyExprTest.kt rename to zenoh-kotlin/src/commonTest/kotlin/io/zenoh/KeyExprTest.kt index 8855e3aa..2cb36495 100644 --- a/zenoh-kotlin/src/test/kotlin/io/zenoh/KeyExprTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/KeyExprTest.kt @@ -17,8 +17,6 @@ package io.zenoh import io.zenoh.exceptions.SessionException import io.zenoh.keyexpr.KeyExpr import io.zenoh.keyexpr.intoKeyExpr -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows import kotlin.test.* class KeyExprTest { @@ -124,7 +122,7 @@ class KeyExprTest { val keyExpr2 = "x/y/z".intoKeyExpr().getOrThrow() val undeclare2 = session.undeclare(keyExpr2).res() assertTrue(undeclare2.isFailure) - assertThrows { undeclare2.getOrThrow() } + assertTrue(undeclare2.exceptionOrNull() is SessionException) session.close() keyExpr.close() diff --git a/zenoh-kotlin/src/test/kotlin/io/zenoh/PublisherTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PublisherTest.kt similarity index 97% rename from zenoh-kotlin/src/test/kotlin/io/zenoh/PublisherTest.kt rename to zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PublisherTest.kt index 614cb136..16c6b403 100644 --- a/zenoh-kotlin/src/test/kotlin/io/zenoh/PublisherTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PublisherTest.kt @@ -20,8 +20,8 @@ import io.zenoh.prelude.Encoding import io.zenoh.prelude.SampleKind import io.zenoh.sample.Sample import io.zenoh.value.Value -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test +import kotlin.test.Test +import kotlin.test.assertEquals class PublisherTest { diff --git a/zenoh-kotlin/src/test/kotlin/io/zenoh/PutTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PutTest.kt similarity index 97% rename from zenoh-kotlin/src/test/kotlin/io/zenoh/PutTest.kt rename to zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PutTest.kt index 91fa32ec..d7dd7134 100644 --- a/zenoh-kotlin/src/test/kotlin/io/zenoh/PutTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PutTest.kt @@ -19,7 +19,7 @@ import io.zenoh.keyexpr.intoKeyExpr import io.zenoh.prelude.Encoding import io.zenoh.sample.Sample import io.zenoh.value.Value -import org.junit.jupiter.api.Test +import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotNull diff --git a/zenoh-kotlin/src/test/kotlin/io/zenoh/QueryableTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/QueryableTest.kt similarity index 94% rename from zenoh-kotlin/src/test/kotlin/io/zenoh/QueryableTest.kt rename to zenoh-kotlin/src/commonTest/kotlin/io/zenoh/QueryableTest.kt index 4e769d7e..dad943e5 100644 --- a/zenoh-kotlin/src/test/kotlin/io/zenoh/QueryableTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/QueryableTest.kt @@ -23,14 +23,14 @@ import io.zenoh.sample.Sample import io.zenoh.value.Value import kotlinx.coroutines.channels.Channel import org.apache.commons.net.ntp.TimeStamp -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test import java.time.Duration import java.time.Instant import java.util.* +import kotlin.test.Test +import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertNull +import kotlin.test.assertTrue class QueryableTest { @@ -55,8 +55,7 @@ class QueryableTest { sessionB.get(TEST_KEY_EXP).with { reply: Reply -> assertTrue(reply is Reply.Success) - val receivedSample = (reply as Reply.Success).sample - assertEquals(receivedSample, sample) + assertEquals(reply.sample, sample) }.timeout(Duration.ofMillis(1000)).res() Thread.sleep(1000) diff --git a/zenoh-kotlin/src/test/kotlin/io/zenoh/SelectorTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SelectorTest.kt similarity index 95% rename from zenoh-kotlin/src/test/kotlin/io/zenoh/SelectorTest.kt rename to zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SelectorTest.kt index 6a5d278a..0a579563 100644 --- a/zenoh-kotlin/src/test/kotlin/io/zenoh/SelectorTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SelectorTest.kt @@ -3,7 +3,7 @@ package io.zenoh import io.zenoh.exceptions.KeyExprException import io.zenoh.selector.Selector import io.zenoh.selector.intoSelector -import org.junit.jupiter.api.Test +import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith diff --git a/zenoh-kotlin/src/test/kotlin/io/zenoh/SessionTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SessionTest.kt similarity index 96% rename from zenoh-kotlin/src/test/kotlin/io/zenoh/SessionTest.kt rename to zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SessionTest.kt index 4d749b8c..f74e97c1 100644 --- a/zenoh-kotlin/src/test/kotlin/io/zenoh/SessionTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SessionTest.kt @@ -17,9 +17,7 @@ package io.zenoh import io.zenoh.exceptions.SessionException import io.zenoh.keyexpr.intoKeyExpr import io.zenoh.sample.Sample -import org.junit.jupiter.api.Assertions.* -import org.junit.jupiter.api.Test -import kotlin.test.assertFailsWith +import kotlin.test.* class SessionTest { diff --git a/zenoh-kotlin/src/test/kotlin/io/zenoh/SubscriberTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SubscriberTest.kt similarity index 97% rename from zenoh-kotlin/src/test/kotlin/io/zenoh/SubscriberTest.kt rename to zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SubscriberTest.kt index c797b4ed..7c96d4c4 100644 --- a/zenoh-kotlin/src/test/kotlin/io/zenoh/SubscriberTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SubscriberTest.kt @@ -21,9 +21,10 @@ import io.zenoh.prelude.Encoding import io.zenoh.sample.Sample import io.zenoh.value.Value import kotlinx.coroutines.channels.Channel -import org.junit.jupiter.api.Assertions.* -import org.junit.jupiter.api.Test import kotlin.collections.ArrayList +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import kotlin.test.Test class SubscriberTest { diff --git a/zenoh-kotlin/src/jvmMain/kotlin/io/zenoh/Zenoh.kt b/zenoh-kotlin/src/jvmMain/kotlin/io/zenoh/Zenoh.kt new file mode 100644 index 00000000..0515c1a6 --- /dev/null +++ b/zenoh-kotlin/src/jvmMain/kotlin/io/zenoh/Zenoh.kt @@ -0,0 +1,77 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +package io.zenoh + +import java.io.File +import java.io.FileOutputStream +import java.io.InputStream +import java.lang.Exception + +/** + * Static singleton class to load the Zenoh native library once and only once, as well as the logger in function of the + * log level configuration. + */ +internal actual class Zenoh private actual constructor() { + + companion object { + private const val ZENOH_LIB_NAME = "zenoh_jni" + private const val ZENOH_LOGS_PROPERTY = "zenoh.logger" + + private var instance: Zenoh? = null + + fun load() { + instance ?: Zenoh().also { instance = it } + } + + fun loadZenohJNI(inputStream: InputStream) { + val tempLib = File.createTempFile("tempLib", "") + tempLib.deleteOnExit() + + FileOutputStream(tempLib).use { output -> + inputStream.copyTo(output) + } + + System.load(tempLib.absolutePath) + } + } + + init { + val lib = ClassLoader.getSystemClassLoader().findLibraryStream(ZENOH_LIB_NAME) + + if (lib != null) { + loadZenohJNI(lib) + } else { + throw Exception("Unable to load ZenohJNI.") + } + + val logLevel = System.getProperty(ZENOH_LOGS_PROPERTY) + if (logLevel != null) { + Logger.start(logLevel) + } + } +} + +private fun ClassLoader.findLibraryStream(libraryName: String): InputStream? { + // TODO: look after targets of multiple architectures + val libraryExtensions = listOf(".dylib", ".so", ".dll") + for (extension in libraryExtensions) { + val resourcePath = "lib$libraryName$extension" + val inputStream = getResourceAsStream(resourcePath) + if (inputStream != null) { + return inputStream + } + } + return null +}