├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ ├── feature_request.yml │ └── release.yml ├── release.yml └── workflows │ ├── check-labels.yml │ ├── ci.yml │ ├── publish-android.yml │ ├── publish-dokka.yml │ ├── publish-jvm.yml │ ├── release.yml │ └── update-release-project.yml ├── .gitignore ├── .markdownlint.yaml ├── CONTRIBUTING.md ├── CONTRIBUTORS.md ├── LICENSE ├── NOTICE.md ├── README.md ├── android-robot.png ├── build.gradle.kts ├── ci └── scripts │ └── bump-and-tag.bash ├── doc_icon.png ├── examples ├── README.md ├── build.gradle.kts └── src │ └── main │ └── java │ └── io │ └── zenoh │ ├── Config.kt │ ├── QueueHandler.java │ ├── ZBytesExamples.java │ ├── ZDelete.java │ ├── ZGet.java │ ├── ZGetLiveliness.java │ ├── ZInfo.java │ ├── ZLiveliness.java │ ├── ZPing.java │ ├── ZPong.java │ ├── ZPub.java │ ├── ZPubThr.java │ ├── ZPut.java │ ├── ZQuerier.java │ ├── ZQueryable.java │ ├── ZScout.java │ ├── ZSub.java │ ├── ZSubLiveliness.java │ └── ZSubThr.java ├── gradle.properties ├── jvm.png ├── rust-toolchain.toml ├── settings.gradle.kts ├── version.txt ├── zenoh-dragon.png ├── zenoh-java ├── build.gradle.kts └── src │ ├── androidMain │ ├── AndroidManifest.xml │ └── kotlin │ │ └── io.zenoh │ │ └── Zenoh.kt │ ├── commonMain │ └── kotlin │ │ └── io │ │ └── zenoh │ │ ├── Config.kt │ │ ├── Logger.kt │ │ ├── Session.kt │ │ ├── Zenoh.kt │ │ ├── ZenohType.kt │ │ ├── annotations │ │ └── Annotations.kt │ │ ├── bytes │ │ ├── Encoding.kt │ │ ├── IntoZBytes.kt │ │ └── ZBytes.kt │ │ ├── config │ │ ├── WhatAmI.kt │ │ └── ZenohId.kt │ │ ├── exceptions │ │ └── ZError.kt │ │ ├── ext │ │ ├── ZDeserializer.kt │ │ └── ZSerializer.kt │ │ ├── handlers │ │ ├── BlockingQueueHandler.kt │ │ ├── Callback.kt │ │ └── Handler.kt │ │ ├── jni │ │ ├── JNIConfig.kt │ │ ├── JNIKeyExpr.kt │ │ ├── JNILiveliness.kt │ │ ├── JNILivelinessToken.kt │ │ ├── JNIPublisher.kt │ │ ├── JNIQuerier.kt │ │ ├── JNIQuery.kt │ │ ├── JNIQueryable.kt │ │ ├── JNIScout.kt │ │ ├── JNISession.kt │ │ ├── JNISubscriber.kt │ │ ├── JNIZBytes.kt │ │ ├── JNIZenohId.kt │ │ └── callbacks │ │ │ ├── JNIGetCallback.kt │ │ │ ├── JNIOnCloseCallback.kt │ │ │ ├── JNIQueryableCallback.kt │ │ │ ├── JNIScoutCallback.kt │ │ │ └── JNISubscriberCallback.kt │ │ ├── keyexpr │ │ ├── KeyExpr.kt │ │ └── SetIntersectionLevel.kt │ │ ├── liveliness │ │ ├── Liveliness.kt │ │ └── LivelinessToken.kt │ │ ├── pubsub │ │ ├── DeleteOptions.kt │ │ ├── Publisher.kt │ │ ├── PublisherOptions.kt │ │ ├── PutOptions.kt │ │ └── Subscriber.kt │ │ ├── qos │ │ ├── CongestionControl.kt │ │ ├── Priority.kt │ │ ├── QoS.kt │ │ └── Reliability.kt │ │ ├── query │ │ ├── ConsolidationMode.kt │ │ ├── Get.kt │ │ ├── Parameters.kt │ │ ├── Querier.kt │ │ ├── Query.kt │ │ ├── QueryTarget.kt │ │ ├── Queryable.kt │ │ ├── Reply.kt │ │ └── Selector.kt │ │ ├── sample │ │ ├── Sample.kt │ │ └── SampleKind.kt │ │ ├── scouting │ │ ├── Hello.kt │ │ ├── Scout.kt │ │ └── ScoutOptions.kt │ │ └── session │ │ ├── SessionDeclaration.kt │ │ └── SessionInfo.kt │ ├── jvmMain │ └── kotlin │ │ └── io │ │ └── zenoh │ │ ├── Target.kt │ │ └── Zenoh.kt │ └── jvmTest │ └── java │ └── io │ └── zenoh │ ├── ConfigTest.java │ ├── DeleteTest.java │ ├── EncodingTest.java │ ├── GetTest.java │ ├── KeyExprTest.java │ ├── LivelinessTest.java │ ├── ParametersTest.java │ ├── PublisherTest.java │ ├── PutTest.java │ ├── QuerierTest.java │ ├── QueryableTest.java │ ├── ScoutTest.java │ ├── SelectorTest.java │ ├── SessionInfoTest.java │ ├── SessionTest.java │ ├── SubscriberTest.java │ ├── UserAttachmentTest.java │ └── ZBytesTests.java └── zenoh-jni ├── Cargo.lock ├── Cargo.toml └── src ├── config.rs ├── errors.rs ├── key_expr.rs ├── lib.rs ├── liveliness.rs ├── logger.rs ├── publisher.rs ├── querier.rs ├── query.rs ├── queryable.rs ├── scouting.rs ├── session.rs ├── subscriber.rs ├── utils.rs ├── zbytes.rs └── zenoh_id.rs /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Report a bug 2 | description: | 3 | Create a bug report to help us improve Zenoh. 4 | title: "[Bug] " 5 | labels: ["bug"] 6 | body: 7 | - type: textarea 8 | id: summary 9 | attributes: 10 | label: "Describe the bug" 11 | description: | 12 | A clear and concise description of the expected behaviour and what the bug is. 13 | placeholder: | 14 | E.g. zenoh peers can not automatically establish a connection. 15 | validations: 16 | required: true 17 | - type: textarea 18 | id: reproduce 19 | attributes: 20 | label: To reproduce 21 | description: "Steps to reproduce the behavior:" 22 | placeholder: | 23 | 1. Start a subscriber "..." 24 | 2. Start a publisher "...." 25 | 3. See error 26 | validations: 27 | required: true 28 | - type: textarea 29 | id: system 30 | attributes: 31 | label: System info 32 | description: "Please complete the following information:" 33 | placeholder: | 34 | - Platform: [e.g. Ubuntu 20.04 64-bit] 35 | - CPU [e.g. AMD Ryzen 3800X] 36 | - Zenoh version/commit [e.g. 6f172ea985d42d20d423a192a2d0d46bb0ce0d11] 37 | validations: 38 | required: true 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Ask a question 4 | url: https://github.com/eclipse-zenoh/roadmap/discussions/categories/zenoh 5 | about: Open to the Zenoh community. Share your feedback with the Zenoh team. 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Request a feature 2 | description: | 3 | Suggest a new feature specific to this repository. NOTE: for generic Zenoh ideas use "Ask a question". 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | **Guidelines for a good issue** 9 | 10 | *Is your feature request related to a problem?* 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | *Describe the solution you'd like* 14 | A clear and concise description of what you want to happen. 15 | 16 | *Describe alternatives you've considered* 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | *Additional context* 20 | Add any other context about the feature request here. 21 | - type: textarea 22 | id: feature 23 | attributes: 24 | label: "Describe the feature" 25 | validations: 26 | required: true 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/release.yml: -------------------------------------------------------------------------------- 1 | name: Add an issue to the next release 2 | description: | 3 | Add an issue as part of next release. 4 | This will be added to the current release project. 5 | You must be a contributor to use this template. 6 | labels: ["release"] 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | **Guidelines for a good issue** 12 | 13 | *Is your release item related to a problem?* 14 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 15 | 16 | *Describe the solution you'd like* 17 | A clear and concise description of what you want to happen. 18 | 19 | *Describe alternatives you've considered* 20 | A clear and concise description of any alternative solutions or features you've considered. 21 | 22 | *Additional context* 23 | Add any other context about the release item request here. 24 | - type: textarea 25 | id: item 26 | attributes: 27 | label: "Describe the release item" 28 | validations: 29 | required: true 30 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2023 ZettaScale Technology 3 | # 4 | # This program and the accompanying materials are made available under the 5 | # terms of the Eclipse Public License 2.0 which is available at 6 | # http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | # which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | # 9 | # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | # 11 | # Contributors: 12 | # ZettaScale Zenoh Team, 13 | # 14 | 15 | changelog: 16 | categories: 17 | - title: Breaking changes 💥 18 | labels: 19 | - breaking-change 20 | - title: New features 🎉 21 | labels: 22 | - enhancement 23 | - new feature 24 | exclude: 25 | labels: 26 | - internal 27 | - title: Bug fixes 🐞 28 | labels: 29 | - bug 30 | exclude: 31 | labels: 32 | - internal 33 | - title: Documentation 📝 34 | labels: 35 | - documentation 36 | exclude: 37 | labels: 38 | - internal 39 | - title: Dependencies 👷 40 | labels: 41 | - dependencies 42 | exclude: 43 | labels: 44 | - internal 45 | - title: Other changes 46 | labels: 47 | - "*" 48 | exclude: 49 | labels: 50 | - internal -------------------------------------------------------------------------------- /.github/workflows/check-labels.yml: -------------------------------------------------------------------------------- 1 | name: Check required labels 2 | 3 | on: 4 | pull_request_target: 5 | types: [opened, synchronize, reopened, labeled] 6 | branches: ["**"] 7 | 8 | jobs: 9 | check-labels: 10 | name: Check PR labels 11 | uses: eclipse-zenoh/ci/.github/workflows/check-labels.yml@main 12 | secrets: 13 | github-token: ${{ secrets.GITHUB_TOKEN }} 14 | permissions: 15 | pull-requests: write 16 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: ["**"] 6 | pull_request: 7 | branches: ["**"] 8 | schedule: 9 | - cron: "0 6 * * 1-5" 10 | workflow_dispatch: 11 | 12 | env: 13 | CARGO_TERM_COLOR: always 14 | 15 | jobs: 16 | build: 17 | name: Build on ${{ matrix.os }} 18 | runs-on: ["${{ matrix.os }}"] 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | os: [ubuntu-latest, macos-latest] 23 | 24 | steps: 25 | - uses: actions/checkout@v4 26 | 27 | - uses: actions/setup-java@v4 28 | with: 29 | distribution: temurin 30 | java-version: 11 31 | 32 | - name: Install Rust toolchain 33 | run: | 34 | rustup show 35 | rustup component add rustfmt clippy 36 | 37 | - name: Cargo Format 38 | working-directory: zenoh-jni 39 | run: cargo fmt --all --check 40 | 41 | - name: Clippy Check 42 | working-directory: zenoh-jni 43 | run: cargo clippy --all-targets --all-features -- -D warnings 44 | 45 | - name: Check for feature leaks 46 | working-directory: zenoh-jni 47 | run: cargo test --no-default-features 48 | 49 | - name: Build Zenoh-JNI 50 | working-directory: zenoh-jni 51 | run: cargo build 52 | 53 | - name: Setup Gradle 54 | uses: gradle/actions/setup-gradle@v4 55 | with: 56 | gradle-version: 8.12.1 57 | 58 | - name: Gradle Test 59 | run: gradle jvmTest --info 60 | 61 | markdown_lint: 62 | runs-on: ubuntu-latest 63 | steps: 64 | - uses: actions/checkout@v4 65 | - uses: DavidAnson/markdownlint-cli2-action@v18 66 | with: 67 | config: '.markdownlint.yaml' 68 | globs: '**/README.md' 69 | 70 | check_rust: 71 | name: Check zenoh-java using Rust 1.75 72 | runs-on: ubuntu-latest 73 | strategy: 74 | fail-fast: false 75 | steps: 76 | - name: Clone this repository 77 | uses: actions/checkout@v4 78 | 79 | - name: Update Rust 1.75.0 toolchain 80 | run: rustup update 1.75.0 81 | 82 | - name: Setup rust-cache 83 | uses: Swatinem/rust-cache@v2 84 | with: 85 | cache-bin: false 86 | 87 | - name: Check zenoh-java with rust 1.75.0 88 | run: | 89 | cd zenoh-jni 90 | cargo +1.75.0 check --release --bins --lib 91 | 92 | # NOTE: In GitHub repository settings, the "Require status checks to pass 93 | # before merging" branch protection rule ensures that commits are only merged 94 | # from branches where specific status checks have passed. These checks are 95 | # specified manually as a list of workflow job names. Thus we use this extra 96 | # job to signal whether all CI checks have passed. 97 | ci: 98 | name: CI status checks 99 | runs-on: ubuntu-latest 100 | needs: [check_rust, build, markdown_lint] 101 | if: always() 102 | steps: 103 | - name: Check whether all jobs pass 104 | run: echo '${{ toJson(needs) }}' | jq -e 'all(.result == "success")' 105 | 106 | # Publish snapshot packages. These jobs will only be triggered when the CI is executed on main. 107 | publish_jvm_snapshot_package: 108 | name: Publish JVM snapshot package 109 | if: contains(fromJSON('["refs/heads/main"]'), github.ref) 110 | needs: ci 111 | uses: ./.github/workflows/publish-jvm.yml 112 | permissions: 113 | contents: read 114 | packages: write 115 | with: 116 | snapshot: true 117 | branch: ${{ github.ref_name }} 118 | secrets: inherit 119 | 120 | publish_android_snapshot_package: 121 | name: Publish Android snapshot package 122 | if: contains(fromJSON('["refs/heads/main"]'), github.ref) 123 | needs: ci 124 | uses: ./.github/workflows/publish-android.yml 125 | permissions: 126 | contents: read 127 | packages: write 128 | with: 129 | snapshot: true 130 | branch: ${{ github.ref_name }} 131 | secrets: inherit 132 | -------------------------------------------------------------------------------- /.github/workflows/publish-android.yml: -------------------------------------------------------------------------------- 1 | name: Publish (Android) 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | snapshot: 7 | required: true 8 | type: boolean 9 | description: "If the publication is for a snapshot version." 10 | default: false 11 | branch: 12 | description: Target branch 13 | type: string 14 | required: false 15 | maven_publish: 16 | type: boolean 17 | required: false 18 | default: true 19 | 20 | env: 21 | CARGO_TERM_COLOR: always 22 | 23 | jobs: 24 | publish_android_package: 25 | name: Publish Android package 26 | runs-on: ubuntu-latest 27 | permissions: 28 | contents: read 29 | packages: write 30 | steps: 31 | - uses: actions/checkout@v4 32 | with: 33 | ref: ${{ inputs.branch }} 34 | 35 | - uses: actions/setup-java@v4 36 | with: 37 | distribution: temurin 38 | java-version: 11 39 | 40 | - uses: nttld/setup-ndk@v1 41 | id: setup-ndk 42 | with: 43 | ndk-version: r26 44 | add-to-path: false 45 | link-to-sdk: true 46 | 47 | - name: Install Rust toolchain 48 | run: | 49 | rustup show 50 | rustup component add rustfmt clippy 51 | 52 | - name: Setup Rust toolchains 53 | run: | 54 | rustup target add armv7-linux-androideabi 55 | rustup target add i686-linux-android 56 | rustup target add aarch64-linux-android 57 | rustup target add x86_64-linux-android 58 | 59 | - name: Setup Gradle 60 | uses: gradle/actions/setup-gradle@v4 61 | with: 62 | gradle-version: 8.12.1 63 | 64 | - name: Gradle Wrapper 65 | run: | 66 | gradle wrapper 67 | 68 | - name: Set pub mode env var 69 | # Note: This step is intended to allow publishing snapshot packages. 70 | # It allows to optionally append the property -PSNAPSHOT to the gradle 71 | # publication task on the next step, resulting in the package version 72 | # following the convention '-SNAPSHOT'. 73 | run: | 74 | if [[ "${{ inputs.snapshot }}" == "true" ]]; then 75 | echo "PUB_MODE=-PSNAPSHOT" >> $GITHUB_ENV 76 | else 77 | echo "RELEASE=closeAndReleaseSonatypeStagingRepository" >> $GITHUB_ENV 78 | fi 79 | 80 | - if: ${{ inputs.maven_publish == true }} 81 | name: Gradle Publish Android Package to Maven Central repository 82 | run: | 83 | ./gradlew publishAndroidReleasePublicationToSonatypeRepository ${{ env.RELEASE }} --info -PremotePublication=true -Pandroid=true ${{ env.PUB_MODE }} 84 | env: 85 | ORG_OSSRH_USERNAME: ${{ secrets.ORG_OSSRH_USERNAME }} 86 | ORG_OSSRH_PASSWORD: ${{ secrets.ORG_OSSRH_PASSWORD }} 87 | ORG_GPG_KEY_ID: ${{ secrets.ORG_GPG_KEY_ID }} 88 | ORG_GPG_SUBKEY_ID: ${{ secrets.ORG_GPG_SUBKEY_ID }} 89 | ORG_GPG_PRIVATE_KEY: ${{ secrets.ORG_GPG_PRIVATE_KEY }} 90 | ORG_GPG_PASSPHRASE: ${{ secrets.ORG_GPG_PASSPHRASE }} 91 | 92 | - name: "Upload gradle problems report" 93 | if: always() 94 | uses: actions/upload-artifact@v4 95 | with: 96 | name: problem-reports-${{ github.job }}.zip 97 | path: ${{ github.workspace }}/build/reports/problems/ 98 | -------------------------------------------------------------------------------- /.github/workflows/publish-dokka.yml: -------------------------------------------------------------------------------- 1 | name: Publish (Dokka) 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | live-run: 7 | description: Live-run 8 | type: boolean 9 | required: true 10 | branch: 11 | description: Target branch 12 | type: string 13 | required: false 14 | workflow_dispatch: 15 | 16 | env: 17 | CARGO_TERM_COLOR: always 18 | 19 | jobs: 20 | build_doc_and_deploy: 21 | name: Build and Deploy Documentation 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: actions/checkout@v4 25 | with: 26 | ref: ${{ inputs.branch }} 27 | 28 | - name: Build doc 29 | run: gradle dokkaGenerate 30 | 31 | - name: Deploy doc 32 | if: ${{ inputs.live-run || false }} 33 | uses: peaceiris/actions-gh-pages@v3 34 | with: 35 | github_token: ${{ secrets.GITHUB_TOKEN }} 36 | publish_dir: ./zenoh-java/build/dokka/javadoc 37 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 ZettaScale Technology 3 | # 4 | # This program and the accompanying materials are made available under the 5 | # terms of the Eclipse Public License 2.0 which is available at 6 | # http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | # which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | # 9 | # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | # 11 | # Contributors: 12 | # ZettaScale Zenoh Team, 13 | # 14 | name: Release 15 | 16 | on: 17 | schedule: 18 | - cron: "0 0 * * 1-5" 19 | workflow_dispatch: 20 | inputs: 21 | live-run: 22 | type: boolean 23 | description: Live-run 24 | required: false 25 | version: 26 | type: string 27 | description: Release number 28 | required: false 29 | zenoh-version: 30 | type: string 31 | description: Release number of Zenoh 32 | required: false 33 | branch: 34 | type: string 35 | description: Release branch 36 | required: false 37 | maven_publish: 38 | type: boolean 39 | description: Publish the package to Maven Central 40 | required: false 41 | default: true 42 | 43 | jobs: 44 | tag: 45 | name: Branch, Bump & tag 46 | runs-on: ubuntu-latest 47 | outputs: 48 | version: ${{ steps.create-release-branch.outputs.version }} 49 | branch: ${{ steps.create-release-branch.outputs.branch }} 50 | steps: 51 | - id: create-release-branch 52 | uses: eclipse-zenoh/ci/create-release-branch@main 53 | with: 54 | repo: ${{ github.repository }} 55 | live-run: ${{ inputs.live-run || false }} 56 | version: ${{ inputs.version }} 57 | branch: ${{ inputs.branch }} 58 | github-token: ${{ secrets.BOT_TOKEN_WORKFLOW }} 59 | 60 | - name: Checkout this repository 61 | uses: actions/checkout@v4 62 | with: 63 | ref: ${{ steps.create-release-branch.outputs.branch }} 64 | 65 | - name: Bump and tag project 66 | run: bash ci/scripts/bump-and-tag.bash 67 | env: 68 | LIVE_RUN: ${{ inputs.live-run || false }} 69 | VERSION: ${{ steps.create-release-branch.outputs.version }} 70 | BUMP_DEPS_VERSION: ${{ inputs.zenoh-version }} 71 | BUMP_DEPS_PATTERN: ${{ inputs.zenoh-version && 'zenoh.*' || '' }} 72 | BUMP_DEPS_BRANCH: ${{ inputs.zenoh-version && format('release/{0}', inputs.zenoh-version) || '' }} 73 | GIT_USER_NAME: eclipse-zenoh-bot 74 | GIT_USER_EMAIL: eclipse-zenoh-bot@users.noreply.github.com 75 | 76 | publish-jvm: 77 | name: Publish JVM package 78 | needs: tag 79 | uses: ./.github/workflows/publish-jvm.yml 80 | with: 81 | snapshot: ${{ !(inputs.live-run || false) }} 82 | branch: ${{ needs.tag.outputs.branch }} 83 | maven_publish: ${{ !contains(inputs.maven_publish, 'false') }} 84 | permissions: 85 | contents: read 86 | packages: write 87 | secrets: inherit 88 | 89 | publish-android: 90 | name: Publish Android package 91 | needs: tag 92 | uses: ./.github/workflows/publish-android.yml 93 | with: 94 | snapshot: ${{ !(inputs.live-run || false) }} 95 | branch: ${{ needs.tag.outputs.branch }} 96 | maven_publish: ${{ !contains(inputs.maven_publish, 'false') }} 97 | permissions: 98 | contents: read 99 | packages: write 100 | secrets: inherit 101 | 102 | publish-dokka: 103 | name: Publish documentation 104 | needs: [tag, publish-android, publish-jvm] 105 | uses: ./.github/workflows/publish-dokka.yml 106 | with: 107 | live-run: ${{ inputs.live-run || false }} 108 | branch: ${{ needs.tag.outputs.branch }} 109 | 110 | publish-github: 111 | needs: [tag, publish-android, publish-jvm] 112 | runs-on: macos-latest 113 | steps: 114 | - uses: eclipse-zenoh/ci/publish-crates-github@main 115 | with: 116 | repo: ${{ github.repository }} 117 | live-run: ${{ inputs.live-run || false }} 118 | version: ${{ needs.tag.outputs.version }} 119 | branch: ${{ needs.tag.outputs.branch }} 120 | github-token: ${{ secrets.BOT_TOKEN_WORKFLOW }} 121 | -------------------------------------------------------------------------------- /.github/workflows/update-release-project.yml: -------------------------------------------------------------------------------- 1 | name: Update release project 2 | 3 | on: 4 | issues: 5 | types: [opened, edited, labeled] 6 | pull_request_target: 7 | types: [closed] 8 | branches: 9 | - main 10 | 11 | jobs: 12 | main: 13 | uses: eclipse-zenoh/zenoh/.github/workflows/update-release-project.yml@main 14 | secrets: inherit 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | **/target 4 | 5 | # These are backup files generated by rustfmt 6 | **/*.rs.bk 7 | 8 | # VSCode projet direcctory 9 | .vscode 10 | 11 | # CLion projet directory 12 | .idea 13 | 14 | # Emacs temps 15 | *~ 16 | 17 | # MacOS Related 18 | .DS_Store 19 | /examples/build/ 20 | /build/ 21 | /.gradle/ 22 | */build/ 23 | -------------------------------------------------------------------------------- /.markdownlint.yaml: -------------------------------------------------------------------------------- 1 | { 2 | "MD013": false, # Line length limitation 3 | "MD024": false, # Allow multiple headings with the same content 4 | "MD033": false, # Enable Inline HTML 5 | "MD041": false, # Allow first line heading 6 | "MD045": false, # Allow Images have no alternate text 7 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Eclipse zenoh 2 | 3 | Thanks for your interest in this project. 4 | 5 | ## Project description 6 | 7 | Eclipse zenoh provides is a stack designed to 8 | 1. minimize network overhead, 9 | 2. support extremely constrained devices, 10 | 3. supports devices with low duty-cycle by allowing the negotiation of data exchange modes and schedules, 11 | 4. provide a rich set of abstraction for distributing, querying and storing data along the entire system, and 12 | 5. provide extremely low latency and high throughput. 13 | 14 | * https://projects.eclipse.org/projects/iot.zenoh 15 | 16 | ## Developer resources 17 | 18 | Information regarding source code management, builds, coding standards, and 19 | more. 20 | 21 | * https://projects.eclipse.org/projects/iot.zenoh/developer 22 | 23 | The project maintains the following source code repositories 24 | 25 | * https://github.com/eclipse-zenoh 26 | 27 | ## Eclipse Contributor Agreement 28 | 29 | Before your contribution can be accepted by the project team contributors must 30 | electronically sign the Eclipse Contributor Agreement (ECA). 31 | 32 | * http://www.eclipse.org/legal/ECA.php 33 | 34 | Commits that are provided by non-committers must have a Signed-off-by field in 35 | the footer indicating that the author is aware of the terms by which the 36 | contribution has been provided to the project. The non-committer must 37 | additionally have an Eclipse Foundation account and must have a signed Eclipse 38 | Contributor Agreement (ECA) on file. 39 | 40 | For more information, please see the Eclipse Committer Handbook: 41 | https://www.eclipse.org/projects/handbook/#resources-commit 42 | 43 | ## Contact 44 | 45 | Contact the project developers via the project's "dev" list. 46 | 47 | * https://accounts.eclipse.org/mailing-list/zenoh-dev 48 | 49 | Or via the Discord server. 50 | 51 | * https://discord.gg/vSDSpqnbkm 52 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | # Contributors to Eclipse zenoh 2 | 3 | These are the contributors to Eclipse zenoh (the initial contributors and the contributors listed in the Git log). 4 | 5 | 6 | | GitHub username | Name | 7 | | --------------- | -----------------------------| 8 | | DariusIMP | Darius Maitia (ZettaScale) | 9 | | JEnoch | Julien Enoch (ZettaScale) | 10 | -------------------------------------------------------------------------------- /NOTICE.md: -------------------------------------------------------------------------------- 1 | # Notices for Eclipse zenoh 2 | 3 | This content is produced and maintained by the Eclipse zenoh project. 4 | 5 | * Project home: https://projects.eclipse.org/projects/iot.zenoh 6 | 7 | ## Trademarks 8 | 9 | Eclipse zenoh is trademark of the Eclipse Foundation. 10 | Eclipse, and the Eclipse Logo are registered trademarks of the Eclipse Foundation. 11 | 12 | ## Copyright 13 | 14 | All content is the property of the respective authors or their employers. 15 | For more information regarding authorship of content, please consult the 16 | listed source code repository logs. 17 | 18 | ## Declared Project Licenses 19 | 20 | This program and the accompanying materials are made available under the 21 | terms of the Eclipse Public License 2.0 which is available at 22 | http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 23 | which is available at https://www.apache.org/licenses/LICENSE-2.0. 24 | 25 | SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 26 | 27 | ## Source Code 28 | 29 | The project maintains the following source code repositories: 30 | 31 | * https://github.com/eclipse-zenoh/zenoh.git 32 | * https://github.com/eclipse-zenoh/zenoh-c.git 33 | * https://github.com/eclipse-zenoh/zenoh-java.git 34 | * https://github.com/eclipse-zenoh/zenoh-go.git 35 | * https://github.com/eclipse-zenoh/zenoh-python.git 36 | 37 | ## Third-party Content 38 | 39 | *To be completed...* 40 | 41 | -------------------------------------------------------------------------------- /android-robot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-zenoh/zenoh-java/0345b1c689db0aa2947c720606b43396da328fc8/android-robot.png -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | buildscript { 16 | repositories { 17 | google() 18 | } 19 | dependencies { 20 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0") 21 | classpath("org.mozilla.rust-android-gradle:plugin:0.9.6") 22 | classpath("com.android.tools.build:gradle:7.4.2") 23 | classpath("com.gradleup.shadow:shadow-gradle-plugin:9.0.0-beta6") 24 | } 25 | } 26 | 27 | plugins { 28 | id("com.android.library") version "7.4.2" apply false 29 | id("org.jetbrains.kotlin.android") version "1.9.10" apply false 30 | id("org.jetbrains.kotlin.multiplatform") version "1.9.0" apply false 31 | id("org.mozilla.rust-android-gradle.rust-android") version "0.9.6" apply false 32 | id("org.jetbrains.dokka-javadoc") version "2.0.0" apply false 33 | id("com.adarshr.test-logger") version "3.2.0" apply false 34 | kotlin("plugin.serialization") version "1.9.0" apply false 35 | id("io.github.gradle-nexus.publish-plugin") version "2.0.0" 36 | } 37 | 38 | group = "org.eclipse.zenoh" 39 | 40 | val baseVersion = file("version.txt").readText().trim() 41 | version = if (project.hasProperty("SNAPSHOT")) { 42 | "$baseVersion-SNAPSHOT" 43 | } else { 44 | baseVersion 45 | } 46 | 47 | nexusPublishing { 48 | repositories { 49 | sonatype { 50 | nexusUrl = uri("https://oss.sonatype.org/service/local/") 51 | snapshotRepositoryUrl = uri("https://oss.sonatype.org/content/repositories/snapshots/") 52 | 53 | username = System.getenv("ORG_OSSRH_USERNAME") 54 | password = System.getenv("ORG_OSSRH_PASSWORD") 55 | } 56 | } 57 | } 58 | 59 | subprojects { 60 | repositories { 61 | google() 62 | mavenCentral() 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ci/scripts/bump-and-tag.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -xeo pipefail 4 | 5 | readonly live_run=${LIVE_RUN:-false} 6 | # Release number 7 | readonly version=${VERSION:?input VERSION is required} 8 | # Dependencies' pattern 9 | readonly bump_deps_pattern=${BUMP_DEPS_PATTERN:-''} 10 | # Dependencies' version 11 | readonly bump_deps_version=${BUMP_DEPS_VERSION:-''} 12 | # Dependencies' git branch 13 | readonly bump_deps_branch=${BUMP_DEPS_BRANCH:-''} 14 | # Git actor name 15 | readonly git_user_name=${GIT_USER_NAME:?input GIT_USER_NAME is required} 16 | # Git actor email 17 | readonly git_user_email=${GIT_USER_EMAIL:?input GIT_USER_EMAIL is required} 18 | 19 | cargo +stable install toml-cli 20 | 21 | # NOTE(fuzzypixelz): toml-cli doesn't yet support in-place modification 22 | # See: https://github.com/gnprice/toml-cli?tab=readme-ov-file#writing-ish-toml-set 23 | function toml_set_in_place() { 24 | local tmp=$(mktemp) 25 | toml set "$1" "$2" "$3" > "$tmp" 26 | mv "$tmp" "$1" 27 | } 28 | 29 | export GIT_AUTHOR_NAME=$git_user_name 30 | export GIT_AUTHOR_EMAIL=$git_user_email 31 | export GIT_COMMITTER_NAME=$git_user_name 32 | export GIT_COMMITTER_EMAIL=$git_user_email 33 | 34 | # Bump Gradle project version 35 | printf '%s' "$version" > version.txt 36 | # Propagate version change to zenoh-jni 37 | toml_set_in_place zenoh-jni/Cargo.toml "package.version" "$version" 38 | 39 | git commit version.txt zenoh-jni/Cargo.toml -m "chore: Bump version to \`$version\`" 40 | 41 | # Select all package dependencies that match $bump_deps_pattern and bump them to $bump_deps_version 42 | if [[ "$bump_deps_pattern" != '' ]]; then 43 | deps=$(toml get zenoh-jni/Cargo.toml dependencies | jq -r "keys[] | select(test(\"$bump_deps_pattern\"))") 44 | for dep in $deps; do 45 | if [[ -n $bump_deps_version ]]; then 46 | toml_set_in_place zenoh-jni/Cargo.toml "dependencies.$dep.version" "$bump_deps_version" 47 | fi 48 | 49 | if [[ -n $bump_deps_branch ]]; then 50 | toml_set_in_place zenoh-jni/Cargo.toml "dependencies.$dep.branch" "$bump_deps_branch" 51 | fi 52 | done 53 | # Update lockfile 54 | cargo check --manifest-path zenoh-jni/Cargo.toml 55 | 56 | if [[ -n $bump_deps_version || -n $bump_deps_branch ]]; then 57 | git commit zenoh-jni/Cargo.toml zenoh-jni/Cargo.lock -m "chore: Bump \`$bump_deps_pattern\` dependencies to \`$bump_deps_version\`" 58 | else 59 | echo "warn: no changes have been made to any dependencies matching $bump_deps_pattern" 60 | fi 61 | fi 62 | 63 | if [[ ${live_run} ]]; then 64 | git tag --force "$version" -m "v$version" 65 | fi 66 | git log -10 67 | git show-ref --tags 68 | git push origin 69 | git push --force origin "$version" 70 | -------------------------------------------------------------------------------- /doc_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-zenoh/zenoh-java/0345b1c689db0aa2947c720606b43396da328fc8/doc_icon.png -------------------------------------------------------------------------------- /examples/build.gradle.kts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar 16 | 17 | plugins { 18 | kotlin("jvm") 19 | kotlin("plugin.serialization") version "1.9.0" 20 | id("com.gradleup.shadow") 21 | } 22 | 23 | kotlin { 24 | jvmToolchain(11) 25 | } 26 | 27 | dependencies { 28 | implementation(project(":zenoh-java")) 29 | implementation("commons-net:commons-net:3.9.0") 30 | implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0") 31 | implementation("info.picocli:picocli:4.7.4") 32 | implementation("com.google.guava:guava:33.3.1-jre") 33 | } 34 | 35 | tasks { 36 | val examples = listOf( 37 | "ZBytesExamples", 38 | "ZDelete", 39 | "ZGet", 40 | "ZGetLiveliness", 41 | "ZInfo", 42 | "ZLiveliness", 43 | "ZPing", 44 | "ZPong", 45 | "ZPub", 46 | "ZPubThr", 47 | "ZPut", 48 | "ZQuerier", 49 | "ZQueryable", 50 | "ZScout", 51 | "ZSub", 52 | "ZSubLiveliness", 53 | "ZSubThr" 54 | ) 55 | 56 | examples.forEach { example -> 57 | register("${example}Jar") { 58 | group = "build" 59 | description = "Build a fat JAR for the $example example" 60 | from(sourceSets["main"].output) 61 | manifest { 62 | attributes["Main-Class"] = "io.zenoh.${example}" 63 | } 64 | configurations.empty() 65 | configurations.add(project.configurations.getByName("runtimeClasspath")) 66 | 67 | archiveBaseName.set(example) 68 | archiveVersion.set("") 69 | archiveClassifier.set("") 70 | } 71 | } 72 | 73 | register("buildExamples") { 74 | group = "build" 75 | description = "Build all fat JARs for the Zenoh Java examples" 76 | dependsOn(examples.map { "${it}Jar" }) 77 | } 78 | 79 | examples.forEach { example -> 80 | register(example, JavaExec::class) { 81 | dependsOn("CompileZenohJNI") 82 | description = "Run the $example example" 83 | mainClass.set("io.zenoh.$example") 84 | classpath(sourceSets["main"].runtimeClasspath) 85 | val zenohPaths = "../zenoh-jni/target/release" 86 | val defaultJvmArgs = arrayListOf("-Djava.library.path=$zenohPaths") 87 | jvmArgs(defaultJvmArgs) 88 | } 89 | } 90 | } 91 | 92 | tasks.register("CompileZenohJNI") { 93 | project.exec { 94 | commandLine("cargo", "build", "--release", "--manifest-path", "../zenoh-jni/Cargo.toml") 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /examples/src/main/java/io/zenoh/Config.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh 16 | 17 | import kotlinx.serialization.Serializable 18 | import kotlinx.serialization.SerialName 19 | import kotlinx.serialization.json.Json 20 | import kotlinx.serialization.json.encodeToJsonElement 21 | import kotlin.io.path.Path 22 | 23 | @Serializable 24 | data class ConfigData( 25 | @SerialName("connect") var connect: Connect? = null, 26 | @SerialName("listen") var listen: Listen? = null, 27 | @SerialName("mode") var mode: String? = null, 28 | @SerialName("scouting") var scouting: Scouting? = null, 29 | ) 30 | 31 | @Serializable 32 | data class Connect( 33 | @SerialName("endpoints") var endpoints: List 34 | ) 35 | 36 | @Serializable 37 | data class Listen( 38 | @SerialName("endpoints") var endpoints: List 39 | ) 40 | 41 | @Serializable 42 | data class Scouting( 43 | @SerialName("multicast") var multicast: Multicast, 44 | ) 45 | 46 | @Serializable 47 | data class Multicast( 48 | @SerialName("enabled") var enabled: Boolean, 49 | ) 50 | 51 | internal fun loadConfig( 52 | emptyArgs: Boolean, 53 | configFile: String?, 54 | connectEndpoints: List?, 55 | listenEndpoints: List?, 56 | noMulticastScouting: Boolean?, 57 | mode: String? 58 | ): Config { 59 | return if (emptyArgs) { 60 | Config.loadDefault() 61 | } else { 62 | configFile?.let { 63 | Config.fromFile(path = Path(it)) 64 | } ?: run { 65 | val connect = connectEndpoints?.let {Connect(it)} 66 | val listen = listenEndpoints?.let {Listen(it)} 67 | val scouting = noMulticastScouting?.let { Scouting(Multicast(!it)) } 68 | val configData = ConfigData(connect, listen, mode, scouting) 69 | val jsonConfig = Json.encodeToJsonElement(configData).toString() 70 | println(jsonConfig) 71 | Config.fromJson(jsonConfig) 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /examples/src/main/java/io/zenoh/QueueHandler.java: -------------------------------------------------------------------------------- 1 | package io.zenoh; 2 | 3 | import io.zenoh.handlers.Handler; 4 | 5 | import java.util.ArrayDeque; 6 | 7 | /** 8 | * Sample handler for the sake of the examples. 9 | * 10 | * A custom handler can be implemented to handle incoming samples, queries or replies for 11 | * subscribers, get operations, query operations or queryables. 12 | * 13 | * The example below shows a queue handler, in which an ArrayDeque is specified as the receiver type. 14 | * The function handle will be called everytime an element of type T is received and in our example 15 | * implementation, elements are simply enqueued into the queue, which can later be retrieved. 16 | */ 17 | class QueueHandler implements Handler> { 18 | 19 | final ArrayDeque queue = new ArrayDeque<>(); 20 | 21 | @Override 22 | public void handle(T t) { 23 | queue.add(t); 24 | } 25 | 26 | @Override 27 | public ArrayDeque receiver() { 28 | return queue; 29 | } 30 | 31 | @Override 32 | public void onClose() {} 33 | } 34 | -------------------------------------------------------------------------------- /examples/src/main/java/io/zenoh/ZDelete.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.exceptions.ZError; 18 | import io.zenoh.keyexpr.KeyExpr; 19 | import picocli.CommandLine; 20 | 21 | import java.util.List; 22 | import java.util.concurrent.Callable; 23 | 24 | import static io.zenoh.ConfigKt.loadConfig; 25 | 26 | @CommandLine.Command( 27 | name = "ZDelete", 28 | mixinStandardHelpOptions = true, 29 | description = "Zenoh Delete example" 30 | ) 31 | public class ZDelete implements Callable { 32 | 33 | @Override 34 | public Integer call() throws ZError { 35 | Zenoh.initLogFromEnvOr("error"); 36 | System.out.println("Opening session..."); 37 | Config config = loadConfig(emptyArgs, configFile, connect, listen, noMulticastScouting, mode); 38 | try (Session session = Zenoh.open(config)) { 39 | KeyExpr keyExpr = KeyExpr.tryFrom(key); 40 | System.out.println("Deleting resources matching '" + keyExpr + "'..."); 41 | session.delete(keyExpr); 42 | } 43 | return 0; 44 | } 45 | 46 | 47 | /** 48 | * ----- Example CLI arguments and private fields ----- 49 | */ 50 | 51 | private final Boolean emptyArgs; 52 | 53 | ZDelete(Boolean emptyArgs) { 54 | this.emptyArgs = emptyArgs; 55 | } 56 | 57 | @CommandLine.Option( 58 | names = {"-e", "--connect"}, 59 | description = "Endpoints to connect to.", 60 | split = "," 61 | ) 62 | private List connect; 63 | 64 | @CommandLine.Option( 65 | names = {"-l", "--listen"}, 66 | description = "Endpoints to listen on.", 67 | split = "," 68 | ) 69 | private List listen; 70 | 71 | @CommandLine.Option( 72 | names = {"-c", "--config"}, 73 | description = "A configuration file." 74 | ) 75 | private String configFile; 76 | 77 | @CommandLine.Option( 78 | names = {"-k", "--key"}, 79 | description = "The key expression to delete [default: demo/example/zenoh-java-delete].", 80 | defaultValue = "demo/example/zenoh-java-delete" 81 | ) 82 | private String key; 83 | 84 | @CommandLine.Option( 85 | names = {"-m", "--mode"}, 86 | description = "The session mode. Default: peer. Possible values: [peer, client, router].", 87 | defaultValue = "peer" 88 | ) 89 | private String mode; 90 | 91 | @CommandLine.Option( 92 | names = {"--no-multicast-scouting"}, 93 | description = "Disable the multicast-based scouting mechanism.", 94 | defaultValue = "false" 95 | ) 96 | private boolean noMulticastScouting; 97 | 98 | public static void main(String[] args) { 99 | int exitCode = new CommandLine(new ZDelete(args.length == 0)).execute(args); 100 | System.exit(exitCode); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /examples/src/main/java/io/zenoh/ZInfo.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.session.SessionInfo; 18 | import picocli.CommandLine; 19 | 20 | import java.util.List; 21 | import java.util.concurrent.Callable; 22 | 23 | import static io.zenoh.ConfigKt.loadConfig; 24 | 25 | @CommandLine.Command( 26 | name = "ZInfo", 27 | mixinStandardHelpOptions = true, 28 | description = "Zenoh Info example" 29 | ) 30 | public class ZInfo implements Callable { 31 | 32 | 33 | @Override 34 | public Integer call() throws Exception { 35 | Zenoh.initLogFromEnvOr("error"); 36 | 37 | Config config = loadConfig(emptyArgs, configFile, connect, listen, noMulticastScouting, mode); 38 | 39 | System.out.println("Opening session..."); 40 | try (Session session = Zenoh.open(config)) { 41 | SessionInfo info = session.info(); 42 | System.out.println("zid: " + info.zid()); 43 | System.out.println("routers zid: " + info.routersZid()); 44 | System.out.println("peers zid: " + info.peersZid()); 45 | } 46 | return 0; 47 | } 48 | 49 | /** 50 | * ----- Example CLI arguments and private fields ----- 51 | */ 52 | 53 | private final Boolean emptyArgs; 54 | 55 | ZInfo(Boolean emptyArgs) { 56 | this.emptyArgs = emptyArgs; 57 | } 58 | 59 | @CommandLine.Option( 60 | names = {"-c", "--config"}, 61 | description = "A configuration file." 62 | ) 63 | private String configFile; 64 | 65 | @CommandLine.Option( 66 | names = {"-e", "--connect"}, 67 | description = "Endpoints to connect to.", 68 | split = "," 69 | ) 70 | private List connect; 71 | 72 | @CommandLine.Option( 73 | names = {"-l", "--listen"}, 74 | description = "Endpoints to listen on.", 75 | split = "," 76 | ) 77 | private List listen; 78 | 79 | @CommandLine.Option( 80 | names = {"-m", "--mode"}, 81 | description = "The session mode. Default: peer. Possible values: [peer, client, router].", 82 | defaultValue = "peer" 83 | ) 84 | private String mode; 85 | 86 | @CommandLine.Option( 87 | names = {"--no-multicast-scouting"}, 88 | description = "Disable the multicast-based scouting mechanism.", 89 | defaultValue = "false" 90 | ) 91 | private boolean noMulticastScouting; 92 | 93 | public static void main(String[] args) { 94 | int exitCode = new CommandLine(new ZInfo(args.length == 0)).execute(args); 95 | System.exit(exitCode); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /examples/src/main/java/io/zenoh/ZLiveliness.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.keyexpr.KeyExpr; 18 | import picocli.CommandLine; 19 | 20 | import java.util.List; 21 | import java.util.concurrent.Callable; 22 | 23 | import static io.zenoh.ConfigKt.loadConfig; 24 | 25 | @CommandLine.Command( 26 | name = "ZLiveliness", 27 | mixinStandardHelpOptions = true, 28 | description = "Zenoh Liveliness example" 29 | ) 30 | public class ZLiveliness implements Callable { 31 | 32 | 33 | @Override 34 | public Integer call() throws Exception { 35 | Zenoh.initLogFromEnvOr("error"); 36 | 37 | Config config = loadConfig(emptyArgs, configFile, connect, listen, noMulticastScouting, mode); 38 | 39 | System.out.println("Opening session..."); 40 | try (Session session = Zenoh.open(config)) { 41 | KeyExpr keyExpr = KeyExpr.tryFrom(key); 42 | session.liveliness().declareToken(keyExpr); 43 | System.out.println("Liveliness token declared for key: " + key); 44 | 45 | while (true) { 46 | Thread.sleep(1000); 47 | } 48 | } 49 | } 50 | 51 | 52 | /** 53 | * ----- Example CLI arguments and private fields ----- 54 | */ 55 | 56 | private final Boolean emptyArgs; 57 | 58 | ZLiveliness(Boolean emptyArgs) { 59 | this.emptyArgs = emptyArgs; 60 | } 61 | 62 | @CommandLine.Option( 63 | names = {"-c", "--config"}, 64 | description = "A configuration file." 65 | ) 66 | private String configFile; 67 | 68 | @CommandLine.Option( 69 | names = {"-k", "--key"}, 70 | description = "The key expression to declare liveliness tokens for [default: group1/zenoh-java].", 71 | defaultValue = "group1/zenoh-java" 72 | ) 73 | private String key; 74 | 75 | @CommandLine.Option( 76 | names = {"-e", "--connect"}, 77 | description = "Endpoints to connect to.", 78 | split = "," 79 | ) 80 | private List connect; 81 | 82 | @CommandLine.Option( 83 | names = {"-l", "--listen"}, 84 | description = "Endpoints to listen on.", 85 | split = "," 86 | ) 87 | private List listen; 88 | 89 | @CommandLine.Option( 90 | names = {"-m", "--mode"}, 91 | description = "The session mode. Default: peer. Possible values: [peer, client, router].", 92 | defaultValue = "peer" 93 | ) 94 | private String mode; 95 | 96 | @CommandLine.Option( 97 | names = {"--no-multicast-scouting"}, 98 | description = "Disable the multicast-based scouting mechanism.", 99 | defaultValue = "false" 100 | ) 101 | private boolean noMulticastScouting; 102 | 103 | 104 | public static void main(String[] args) { 105 | int exitCode = new CommandLine(new ZLiveliness(args.length == 0)).execute(args); 106 | System.exit(exitCode); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /examples/src/main/java/io/zenoh/ZPong.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.exceptions.ZError; 18 | import io.zenoh.keyexpr.KeyExpr; 19 | import io.zenoh.pubsub.Publisher; 20 | import io.zenoh.pubsub.PublisherOptions; 21 | import io.zenoh.qos.CongestionControl; 22 | import picocli.CommandLine; 23 | 24 | import java.util.List; 25 | import java.util.concurrent.Callable; 26 | import java.util.concurrent.CountDownLatch; 27 | 28 | import static io.zenoh.ConfigKt.loadConfig; 29 | 30 | @CommandLine.Command( 31 | name = "ZPong", 32 | mixinStandardHelpOptions = true, 33 | description = "Zenoh ZPong example" 34 | ) 35 | public class ZPong implements Callable { 36 | 37 | @Override 38 | public Integer call() throws Exception { 39 | Zenoh.initLogFromEnvOr("error"); 40 | 41 | Config config = loadConfig(true, configFile, connect, listen, noMulticastScouting, mode); 42 | 43 | System.out.println("Opening session..."); 44 | try (Session session = Zenoh.open(config)) { 45 | KeyExpr keyExprPing = KeyExpr.tryFrom("test/ping"); 46 | KeyExpr keyExprPong = KeyExpr.tryFrom("test/pong"); 47 | 48 | var publisherOptions = new PublisherOptions(); 49 | publisherOptions.setCongestionControl(CongestionControl.BLOCK); 50 | publisherOptions.setExpress(!noExpress); 51 | 52 | Publisher publisher = session.declarePublisher(keyExprPong, publisherOptions); 53 | 54 | session.declareSubscriber(keyExprPing, sample -> { 55 | try { 56 | publisher.put(sample.getPayload()); 57 | } catch (ZError e) { 58 | System.err.println("Error responding to ping: " + e.getMessage()); 59 | } 60 | }); 61 | 62 | latch.await(); 63 | } 64 | return 0; 65 | } 66 | 67 | 68 | /** 69 | * ----- Example CLI arguments and private fields ----- 70 | */ 71 | 72 | @CommandLine.Option( 73 | names = "--no-express", 74 | description = "Express for sending data.", 75 | defaultValue = "false" 76 | ) 77 | private boolean noExpress; 78 | 79 | @CommandLine.Option( 80 | names = {"-c", "--config"}, 81 | description = "A configuration file." 82 | ) 83 | private String configFile; 84 | 85 | @CommandLine.Option( 86 | names = {"-e", "--connect"}, 87 | description = "Endpoints to connect to.", 88 | split = "," 89 | ) 90 | private List connect; 91 | 92 | @CommandLine.Option( 93 | names = {"-l", "--listen"}, 94 | description = "Endpoints to listen on.", 95 | split = "," 96 | ) 97 | private List listen; 98 | 99 | @CommandLine.Option( 100 | names = {"-m", "--mode"}, 101 | description = "The session mode. Default: peer. Possible values: [peer, client, router].", 102 | defaultValue = "peer" 103 | ) 104 | private String mode; 105 | 106 | @CommandLine.Option( 107 | names = {"--no-multicast-scouting"}, 108 | description = "Disable the multicast-based scouting mechanism.", 109 | defaultValue = "false" 110 | ) 111 | private boolean noMulticastScouting; 112 | 113 | private static final CountDownLatch latch = new CountDownLatch(1); 114 | 115 | public static void main(String[] args) { 116 | Runtime.getRuntime().addShutdownHook(new Thread(() -> { 117 | System.out.println("Shutting down..."); 118 | latch.countDown(); 119 | })); 120 | 121 | int exitCode = new CommandLine(new ZPong()).execute(args); 122 | System.exit(exitCode); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /examples/src/main/java/io/zenoh/ZPut.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.keyexpr.KeyExpr; 18 | import io.zenoh.pubsub.PutOptions; 19 | import picocli.CommandLine; 20 | 21 | import java.util.List; 22 | import java.util.concurrent.Callable; 23 | 24 | import static io.zenoh.ConfigKt.loadConfig; 25 | 26 | @CommandLine.Command( 27 | name = "ZPut", 28 | mixinStandardHelpOptions = true, 29 | description = "Zenoh Put example" 30 | ) 31 | public class ZPut implements Callable { 32 | 33 | @Override 34 | public Integer call() throws Exception { 35 | Zenoh.initLogFromEnvOr("error"); 36 | 37 | Config config = loadConfig(emptyArgs, configFile, connect, listen, noMulticastScouting, mode); 38 | 39 | System.out.println("Opening session..."); 40 | try (Session session = Zenoh.open(config)) { 41 | KeyExpr keyExpr = KeyExpr.tryFrom(key); 42 | System.out.println("Putting Data ('" + keyExpr + "': '" + value + "')..."); 43 | if (attachment != null) { 44 | var putOptions = new PutOptions(); 45 | putOptions.setAttachment(attachment); 46 | session.put(keyExpr, value, putOptions); 47 | } else { 48 | session.put(keyExpr, value); 49 | } 50 | } 51 | return 0; 52 | } 53 | 54 | 55 | /** 56 | * ----- Example CLI arguments and private fields ----- 57 | */ 58 | 59 | private final Boolean emptyArgs; 60 | 61 | ZPut(Boolean emptyArgs) { 62 | this.emptyArgs = emptyArgs; 63 | } 64 | 65 | @CommandLine.Option( 66 | names = {"-c", "--config"}, 67 | description = "A configuration file." 68 | ) 69 | private String configFile; 70 | 71 | @CommandLine.Option( 72 | names = {"-k", "--key"}, 73 | description = "The key expression to write to [default: demo/example/zenoh-java-put].", 74 | defaultValue = "demo/example/zenoh-java-put" 75 | ) 76 | private String key; 77 | 78 | @CommandLine.Option( 79 | names = {"-e", "--connect"}, 80 | description = "Endpoints to connect to.", 81 | split = "," 82 | ) 83 | private List connect; 84 | 85 | @CommandLine.Option( 86 | names = {"-l", "--listen"}, 87 | description = "Endpoints to listen on.", 88 | split = "," 89 | ) 90 | private List listen; 91 | 92 | @CommandLine.Option( 93 | names = {"-m", "--mode"}, 94 | description = "The session mode. Default: peer. Possible values: [peer, client, router].", 95 | defaultValue = "peer" 96 | ) 97 | private String mode; 98 | 99 | @CommandLine.Option( 100 | names = {"-v", "--value"}, 101 | description = "The value to write. [default: 'Put from Java!'].", 102 | defaultValue = "Put from Java!" 103 | ) 104 | private String value; 105 | 106 | @CommandLine.Option( 107 | names = {"-a", "--attach"}, 108 | description = "The attachment to add to the put. The key-value pairs are &-separated, and = serves as the separator between key and value." 109 | ) 110 | private String attachment; 111 | 112 | @CommandLine.Option( 113 | names = {"--no-multicast-scouting"}, 114 | description = "Disable the multicast-based scouting mechanism.", 115 | defaultValue = "false" 116 | ) 117 | private boolean noMulticastScouting; 118 | 119 | public static void main(String[] args) { 120 | int exitCode = new CommandLine(new ZPut(args.length == 0)).execute(args); 121 | System.exit(exitCode); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /examples/src/main/java/io/zenoh/ZScout.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.config.WhatAmI; 18 | import io.zenoh.scouting.Hello; 19 | import io.zenoh.scouting.ScoutOptions; 20 | import picocli.CommandLine; 21 | 22 | import java.util.Optional; 23 | import java.util.Set; 24 | import java.util.concurrent.BlockingQueue; 25 | import java.util.concurrent.Callable; 26 | 27 | @CommandLine.Command( 28 | name = "ZScout", 29 | mixinStandardHelpOptions = true, 30 | description = "Zenoh Scouting example" 31 | ) 32 | public class ZScout implements Callable { 33 | 34 | @Override 35 | public Integer call() throws Exception { 36 | Zenoh.initLogFromEnvOr("error"); 37 | 38 | System.out.println("Scouting..."); 39 | 40 | var scoutOptions = new ScoutOptions(); 41 | scoutOptions.setWhatAmI(Set.of(WhatAmI.Peer, WhatAmI.Router)); 42 | var scout = Zenoh.scout(scoutOptions); 43 | BlockingQueue> receiver = scout.getReceiver(); 44 | assert receiver != null; 45 | 46 | try { 47 | while (true) { 48 | Optional wrapper = receiver.take(); 49 | if (wrapper.isEmpty()) { 50 | break; 51 | } 52 | 53 | Hello hello = wrapper.get(); 54 | System.out.println(hello); 55 | } 56 | } finally { 57 | scout.stop(); 58 | } 59 | 60 | return 0; 61 | } 62 | 63 | public static void main(String[] args) { 64 | int exitCode = new CommandLine(new ZScout()).execute(args); 65 | System.exit(exitCode); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled 2 | org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true 3 | -------------------------------------------------------------------------------- /jvm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-zenoh/zenoh-java/0345b1c689db0aa2947c720606b43396da328fc8/jvm.png -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.85.0" 3 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | pluginManagement { 16 | repositories { 17 | gradlePluginPortal() 18 | mavenCentral() 19 | google() 20 | } 21 | } 22 | rootProject.name = "zenoh-java" 23 | 24 | include(":zenoh-java") 25 | include(":examples") 26 | include(":zenoh-jni") 27 | 28 | plugins { 29 | id("org.gradle.toolchains.foojay-resolver-convention") version("0.4.0") 30 | } 31 | -------------------------------------------------------------------------------- /version.txt: -------------------------------------------------------------------------------- 1 | 1.4.0 -------------------------------------------------------------------------------- /zenoh-dragon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-zenoh/zenoh-java/0345b1c689db0aa2947c720606b43396da328fc8/zenoh-dragon.png -------------------------------------------------------------------------------- /zenoh-java/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /zenoh-java/src/androidMain/kotlin/io.zenoh/Zenoh.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh 16 | 17 | /** 18 | * Static singleton class to load the Zenoh native library once and only once, as well as the logger in function of the 19 | * log level configuration. 20 | */ 21 | internal actual object ZenohLoad { 22 | private const val ZENOH_LIB_NAME = "zenoh_jni" 23 | 24 | init { 25 | System.loadLibrary(ZENOH_LIB_NAME) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/Logger.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh 16 | 17 | import io.zenoh.exceptions.ZError 18 | 19 | /** Logger class to redirect the Rust logs from Zenoh to the kotlin environment. */ 20 | internal class Logger { 21 | 22 | companion object { 23 | 24 | internal const val LOG_ENV: String = "RUST_LOG" 25 | 26 | @Throws(ZError::class) 27 | fun start(filter: String) { 28 | startLogsViaJNI(filter) 29 | } 30 | 31 | /** 32 | * Redirects the rust logs either to logcat for Android systems or to the standard output (for non-android 33 | * systems). 34 | * 35 | * See https://docs.rs/env_logger/latest/env_logger/index.html for accepted filter format. 36 | */ 37 | @Throws(ZError::class) 38 | private external fun startLogsViaJNI(filter: String) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/ZenohType.kt: -------------------------------------------------------------------------------- 1 | package io.zenoh 2 | 3 | /** 4 | * Zenoh type. 5 | * 6 | * This kind of elements have in common that they can be received through the Zenoh network. 7 | */ 8 | interface ZenohType 9 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/annotations/Annotations.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.annotations 16 | 17 | @RequiresOptIn( 18 | level = RequiresOptIn.Level.WARNING, 19 | message = "This feature is unstable and may change in future releases." 20 | ) 21 | @Retention(AnnotationRetention.BINARY) 22 | @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) 23 | annotation class Unstable 24 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/bytes/IntoZBytes.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.bytes 16 | 17 | /** 18 | * IntoZBytes interface. 19 | * 20 | * Classes implementing this interface can be serialized into a ZBytes object. 21 | * 22 | * Example: 23 | * ```java 24 | * class Foo implements IntoZBytes { 25 | * 26 | * private final String content; 27 | * 28 | * Foo(String content) { 29 | * this.content = content; 30 | * } 31 | * 32 | * @NotNull 33 | * @Override 34 | * public ZBytes into() { 35 | * return ZBytes.from(content); 36 | * } 37 | * } 38 | * ``` 39 | */ 40 | interface IntoZBytes { 41 | fun into(): ZBytes 42 | } 43 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/bytes/ZBytes.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.bytes 16 | 17 | /** 18 | * ZBytes contains the serialized bytes of user data. 19 | * 20 | * It provides convenient methods to the user for serialization/deserialization. 21 | * 22 | * **NOTE** 23 | * 24 | * Zenoh semantic and protocol take care of sending and receiving bytes 25 | * without restricting the actual data types. Default (de)serializers are provided for 26 | * convenience to the users to deal with primitives data types via a simple 27 | * out-of-the-box encoding. They are NOT by any means the only (de)serializers 28 | * users can use nor a limitation to the types supported by Zenoh. Users are free and 29 | * encouraged to use any data format of their choice like JSON, protobuf, 30 | * flatbuffers, etc. 31 | * 32 | */ 33 | class ZBytes internal constructor(internal val bytes: ByteArray) : IntoZBytes { 34 | 35 | companion object { 36 | 37 | /** 38 | * Creates a [ZBytes] instance from a [String]. 39 | */ 40 | @JvmStatic 41 | fun from(string: String) = ZBytes(string.encodeToByteArray()) 42 | 43 | /** 44 | * Creates a [ZBytes] instance from a [ByteArray]. 45 | */ 46 | @JvmStatic 47 | fun from(bytes: ByteArray) = ZBytes(bytes) 48 | } 49 | 50 | /** Returns the internal byte representation of the [ZBytes]. */ 51 | fun toBytes(): ByteArray = bytes 52 | 53 | /** Attempts to decode the [ZBytes] into a string with UTF-8 encoding. */ 54 | @Throws 55 | fun tryToString(): String = 56 | bytes.decodeToString(throwOnInvalidSequence = true) 57 | 58 | override fun toString(): String = bytes.decodeToString() 59 | 60 | override fun into(): ZBytes = this 61 | 62 | override fun equals(other: Any?) = other is ZBytes && bytes.contentEquals(other.bytes) 63 | 64 | override fun hashCode() = bytes.contentHashCode() 65 | } 66 | 67 | internal fun ByteArray.into(): ZBytes { 68 | return ZBytes(this) 69 | } 70 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/config/WhatAmI.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.config 16 | 17 | /** 18 | * WhatAmI 19 | * 20 | * The role of the node sending the `hello` message. 21 | */ 22 | enum class WhatAmI(internal val value: Int) { 23 | Router(1), 24 | Peer(2), 25 | Client(4); 26 | 27 | companion object { 28 | internal fun fromInt(value: Int) = entries.first { value == it.value } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/config/ZenohId.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.config 16 | 17 | import io.zenoh.jni.JNIZenohId 18 | 19 | /** 20 | * The global unique id of a Zenoh peer. 21 | */ 22 | data class ZenohId internal constructor(internal val bytes: ByteArray) { 23 | 24 | override fun toString(): String { 25 | return JNIZenohId.toStringViaJNI(bytes) 26 | } 27 | 28 | override fun equals(other: Any?): Boolean { 29 | if (this === other) return true 30 | if (javaClass != other?.javaClass) return false 31 | 32 | other as ZenohId 33 | 34 | return bytes.contentEquals(other.bytes) 35 | } 36 | 37 | override fun hashCode(): Int { 38 | return bytes.contentHashCode() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/exceptions/ZError.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.exceptions 16 | 17 | /** 18 | * A Zenoh Error. 19 | */ 20 | class ZError(override val message: String? = null): Exception() 21 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/ext/ZDeserializer.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.ext 16 | 17 | import com.google.common.reflect.TypeToken 18 | import io.zenoh.bytes.IntoZBytes 19 | import io.zenoh.bytes.ZBytes 20 | import io.zenoh.jni.JNIZBytes 21 | 22 | /** 23 | * Zenoh deserializer. 24 | * 25 | * This class is a utility for deserializing [ZBytes] into elements of type [T]. 26 | * 27 | * This class supports the following types: 28 | * - [Boolean] 29 | * - [Byte] 30 | * - [Short] 31 | * - [Int] 32 | * - [Long] 33 | * - [Float] 34 | * - [Double] 35 | * - [List] 36 | * - [String] 37 | * - [ByteArray] 38 | * - [Map] 39 | * 40 | * For List and Map, the inner types can be a combination of the above types, including themselves. 41 | * 42 | * Due to Java's type erasure, an actual implementation of this abstract class needs to be created (see the examples below). 43 | * 44 | * This deserialization utility can be used across the Zenoh ecosystem with Zenoh 45 | * versions based on other supported languages such as Rust, Python, C and C++. 46 | * This works when the types are equivalent (a `Byte` corresponds to an `i8` in Rust, a `Short` to an `i16`, etc). 47 | * 48 | * # Examples 49 | * 50 | * Example for a basic type, in this case an integer: 51 | * ```java 52 | * Integer input = 123456; 53 | * ZSerializer serializer = new ZSerializer<>() {}; 54 | * ZBytes zbytes = serializer.serialize(input); 55 | * 56 | * ZDeserializer deserializer = new ZDeserializer<>() {}; 57 | * Integer output = deserializer.deserialize(zbytes); 58 | * assert input.equals(output); 59 | * ``` 60 | * 61 | * Examples for parameterized types: 62 | * - List 63 | * ```java 64 | * List input = List.of(1, 2, 3, 4, 5); 65 | * ZSerializer> serializer = new ZSerializer<>() {}; 66 | * ZBytes zbytes = serializer.serialize(input12); 67 | * 68 | * ZDeserializer> deserializer = new ZDeserializer<>() {}; 69 | * List output = deserializer.deserialize(zbytes); 70 | * assert input.equals(output); 71 | * ``` 72 | * 73 | * - Map 74 | * ```java 75 | * Map input = Map.of("one", 1, "two", 2, "three", 3); 76 | * ZSerializer> serializer = new ZSerializer<>() {}; 77 | * ZBytes zbytes = serializer.serialize(input); 78 | * 79 | * ZDeserializer> deserializer = new ZDeserializer<>() {}; 80 | * Map output = deserializer.deserialize(zbytes); 81 | * assert input.equals(output); 82 | * ``` 83 | * 84 | * As mentioned, for List and Map, the inner types can be a combination of the above types, including themselves. 85 | * Here's an example with a List of Maps: 86 | * ```java 87 | * List> input = List.of(Map.of("a", 1, "b", 2)); 88 | * ZSerializer>> serializer = new ZSerializer<>() {}; 89 | * ZBytes zbytes = serializer.serialize(input); 90 | * 91 | * ZDeserializer>> deserializer = new ZDeserializer<>() {}; 92 | * List> output = deserializer.deserialize(zbytes); 93 | * assert input.equals(output); 94 | * ``` 95 | * 96 | * For more examples, see the ZBytesExamples in the examples. 97 | * 98 | * @param T The deserialization type. 99 | * @see ZBytes 100 | * @see ZSerializer 101 | */ 102 | abstract class ZDeserializer: TypeToken() { 103 | 104 | /** 105 | * Deserialize the [zbytes] into an element of type [T]. 106 | */ 107 | fun deserialize(zbytes: IntoZBytes): T { 108 | @Suppress("UNCHECKED_CAST") 109 | return JNIZBytes.deserializeViaJNI(zbytes.into(), this.type) as T 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/ext/ZSerializer.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.ext 16 | 17 | import com.google.common.reflect.TypeToken 18 | import io.zenoh.bytes.ZBytes 19 | import io.zenoh.jni.JNIZBytes 20 | 21 | /** 22 | * Zenoh serializer. 23 | * 24 | * This class is a utility for serializing elements of type [T] into [ZBytes]. 25 | * 26 | * This class supports the following types: 27 | * - [Boolean] 28 | * - [Byte] 29 | * - [Short] 30 | * - [Int] 31 | * - [Long] 32 | * - [Float] 33 | * - [Double] 34 | * - [List] 35 | * - [String] 36 | * - [ByteArray] 37 | * - [Map] 38 | * 39 | * For List and Map, the inner types can be a combination of the above types, including themselves. 40 | * 41 | * Due to Java's type erasure, an actual implementation of this abstract class needs to be created (see the examples below). 42 | * 43 | * This serialization utility can be used across the Zenoh ecosystem with Zenoh 44 | * versions based on other supported languages such as Rust, Python, C and C++. 45 | * This works when the types are equivalent (a `Byte` corresponds to an `i8` in Rust, a `Short` to an `i16`, etc). 46 | * 47 | * # Examples 48 | * 49 | * Example for a basic type, in this case an integer: 50 | * ```java 51 | * Integer input = 123456; 52 | * ZSerializer serializer = new ZSerializer<>() {}; 53 | * ZBytes zbytes = serializer.serialize(input); 54 | * 55 | * ZDeserializer deserializer = new ZDeserializer<>() {}; 56 | * Integer output = deserializer.deserialize(zbytes); 57 | * assert input.equals(output); 58 | * ``` 59 | * 60 | * Examples for parameterized types: 61 | * - List 62 | * ```java 63 | * List input = List.of(1, 2, 3, 4, 5); 64 | * ZSerializer> serializer = new ZSerializer<>() {}; 65 | * ZBytes zbytes = serializer.serialize(input12); 66 | * 67 | * ZDeserializer> deserializer = new ZDeserializer<>() {}; 68 | * List output = deserializer.deserialize(zbytes); 69 | * assert input.equals(output); 70 | * ``` 71 | * 72 | * - Map 73 | * ```java 74 | * Map input = Map.of("one", 1, "two", 2, "three", 3); 75 | * ZSerializer> serializer = new ZSerializer<>() {}; 76 | * ZBytes zbytes = serializer.serialize(input); 77 | * 78 | * ZDeserializer> deserializer = new ZDeserializer<>() {}; 79 | * Map output = deserializer.deserialize(zbytes); 80 | * assert input.equals(output); 81 | * ``` 82 | * 83 | * As mentioned, for List and Map, the inner types can be a combination of the above types, including themselves. 84 | * Here's an example with a List of Maps: 85 | * ```java 86 | * List> input = List.of(Map.of("a", 1, "b", 2)); 87 | * ZSerializer>> serializer = new ZSerializer<>() {}; 88 | * ZBytes zbytes = serializer.serialize(input); 89 | * 90 | * ZDeserializer>> deserializer = new ZDeserializer<>() {}; 91 | * List> output = deserializer.deserialize(zbytes); 92 | * assert input.equals(output); 93 | * ``` 94 | * 95 | * For more examples, see the ZBytesExamples in the examples. 96 | * 97 | * @param T The type to be serialized. 98 | * @see ZBytes 99 | * @see ZDeserializer 100 | */ 101 | abstract class ZSerializer: TypeToken() { 102 | 103 | /** 104 | * Serialize [t] into a [ZBytes]. 105 | */ 106 | fun serialize(t: T): ZBytes { 107 | return JNIZBytes.serializeViaJNI(t as Any, this.type) 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/handlers/BlockingQueueHandler.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.handlers 16 | 17 | import io.zenoh.ZenohType 18 | import java.util.Optional 19 | import java.util.concurrent.BlockingQueue 20 | 21 | /** 22 | * Blocking queue handler 23 | * 24 | * Implementation of a [Handler] with a [BlockingQueue] receiver. 25 | * 26 | * The way to tell no more elements of type [T] will be received is when an empty element is put (see [onClose]). 27 | * 28 | * @param T a [ZenohType] 29 | * @property queue 30 | * @constructor Create empty Queue handler 31 | */ 32 | internal class BlockingQueueHandler(private val queue: BlockingQueue>) : Handler>> { 33 | 34 | override fun handle(t: T) { 35 | queue.put(Optional.of(t)) 36 | } 37 | 38 | override fun receiver(): BlockingQueue> { 39 | return queue 40 | } 41 | 42 | override fun onClose() { 43 | queue.put(Optional.empty()) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/handlers/Callback.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.handlers 16 | 17 | import io.zenoh.ZenohType 18 | 19 | /** 20 | * Runnable callback. 21 | * 22 | * @param T Type of the parameter, which is a [ZenohType]. 23 | * @constructor Create empty Callback 24 | */ 25 | fun interface Callback { 26 | 27 | /** Callback to be run. */ 28 | fun run(t: T) 29 | 30 | } 31 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/handlers/Handler.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.handlers 16 | 17 | import io.zenoh.ZenohType 18 | 19 | /** 20 | * Handler interface for classes implementing behavior to handle the 21 | * incoming [T] elements. 22 | * 23 | * **Example**: 24 | * In this example we implement a handler that stores the received elements into an ArrayDeque, 25 | * which can then be retrieved: 26 | * 27 | * ```java 28 | * public class QueueHandler implements Handler> { 29 | * 30 | * private final ArrayDeque queue = new ArrayDeque<>(); 31 | * 32 | * @Override 33 | * public void handle(T t) { 34 | * System.out.println("Received " + t + ", enqueuing..."); 35 | * queue.add(t); 36 | * } 37 | * 38 | * @Override 39 | * public ArrayDeque receiver() { 40 | * return queue; 41 | * } 42 | * 43 | * @Override 44 | * public void onClose() { 45 | * System.out.println("Received in total " + queue.size() + " elements."); 46 | * } 47 | * } 48 | * ``` 49 | * 50 | * That `QueueHandler` could then be used as follows, for instance for a subscriber: 51 | * ```java 52 | * var queue = session.declareSubscriber(keyExpr, new QueueHandler()); 53 | * ... 54 | * ``` 55 | * where the `queue` returned is the receiver from the handler. 56 | * 57 | * @param T A receiving [ZenohType]. 58 | * @param R An arbitrary receiver. 59 | */ 60 | interface Handler { 61 | 62 | /** 63 | * Handle the received [t] element. 64 | * 65 | * @param t An element of type [T]. 66 | */ 67 | fun handle(t: T) 68 | 69 | /** 70 | * Return the receiver of the handler. 71 | */ 72 | fun receiver(): R 73 | 74 | /** 75 | * This callback is invoked by Zenoh at the conclusion of the handler's lifecycle. 76 | * 77 | * For instances of [io.zenoh.queryable.Queryable] and [io.zenoh.subscriber.Subscriber], 78 | * Zenoh triggers this callback when they are closed or undeclared. In the case of a Get query 79 | * (see [io.zenoh.query.Get]), it is invoked when no more elements of type [T] are expected 80 | * to be received. 81 | */ 82 | fun onClose() 83 | } 84 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/JNIConfig.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni 16 | 17 | import io.zenoh.Config 18 | import io.zenoh.ZenohLoad 19 | import io.zenoh.exceptions.ZError 20 | import java.io.File 21 | import java.nio.file.Path 22 | 23 | internal class JNIConfig(internal val ptr: Long) { 24 | 25 | companion object { 26 | 27 | init { 28 | ZenohLoad 29 | } 30 | 31 | fun loadDefaultConfig(): Config { 32 | val cfgPtr = loadDefaultConfigViaJNI() 33 | return Config(JNIConfig(cfgPtr)) 34 | } 35 | 36 | @Throws(ZError::class) 37 | fun loadConfigFile(path: Path): Config { 38 | val cfgPtr = loadConfigFileViaJNI(path.toString()) 39 | return Config(JNIConfig(cfgPtr)) 40 | } 41 | 42 | @Throws(ZError::class) 43 | fun loadConfigFile(file: File): Config = loadConfigFile(file.toPath()) 44 | 45 | @Throws(ZError::class) 46 | fun loadJsonConfig(rawConfig: String): Config { 47 | val cfgPtr = loadJsonConfigViaJNI(rawConfig) 48 | return Config(JNIConfig(cfgPtr)) 49 | } 50 | 51 | @Throws(ZError::class) 52 | fun loadJson5Config(rawConfig: String): Config { 53 | val cfgPtr = loadJsonConfigViaJNI(rawConfig) 54 | return Config(JNIConfig(cfgPtr)) 55 | } 56 | 57 | @Throws(ZError::class) 58 | fun loadYamlConfig(rawConfig: String): Config { 59 | val cfgPtr = loadYamlConfigViaJNI(rawConfig) 60 | return Config(JNIConfig(cfgPtr)) 61 | } 62 | 63 | @Throws(ZError::class) 64 | private external fun loadDefaultConfigViaJNI(): Long 65 | 66 | @Throws(ZError::class) 67 | private external fun loadConfigFileViaJNI(path: String): Long 68 | 69 | @Throws(ZError::class) 70 | private external fun loadJsonConfigViaJNI(rawConfig: String): Long 71 | 72 | @Throws(ZError::class) 73 | private external fun loadYamlConfigViaJNI(rawConfig: String): Long 74 | 75 | @Throws(ZError::class) 76 | private external fun getIdViaJNI(ptr: Long): ByteArray 77 | 78 | @Throws(ZError::class) 79 | private external fun insertJson5ViaJNI(ptr: Long, key: String, value: String): Long 80 | 81 | /** Frees the underlying native config. */ 82 | private external fun freePtrViaJNI(ptr: Long) 83 | 84 | @Throws(ZError::class) 85 | private external fun getJsonViaJNI(ptr: Long, key: String): String 86 | } 87 | 88 | fun close() { 89 | freePtrViaJNI(ptr) 90 | } 91 | 92 | @Throws(ZError::class) 93 | fun getJson(key: String): String { 94 | return getJsonViaJNI(ptr, key) 95 | } 96 | 97 | @Throws(ZError::class) 98 | fun insertJson5(key: String, value: String) { 99 | insertJson5ViaJNI(this.ptr, key, value) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/JNIKeyExpr.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni 16 | 17 | import io.zenoh.ZenohLoad 18 | import io.zenoh.exceptions.ZError 19 | import io.zenoh.keyexpr.KeyExpr 20 | import io.zenoh.keyexpr.SetIntersectionLevel 21 | 22 | internal class JNIKeyExpr(internal val ptr: Long) { 23 | 24 | companion object { 25 | init { 26 | ZenohLoad 27 | } 28 | 29 | @Throws(ZError::class) 30 | fun tryFrom(keyExpr: String): KeyExpr { 31 | return KeyExpr(tryFromViaJNI(keyExpr)) 32 | } 33 | 34 | @Throws(ZError::class) 35 | fun autocanonize(keyExpr: String): KeyExpr { 36 | return KeyExpr(autocanonizeViaJNI(keyExpr)) 37 | } 38 | 39 | @Throws(ZError::class) 40 | fun intersects(keyExprA: KeyExpr, keyExprB: KeyExpr): Boolean = intersectsViaJNI( 41 | keyExprA.jniKeyExpr?.ptr ?: 0, 42 | keyExprA.keyExpr, 43 | keyExprB.jniKeyExpr?.ptr ?: 0, 44 | keyExprB.keyExpr 45 | ) 46 | 47 | @Throws(ZError::class) 48 | fun includes(keyExprA: KeyExpr, keyExprB: KeyExpr): Boolean = includesViaJNI( 49 | keyExprA.jniKeyExpr?.ptr ?: 0, 50 | keyExprA.keyExpr, 51 | keyExprB.jniKeyExpr?.ptr ?: 0, 52 | keyExprB.keyExpr 53 | ) 54 | 55 | @Throws(ZError::class) 56 | fun relationTo(keyExpr: KeyExpr, other: KeyExpr): SetIntersectionLevel { 57 | val intersection = relationToViaJNI( 58 | keyExpr.jniKeyExpr?.ptr ?: 0, 59 | keyExpr.keyExpr, 60 | other.jniKeyExpr?.ptr ?: 0, 61 | other.keyExpr 62 | ) 63 | return SetIntersectionLevel.fromInt(intersection) 64 | } 65 | 66 | @Throws(ZError::class) 67 | fun joinViaJNI(keyExpr: KeyExpr, other: String): KeyExpr { 68 | return KeyExpr(joinViaJNI(keyExpr.jniKeyExpr?.ptr ?: 0, keyExpr.keyExpr, other)) 69 | } 70 | 71 | @Throws(ZError::class) 72 | fun concatViaJNI(keyExpr: KeyExpr, other: String): KeyExpr { 73 | return KeyExpr(concatViaJNI(keyExpr.jniKeyExpr?.ptr ?: 0, keyExpr.keyExpr, other)) 74 | } 75 | 76 | @Throws(ZError::class) 77 | private external fun tryFromViaJNI(keyExpr: String): String 78 | 79 | @Throws(ZError::class) 80 | private external fun autocanonizeViaJNI(keyExpr: String): String 81 | 82 | @Throws(ZError::class) 83 | private external fun intersectsViaJNI(ptrA: Long, keyExprA: String, ptrB: Long, keyExprB: String): Boolean 84 | 85 | @Throws(ZError::class) 86 | private external fun includesViaJNI(ptrA: Long, keyExprA: String, ptrB: Long, keyExprB: String): Boolean 87 | 88 | @Throws(ZError::class) 89 | private external fun relationToViaJNI(ptrA: Long, keyExprA: String, ptrB: Long, keyExprB: String): Int 90 | 91 | @Throws(ZError::class) 92 | private external fun joinViaJNI(ptrA: Long, keyExprA: String, other: String): String 93 | 94 | @Throws(ZError::class) 95 | private external fun concatViaJNI(ptrA: Long, keyExprA: String, other: String): String 96 | } 97 | 98 | fun close() { 99 | freePtrViaJNI(ptr) 100 | } 101 | 102 | /** Frees the underlying native KeyExpr. */ 103 | private external fun freePtrViaJNI(ptr: Long) 104 | } 105 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/JNILivelinessToken.kt: -------------------------------------------------------------------------------- 1 | package io.zenoh.jni 2 | 3 | internal class JNILivelinessToken(val ptr: Long) { 4 | 5 | fun undeclare() { 6 | undeclareViaJNI(this.ptr) 7 | } 8 | 9 | companion object { 10 | external fun undeclareViaJNI(ptr: Long) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/JNIPublisher.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni 16 | 17 | import io.zenoh.exceptions.ZError 18 | import io.zenoh.bytes.Encoding 19 | import io.zenoh.bytes.IntoZBytes 20 | 21 | /** 22 | * Adapter class to handle the interactions with Zenoh through JNI for a [io.zenoh.pubsub.Publisher]. 23 | * 24 | * @property ptr: raw pointer to the underlying native Publisher. 25 | */ 26 | internal class JNIPublisher(private val ptr: Long) { 27 | 28 | /** 29 | * Put operation. 30 | * 31 | * @param payload Payload of the put. 32 | * @param encoding Encoding of the payload. 33 | * @param attachment Optional attachment. 34 | */ 35 | @Throws(ZError::class) 36 | fun put(payload: IntoZBytes, encoding: Encoding?, attachment: IntoZBytes?) { 37 | val resolvedEncoding = encoding ?: Encoding.defaultEncoding() 38 | putViaJNI(payload.into().bytes, resolvedEncoding.id, resolvedEncoding.schema, attachment?.into()?.bytes, ptr) 39 | } 40 | 41 | /** 42 | * Delete operation. 43 | * 44 | * @param attachment Optional attachment. 45 | */ 46 | @Throws(ZError::class) 47 | fun delete(attachment: IntoZBytes?) { 48 | deleteViaJNI(attachment?.into()?.bytes, ptr) 49 | } 50 | 51 | /** 52 | * Close and free the underlying publisher pointer. 53 | * 54 | * Further operations with this publisher should not be performed anymore. 55 | */ 56 | fun close() { 57 | freePtrViaJNI(ptr) 58 | } 59 | 60 | @Throws(ZError::class) 61 | private external fun putViaJNI( 62 | valuePayload: ByteArray, encodingId: Int, encodingSchema: String?, attachment: ByteArray?, ptr: Long 63 | ) 64 | 65 | @Throws(ZError::class) 66 | private external fun deleteViaJNI(attachment: ByteArray?, ptr: Long) 67 | 68 | private external fun freePtrViaJNI(ptr: Long) 69 | 70 | } 71 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/JNIQuerier.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni 16 | 17 | import io.zenoh.annotations.Unstable 18 | import io.zenoh.bytes.Encoding 19 | import io.zenoh.bytes.IntoZBytes 20 | import io.zenoh.bytes.into 21 | import io.zenoh.config.ZenohId 22 | import io.zenoh.exceptions.ZError 23 | import io.zenoh.handlers.Callback 24 | import io.zenoh.handlers.Handler 25 | import io.zenoh.jni.callbacks.JNIGetCallback 26 | import io.zenoh.jni.callbacks.JNIOnCloseCallback 27 | import io.zenoh.keyexpr.KeyExpr 28 | import io.zenoh.qos.CongestionControl 29 | import io.zenoh.qos.Priority 30 | import io.zenoh.qos.QoS 31 | import io.zenoh.query.Parameters 32 | import io.zenoh.query.Querier 33 | import io.zenoh.query.Reply 34 | import io.zenoh.sample.Sample 35 | import io.zenoh.sample.SampleKind 36 | import org.apache.commons.net.ntp.TimeStamp 37 | 38 | internal class JNIQuerier(val ptr: Long) { 39 | 40 | @OptIn(Unstable::class) 41 | @Throws(ZError::class) 42 | fun performGetWithCallback(keyExpr: KeyExpr, callback: Callback, options: Querier.GetOptions) { 43 | performGet(keyExpr, options.parameters, callback, fun() {}, Unit, options.attachment, options.payload, options.encoding) 44 | } 45 | 46 | @OptIn(Unstable::class) 47 | @Throws(ZError::class) 48 | fun performGetWithHandler(keyExpr: KeyExpr, handler: Handler, options: Querier.GetOptions): R { 49 | return performGet(keyExpr, options.parameters, handler::handle, handler::onClose, handler.receiver(), options.attachment, options.payload, options.encoding) 50 | } 51 | 52 | @Throws(ZError::class) 53 | private fun performGet( 54 | keyExpr: KeyExpr, 55 | parameters: Parameters?, 56 | callback: Callback, 57 | onClose: () -> Unit, 58 | receiver: R, 59 | attachment: IntoZBytes?, 60 | payload: IntoZBytes?, 61 | encoding: Encoding? 62 | ): R { 63 | val getCallback = JNIGetCallback { 64 | replierId: ByteArray?, 65 | success: Boolean, 66 | keyExpr2: String?, 67 | payload2: ByteArray, 68 | encodingId: Int, 69 | encodingSchema: String?, 70 | kind: Int, 71 | timestampNTP64: Long, 72 | timestampIsValid: Boolean, 73 | attachmentBytes: ByteArray?, 74 | express: Boolean, 75 | priority: Int, 76 | congestionControl: Int, 77 | -> 78 | val reply: Reply 79 | if (success) { 80 | val timestamp = if (timestampIsValid) TimeStamp(timestampNTP64) else null 81 | val sample = Sample( 82 | KeyExpr(keyExpr2!!, null), 83 | payload2.into(), 84 | Encoding(encodingId, schema = encodingSchema), 85 | SampleKind.fromInt(kind), 86 | timestamp, 87 | QoS(CongestionControl.fromInt(congestionControl), Priority.fromInt(priority), express), 88 | attachmentBytes?.into() 89 | ) 90 | reply = Reply.Success(replierId?.let { ZenohId(it) }, sample) 91 | } else { 92 | reply = Reply.Error( 93 | replierId?.let { ZenohId(it) }, 94 | payload2.into(), 95 | Encoding(encodingId, schema = encodingSchema) 96 | ) 97 | } 98 | callback.run(reply) 99 | } 100 | 101 | getViaJNI(this.ptr, 102 | keyExpr.jniKeyExpr?.ptr ?: 0, 103 | keyExpr.keyExpr, 104 | parameters?.toString(), 105 | getCallback, 106 | onClose, 107 | attachment?.into()?.bytes, 108 | payload?.into()?.bytes, 109 | encoding?.id ?: Encoding.defaultEncoding().id, 110 | encoding?.schema 111 | ) 112 | return receiver 113 | } 114 | 115 | fun close() { 116 | freePtrViaJNI(ptr) 117 | } 118 | 119 | @Throws(ZError::class) 120 | private external fun getViaJNI( 121 | querierPtr: Long, 122 | keyExprPtr: Long, 123 | keyExprString: String, 124 | parameters: String?, 125 | callback: JNIGetCallback, 126 | onClose: JNIOnCloseCallback, 127 | attachmentBytes: ByteArray?, 128 | payload: ByteArray?, 129 | encodingId: Int, 130 | encodingSchema: String?, 131 | ) 132 | 133 | private external fun freePtrViaJNI(ptr: Long) 134 | 135 | } 136 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/JNIQuery.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni 16 | 17 | import io.zenoh.exceptions.ZError 18 | import io.zenoh.keyexpr.KeyExpr 19 | import io.zenoh.bytes.Encoding 20 | import io.zenoh.qos.QoS 21 | import io.zenoh.bytes.IntoZBytes 22 | import io.zenoh.sample.Sample 23 | import org.apache.commons.net.ntp.TimeStamp 24 | 25 | /** 26 | * Adapter class for interacting with a Query using JNI. 27 | * 28 | * This class serves as an adapter for interacting with a Query through JNI (Java Native Interface). 29 | * 30 | * @property ptr The raw pointer to the underlying native query. 31 | */ 32 | internal class JNIQuery(private val ptr: Long) { 33 | 34 | fun replySuccess(sample: Sample) { 35 | val timestampEnabled = sample.timestamp != null 36 | replySuccessViaJNI( 37 | ptr, 38 | sample.keyExpr.jniKeyExpr?.ptr ?: 0, 39 | sample.keyExpr.keyExpr, 40 | sample.payload.bytes, 41 | sample.encoding.id, 42 | sample.encoding.schema, 43 | timestampEnabled, 44 | if (timestampEnabled) sample.timestamp!!.ntpValue() else 0, 45 | sample.attachment?.bytes, 46 | sample.qos.express, 47 | sample.qos.priority.value, 48 | sample.qos.congestionControl.value 49 | ) 50 | } 51 | 52 | fun replyError(error: IntoZBytes, encoding: Encoding) { 53 | replyErrorViaJNI(ptr, error.into().bytes, encoding.id, encoding.schema) 54 | } 55 | 56 | fun replyDelete(keyExpr: KeyExpr, timestamp: TimeStamp?, attachment: IntoZBytes?, qos: QoS) { 57 | val timestampEnabled = timestamp != null 58 | replyDeleteViaJNI( 59 | ptr, 60 | keyExpr.jniKeyExpr?.ptr ?: 0, 61 | keyExpr.keyExpr, 62 | timestampEnabled, 63 | if (timestampEnabled) timestamp!!.ntpValue() else 0, 64 | attachment?.into()?.bytes, 65 | qos.express, 66 | qos.priority.value, 67 | qos.congestionControl.value 68 | ) 69 | } 70 | 71 | fun close() { 72 | freePtrViaJNI(ptr) 73 | } 74 | 75 | @Throws(ZError::class) 76 | private external fun replySuccessViaJNI( 77 | queryPtr: Long, 78 | keyExprPtr: Long, 79 | keyExprString: String, 80 | valuePayload: ByteArray, 81 | valueEncodingId: Int, 82 | valueEncodingSchema: String?, 83 | timestampEnabled: Boolean, 84 | timestampNtp64: Long, 85 | attachment: ByteArray?, 86 | qosExpress: Boolean, 87 | qosPriority: Int, 88 | qosCongestionControl: Int, 89 | ) 90 | 91 | @Throws(ZError::class) 92 | private external fun replyErrorViaJNI( 93 | queryPtr: Long, 94 | errorValuePayload: ByteArray, 95 | errorValueEncoding: Int, 96 | encodingSchema: String?, 97 | ) 98 | 99 | @Throws(ZError::class) 100 | private external fun replyDeleteViaJNI( 101 | queryPtr: Long, 102 | keyExprPtr: Long, 103 | keyExprString: String, 104 | timestampEnabled: Boolean, 105 | timestampNtp64: Long, 106 | attachment: ByteArray?, 107 | qosExpress: Boolean, 108 | qosPriority: Int, 109 | qosCongestionControl: Int, 110 | ) 111 | 112 | /** Frees the underlying native Query. */ 113 | private external fun freePtrViaJNI(ptr: Long) 114 | } 115 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/JNIQueryable.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni 16 | 17 | /** 18 | * Adapter class to handle the interactions with Zenoh through JNI for a [io.zenoh.query.Queryable] 19 | * 20 | * @property ptr: raw pointer to the underlying native Queryable. 21 | */ 22 | internal class JNIQueryable(val ptr: Long) { 23 | 24 | fun close() { 25 | freePtrViaJNI(ptr) 26 | } 27 | 28 | /** Frees the underlying native Queryable. */ 29 | private external fun freePtrViaJNI(ptr: Long) 30 | } 31 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/JNIScout.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni 16 | 17 | import io.zenoh.Config 18 | import io.zenoh.ZenohLoad 19 | import io.zenoh.exceptions.ZError 20 | import io.zenoh.handlers.Callback 21 | import io.zenoh.jni.callbacks.JNIScoutCallback 22 | import io.zenoh.config.ZenohId 23 | import io.zenoh.scouting.Hello 24 | import io.zenoh.config.WhatAmI 25 | import io.zenoh.jni.callbacks.JNIOnCloseCallback 26 | import io.zenoh.scouting.CallbackScout 27 | import io.zenoh.scouting.HandlerScout 28 | 29 | /** 30 | * Adapter class to handle the interactions with Zenoh through JNI for a [io.zenoh.scouting.Scout] 31 | * 32 | * @property ptr: raw pointer to the underlying native scout. 33 | */ 34 | internal class JNIScout(private val ptr: Long) { 35 | 36 | companion object { 37 | 38 | init { 39 | ZenohLoad 40 | } 41 | 42 | @Throws(ZError::class) 43 | fun scoutWithHandler( 44 | whatAmI: Set, 45 | callback: Callback, 46 | onClose: () -> Unit, 47 | config: Config?, 48 | receiver: R 49 | ): HandlerScout { 50 | val scoutCallback = JNIScoutCallback { whatAmI2: Int, id: ByteArray, locators: List -> 51 | callback.run(Hello(WhatAmI.fromInt(whatAmI2), ZenohId(id), locators)) 52 | } 53 | val binaryWhatAmI: Int = whatAmI.map { it.value }.reduce { acc, it -> acc or it } 54 | val ptr = scoutViaJNI(binaryWhatAmI, scoutCallback, onClose,config?.jniConfig?.ptr ?: 0) 55 | return HandlerScout(JNIScout(ptr), receiver) 56 | } 57 | 58 | @Throws(ZError::class) 59 | fun scoutWithCallback( 60 | whatAmI: Set, 61 | callback: Callback, 62 | config: Config?, 63 | ): CallbackScout { 64 | val scoutCallback = JNIScoutCallback { whatAmI2: Int, id: ByteArray, locators: List -> 65 | callback.run(Hello(WhatAmI.fromInt(whatAmI2), ZenohId(id), locators)) 66 | } 67 | val binaryWhatAmI: Int = whatAmI.map { it.value }.reduce { acc, it -> acc or it } 68 | val ptr = scoutViaJNI(binaryWhatAmI, scoutCallback, fun() {},config?.jniConfig?.ptr ?: 0) 69 | return CallbackScout(JNIScout(ptr)) 70 | } 71 | 72 | @Throws(ZError::class) 73 | private external fun scoutViaJNI( 74 | whatAmI: Int, 75 | callback: JNIScoutCallback, 76 | onClose: JNIOnCloseCallback, 77 | configPtr: Long, 78 | ): Long 79 | 80 | @Throws(ZError::class) 81 | external fun freePtrViaJNI(ptr: Long) 82 | } 83 | 84 | fun close() { 85 | freePtrViaJNI(ptr) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/JNISubscriber.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni 16 | 17 | /** 18 | * Adapter class to handle the interactions with Zenoh through JNI for a [io.zenoh.pubsub.Subscriber] 19 | * 20 | * @property ptr: raw pointer to the underlying native Subscriber. 21 | */ 22 | internal class JNISubscriber(private val ptr: Long) { 23 | 24 | fun close() { 25 | freePtrViaJNI(ptr) 26 | } 27 | 28 | /** Frees the underlying native Subscriber. */ 29 | private external fun freePtrViaJNI(ptr: Long) 30 | 31 | } 32 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/JNIZBytes.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni 16 | 17 | import io.zenoh.ZenohLoad 18 | import io.zenoh.bytes.ZBytes 19 | import java.lang.reflect.Type 20 | 21 | @PublishedApi 22 | internal object JNIZBytes { 23 | 24 | init { 25 | ZenohLoad 26 | } 27 | 28 | @JvmStatic 29 | external fun serializeViaJNI(any: Any, type: Type): ZBytes 30 | 31 | @JvmStatic 32 | external fun deserializeViaJNI(zBytes: ZBytes, type: Type): Any 33 | } 34 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/JNIZenohId.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni 16 | 17 | import io.zenoh.ZenohLoad 18 | 19 | internal object JNIZenohId { 20 | 21 | init { 22 | ZenohLoad 23 | } 24 | 25 | external fun toStringViaJNI(bytes: ByteArray): String 26 | 27 | } 28 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/callbacks/JNIGetCallback.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni.callbacks 16 | 17 | internal fun interface JNIGetCallback { 18 | 19 | fun run( 20 | replierId: ByteArray?, 21 | success: Boolean, 22 | keyExpr: String?, 23 | payload: ByteArray, 24 | encodingId: Int, 25 | encodingSchema: String?, 26 | kind: Int, 27 | timestampNTP64: Long, 28 | timestampIsValid: Boolean, 29 | attachment: ByteArray?, 30 | express: Boolean, 31 | priority: Int, 32 | congestionControl: Int, 33 | ) 34 | } 35 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/callbacks/JNIOnCloseCallback.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni.callbacks 16 | 17 | internal fun interface JNIOnCloseCallback { 18 | 19 | fun run() 20 | 21 | } 22 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/callbacks/JNIQueryableCallback.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni.callbacks 16 | 17 | internal fun interface JNIQueryableCallback { 18 | fun run(keyExpr: String, 19 | selectorParams: String, 20 | payload: ByteArray?, 21 | encodingId: Int, 22 | encodingSchema: String?, 23 | attachmentBytes: ByteArray?, 24 | queryPtr: Long) 25 | } 26 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/callbacks/JNIScoutCallback.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni.callbacks 16 | 17 | internal fun interface JNIScoutCallback { 18 | 19 | fun run(whatAmI: Int, zid: ByteArray, locators: List) 20 | } 21 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/jni/callbacks/JNISubscriberCallback.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.jni.callbacks 16 | 17 | internal fun interface JNISubscriberCallback { 18 | fun run( 19 | keyExpr: String, 20 | payload: ByteArray, 21 | encodingId: Int, 22 | encodingSchema: String?, 23 | kind: Int, 24 | timestampNTP64: Long, 25 | timestampIsValid: Boolean, 26 | attachment: ByteArray?, 27 | express: Boolean, 28 | priority: Int, 29 | congestionControl: Int, 30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/keyexpr/SetIntersectionLevel.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.keyexpr 16 | 17 | /** 18 | * The possible relations between two sets. 19 | * 20 | * Note that [EQUALS] implies [INCLUDES], which itself implies [INTERSECTS]. 21 | */ 22 | enum class SetIntersectionLevel(internal val value: Int) { 23 | DISJOINT(0), 24 | INTERSECTS(1), 25 | INCLUDES(2), 26 | EQUALS(3); 27 | 28 | companion object { 29 | internal fun fromInt(value: Int) = SetIntersectionLevel.entries.first { it.value == value } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/liveliness/LivelinessToken.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.liveliness 16 | 17 | import io.zenoh.jni.JNILivelinessToken 18 | import io.zenoh.session.SessionDeclaration 19 | 20 | /** 21 | * A token whose liveliness is tied to the Zenoh [io.zenoh.Session]. 22 | * 23 | * A declared liveliness token will be seen as alive by any other Zenoh 24 | * application in the system that monitors it while the liveliness token 25 | * is not undeclared or dropped, while the Zenoh application that declared 26 | * it is alive (didn't stop or crashed) and while the Zenoh application 27 | * that declared the token has Zenoh connectivity with the Zenoh application 28 | * that monitors it. 29 | * 30 | * Liveliness tokens are automatically undeclared when dropped. 31 | */ 32 | class LivelinessToken internal constructor(private var jniLivelinessToken: JNILivelinessToken?): SessionDeclaration, AutoCloseable { 33 | 34 | /** 35 | * Undeclares the token. 36 | */ 37 | override fun undeclare() { 38 | jniLivelinessToken?.undeclare() 39 | jniLivelinessToken = null 40 | } 41 | 42 | /** 43 | * Closes the token. This function is equivalent to [undeclare]. 44 | * When using try-with-resources, this function is called automatically. 45 | */ 46 | override fun close() { 47 | undeclare() 48 | } 49 | 50 | protected fun finalize() { 51 | undeclare() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/pubsub/DeleteOptions.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.pubsub 16 | 17 | import io.zenoh.bytes.IntoZBytes 18 | import io.zenoh.bytes.ZBytes 19 | import io.zenoh.qos.CongestionControl 20 | import io.zenoh.qos.Priority 21 | import io.zenoh.qos.QoS 22 | import io.zenoh.qos.Reliability 23 | 24 | /** 25 | * Options for delete operations. 26 | * 27 | * @param reliability The [Reliability] desired. 28 | * @param attachment Optional attachment for the delete operation. 29 | * @property express [QoS] express value. 30 | * @property congestionControl The congestion control policy. 31 | * @property priority The priority policy. 32 | */ 33 | data class DeleteOptions( 34 | var reliability: Reliability = Reliability.RELIABLE, 35 | var attachment: IntoZBytes? = null, 36 | var express: Boolean = QoS.defaultPush.express, 37 | var congestionControl: CongestionControl = QoS.defaultPush.congestionControl, 38 | var priority: Priority = QoS.defaultPush.priority 39 | ) { 40 | fun setAttachment(attachment: String) = apply { this.attachment = ZBytes.from(attachment) } 41 | } 42 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/pubsub/Publisher.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.pubsub 16 | 17 | import io.zenoh.* 18 | import io.zenoh.bytes.Encoding 19 | import io.zenoh.bytes.IntoZBytes 20 | import io.zenoh.bytes.ZBytes 21 | import io.zenoh.exceptions.ZError 22 | import io.zenoh.jni.JNIPublisher 23 | import io.zenoh.keyexpr.KeyExpr 24 | import io.zenoh.qos.CongestionControl 25 | import io.zenoh.qos.Priority 26 | import io.zenoh.session.SessionDeclaration 27 | import kotlin.Throws 28 | 29 | /** 30 | * A Zenoh Publisher. 31 | * 32 | * A publisher is automatically dropped when using it with the 'try-with-resources' statement (i.e. 'use' in Kotlin). 33 | * The session from which it was declared will also keep a reference to it and undeclare it once the session is closed. 34 | * 35 | * In order to declare a publisher, [Session.declarePublisher] must be called. 36 | * 37 | * Example: 38 | * ```java 39 | * try (Session session = Session.open()) { 40 | * try (KeyExpr keyExpr = KeyExpr.tryFrom("demo/java/greeting")) { 41 | * System.out.println("Declaring publisher on '" + keyExpr + "'..."); 42 | * try (Publisher publisher = session.declarePublisher(keyExpr)) { 43 | * int i = 0; 44 | * while (true) { 45 | * publisher.put("Hello for the " + i + "th time!"); 46 | * Thread.sleep(1000); 47 | * i++; 48 | * } 49 | * } 50 | * } 51 | * } catch (ZError | InterruptedException e) { 52 | * System.out.println("Error: " + e); 53 | * } 54 | * ``` 55 | * 56 | * The publisher configuration parameters can be later changed using the setter functions. 57 | * 58 | * @property keyExpr The key expression the publisher will be associated to. 59 | * @property encoding The encoding user by the publisher. 60 | */ 61 | class Publisher internal constructor( 62 | val keyExpr: KeyExpr, 63 | private var congestionControl: CongestionControl, 64 | private var priority: Priority, 65 | val encoding: Encoding, 66 | private var jniPublisher: JNIPublisher?, 67 | ) : SessionDeclaration, AutoCloseable { 68 | 69 | companion object { 70 | private val publisherNotValid = ZError("Publisher is not valid.") 71 | } 72 | 73 | /** Get the congestion control applied when routing the data. */ 74 | fun congestionControl() = congestionControl 75 | 76 | /** Get the priority of the written data. */ 77 | fun priority() = priority 78 | 79 | /** Performs a PUT operation on the specified [keyExpr] with the specified [payload]. */ 80 | @Throws(ZError::class) 81 | fun put(payload: IntoZBytes) { 82 | jniPublisher?.put(payload, encoding, null) ?: throw publisherNotValid 83 | } 84 | 85 | /** Performs a PUT operation on the specified [keyExpr] with the specified [payload]. */ 86 | @Throws(ZError::class) 87 | fun put(payload: IntoZBytes, options: PutOptions) { 88 | jniPublisher?.put(payload, options.encoding ?: this.encoding, options.attachment) ?: throw publisherNotValid 89 | } 90 | 91 | /** Performs a PUT operation on the specified [keyExpr] with the specified [payload]. */ 92 | @Throws(ZError::class) 93 | fun put(payload: String) = put(ZBytes.from(payload)) 94 | 95 | /** Performs a PUT operation on the specified [keyExpr] with the specified [payload]. */ 96 | @Throws(ZError::class) 97 | fun put(payload: String, options: PutOptions) = put(ZBytes.from(payload), options) 98 | 99 | /** 100 | * Performs a DELETE operation on the specified [keyExpr] 101 | */ 102 | @JvmOverloads 103 | @Throws(ZError::class) 104 | fun delete(options: DeleteOptions = DeleteOptions()) { 105 | jniPublisher?.delete(options.attachment) ?: throw(publisherNotValid) 106 | } 107 | 108 | /** 109 | * Returns `true` if the publisher is still running. 110 | */ 111 | fun isValid(): Boolean { 112 | return jniPublisher != null 113 | } 114 | 115 | override fun close() { 116 | undeclare() 117 | } 118 | 119 | override fun undeclare() { 120 | jniPublisher?.close() 121 | jniPublisher = null 122 | } 123 | 124 | @Suppress("removal") 125 | protected fun finalize() { 126 | jniPublisher?.close() 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/pubsub/PublisherOptions.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.pubsub 16 | 17 | import io.zenoh.bytes.Encoding 18 | import io.zenoh.qos.* 19 | 20 | /** 21 | * Options for the publisher. 22 | * 23 | * @param reliability The desired reliability. 24 | * @param encoding The encoding of the payload. 25 | * @property express [QoS] express value. 26 | * @property congestionControl The congestion control policy. 27 | * @property priority The priority policy. 28 | */ 29 | data class PublisherOptions(var reliability: Reliability = Reliability.RELIABLE, 30 | var encoding: Encoding = Encoding.defaultEncoding(), 31 | var express: Boolean = QoS.defaultPush.express, 32 | var congestionControl: CongestionControl = QoS.defaultPush.congestionControl, 33 | var priority: Priority = QoS.defaultPush.priority) 34 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/pubsub/PutOptions.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.pubsub 16 | 17 | import io.zenoh.bytes.Encoding 18 | import io.zenoh.bytes.IntoZBytes 19 | import io.zenoh.bytes.ZBytes 20 | import io.zenoh.qos.* 21 | 22 | /** 23 | * Options for the PUT operations. 24 | * 25 | * @param encoding The encoding of the payload. 26 | * @param reliability The desired reliability. 27 | * @param attachment Optional attachment. 28 | * @property express [QoS] express value. 29 | * @property congestionControl The congestion control policy. 30 | * @property priority The priority policy. 31 | */ 32 | data class PutOptions( 33 | var encoding: Encoding? = null, 34 | var reliability: Reliability = Reliability.RELIABLE, 35 | var attachment: IntoZBytes? = null, 36 | var express: Boolean = QoS.defaultPush.express, 37 | var congestionControl: CongestionControl = QoS.defaultPush.congestionControl, 38 | var priority: Priority = QoS.defaultPush.priority 39 | ) { 40 | fun setAttachment(attachment: String) = apply { this.attachment = ZBytes.from(attachment) } 41 | } 42 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/pubsub/Subscriber.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.pubsub 16 | 17 | import io.zenoh.handlers.BlockingQueueHandler 18 | import io.zenoh.jni.JNISubscriber 19 | import io.zenoh.keyexpr.KeyExpr 20 | import io.zenoh.session.SessionDeclaration 21 | 22 | /** 23 | * A subscriber that allows listening to updates on a key expression and reacting to changes. 24 | * 25 | * Its main purpose is to keep the subscription active as long as it exists. 26 | * 27 | * Example using the default [BlockingQueueHandler] handler: 28 | * 29 | * ```java 30 | * var queue = session.declareSubscriber("a/b/c"); 31 | * try (Session session = Zenoh.open(config)) { 32 | * try (var subscriber = session.declareSubscriber(keyExpr)) { 33 | * var receiver = subscriber.getReceiver(); 34 | * assert receiver != null; 35 | * while (true) { 36 | * Optional wrapper = receiver.take(); 37 | * if (wrapper.isEmpty()) { 38 | * break; 39 | * } 40 | * System.out.println(wrapper.get()); 41 | * } 42 | * } 43 | * } 44 | * ``` 45 | * 46 | * Example using a callback: 47 | * ```java 48 | * try (Session session = Zenoh.open(config)) { 49 | * session.declareSubscriber(keyExpr, System.out::println); 50 | * } 51 | * ``` 52 | * 53 | * Example using a handler: 54 | * ```java 55 | * class MyHandler implements Handler> {...} 56 | * 57 | * //... 58 | * try (Session session = Zenoh.open(config)) { 59 | * var handler = new MyHandler(); 60 | * var arraylist = session.declareSubscriber(keyExpr, handler); 61 | * // ... 62 | * } 63 | * ``` 64 | */ 65 | sealed class Subscriber( 66 | val keyExpr: KeyExpr, private var jniSubscriber: JNISubscriber? 67 | ) : AutoCloseable, SessionDeclaration { 68 | 69 | fun isValid(): Boolean { 70 | return jniSubscriber != null 71 | } 72 | 73 | override fun undeclare() { 74 | jniSubscriber?.close() 75 | jniSubscriber = null 76 | } 77 | 78 | override fun close() { 79 | undeclare() 80 | } 81 | 82 | protected fun finalize() { 83 | jniSubscriber?.close() 84 | } 85 | } 86 | 87 | /** 88 | * Subscriber using a callback to handle incoming samples. 89 | * 90 | * Example: 91 | * ```java 92 | * try (Session session = Zenoh.open(config)) { 93 | * session.declareSubscriber(keyExpr, System.out::println); 94 | * } 95 | * ``` 96 | */ 97 | class CallbackSubscriber internal constructor(keyExpr: KeyExpr, jniSubscriber: JNISubscriber?): Subscriber(keyExpr, jniSubscriber) 98 | 99 | /** 100 | * Subscriber using a [io.zenoh.handlers.Handler] for handling incoming samples. 101 | * 102 | * Example using the default handler: 103 | * ```java 104 | * try (Session session = Zenoh.open(config)) { 105 | * try (HandlerSubscriber>> subscriber = session.declareSubscriber(keyExpr)) { 106 | * BlockingQueue> receiver = subscriber.getReceiver(); 107 | * assert receiver != null; 108 | * while (true) { 109 | * Optional wrapper = receiver.take(); 110 | * if (wrapper.isEmpty()) { 111 | * break; 112 | * } 113 | * System.out.println(wrapper.get()); 114 | * } 115 | * } 116 | * } 117 | * ``` 118 | * 119 | * @param R The type of the receiver. 120 | * @param receiver The receiver of the subscriber's handler. 121 | */ 122 | class HandlerSubscriber internal constructor(keyExpr: KeyExpr, jniSubscriber: JNISubscriber?, val receiver: R): Subscriber(keyExpr, jniSubscriber) 123 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/qos/CongestionControl.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.qos 16 | 17 | /** The congestion control to be applied when routing the data. */ 18 | enum class CongestionControl (val value: Int) { 19 | 20 | /** 21 | * Allows the message to be dropped if all buffers are full. 22 | */ 23 | DROP(0), 24 | 25 | /** 26 | * Prevents the message from being dropped at all cost. 27 | * In the face of heavy congestion on a part of the network, this could result in your publisher node blocking. 28 | */ 29 | BLOCK(1); 30 | 31 | companion object { 32 | fun fromInt(value: Int) = entries.first { it.value == value } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/qos/Priority.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.qos 16 | 17 | /** 18 | * The Priority of Zenoh messages. 19 | * 20 | * A Priority is identified by a numeric value. Lower the value, higher the priority. Higher the value, lower the priority. 21 | * 22 | * - Highest priority: 1 ([REALTIME]) 23 | * - Lowest priority: 7 ([BACKGROUND]) 24 | */ 25 | enum class Priority(val value: Int) { 26 | REALTIME(1), 27 | INTERACTIVE_HIGH(2), 28 | INTERACTIVE_LOW(3), 29 | DATA_HIGH(4), 30 | DATA(5), 31 | DATA_LOW(6), 32 | BACKGROUND(7); 33 | 34 | companion object { 35 | fun fromInt(value: Int) = entries.first { it.value == value } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/qos/QoS.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.qos 16 | 17 | /** 18 | * Quality of service settings used to send zenoh message. 19 | * 20 | * @property congestionControl [CongestionControl] policy used for the message. 21 | * @property priority [Priority] policy used for the message. 22 | * @property express If true, the message is not batched in order to reduce the latency. 23 | */ 24 | data class QoS ( 25 | var congestionControl: CongestionControl = CongestionControl.DROP, 26 | var priority: Priority = Priority.DATA, 27 | var express: Boolean = false 28 | ) { 29 | 30 | companion object { 31 | internal val defaultPush = QoS(CongestionControl.DROP, Priority.DATA, false) 32 | internal val defaultRequest = QoS(CongestionControl.BLOCK, Priority.DATA, false) 33 | internal val defaultResponse = QoS(CongestionControl.BLOCK, Priority.DATA, false) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/qos/Reliability.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.qos 16 | 17 | /** 18 | * The reliability policy. 19 | * 20 | * Used by subscribers to inform the network of the reliability it wishes to obtain. 21 | */ 22 | enum class Reliability { 23 | /** 24 | * Best Effort 25 | * 26 | * Informs the network that dropping some messages is acceptable. 27 | */ 28 | BEST_EFFORT, 29 | 30 | /** 31 | * Reliable 32 | * 33 | * Informs the network that this subscriber wishes for all publications to reliably reach it. 34 | * 35 | * Note that if a publisher puts a sample with the [io.zenoh.prelude.CongestionControl.DROP] option, 36 | * this reliability requirement may be infringed to prevent slow readers from blocking the network. 37 | */ 38 | RELIABLE, 39 | } 40 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/query/ConsolidationMode.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.query 16 | 17 | /** The kind of consolidation. */ 18 | enum class ConsolidationMode { 19 | /** Apply automatic consolidation based on queryable's preferences. */ 20 | AUTO, 21 | 22 | /** No consolidation applied: multiple samples may be received for the same key-timestamp.*/ 23 | NONE, 24 | 25 | /** 26 | * Monotonic consolidation immediately forwards samples, except if one with an equal or more recent timestamp 27 | * has already been sent with the same key. 28 | * 29 | * This optimizes latency while potentially reducing bandwidth. 30 | * 31 | * Note that this doesn't cause re-ordering, but drops the samples for which a more recent timestamp has already 32 | * been observed with the same key. 33 | */ 34 | MONOTONIC, 35 | 36 | /** Holds back samples to only send the set of samples that had the highest timestamp for their key. */ 37 | LATEST; 38 | } 39 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/query/Get.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.query 16 | 17 | import io.zenoh.bytes.Encoding 18 | import io.zenoh.bytes.IntoZBytes 19 | import io.zenoh.bytes.ZBytes 20 | import io.zenoh.qos.QoS 21 | import java.time.Duration 22 | 23 | /** 24 | * Get to query data from the matching queryables in the system. 25 | * 26 | * @param timeout Timeout of the query. 27 | * @param target The [QueryTarget] of the query. 28 | * @param consolidation The [ConsolidationMode] of the query. 29 | * @param payload Optional payload. 30 | * @param encoding Encoding of the payload. 31 | * @param attachment Optional attachment. 32 | * @param qos The intended [QoS] for the query. 33 | */ 34 | data class GetOptions( 35 | var timeout: Duration = Duration.ofMillis(10000), 36 | var target: QueryTarget = QueryTarget.BEST_MATCHING, 37 | var consolidation: ConsolidationMode = ConsolidationMode.AUTO, 38 | var payload: IntoZBytes? = null, 39 | var encoding: Encoding? = null, 40 | var attachment: IntoZBytes? = null, 41 | var qos: QoS = QoS.defaultRequest 42 | ) { 43 | fun setPayload(payload: String) = apply { this.payload = ZBytes.from(payload) } 44 | fun setAttachment(attachment: String) = apply { this.attachment = ZBytes.from(attachment) } 45 | } 46 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/query/QueryTarget.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.query 16 | 17 | /** The Queryables that should be targeted by a GET operation. */ 18 | enum class QueryTarget { 19 | 20 | /** 21 | * Best Matching: the nearest complete queryable if any else all matching queryables. 22 | */ 23 | BEST_MATCHING, 24 | 25 | /** 26 | * All matching queryables. 27 | */ 28 | ALL, 29 | 30 | /** 31 | * All Complete queryables. 32 | */ 33 | ALL_COMPLETE; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/query/Queryable.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.query 16 | 17 | import io.zenoh.handlers.BlockingQueueHandler 18 | import io.zenoh.handlers.Handler 19 | import io.zenoh.jni.JNIQueryable 20 | import io.zenoh.keyexpr.KeyExpr 21 | import io.zenoh.session.SessionDeclaration 22 | 23 | /** 24 | * A queryable that allows to perform multiple queries on the specified [KeyExpr]. 25 | * 26 | * Its main purpose is to keep the queryable active as long as it exists. 27 | * 28 | * Example using the default [BlockingQueueHandler] handler: 29 | * ```java 30 | * try (Session session = Zenoh.open(config)) { 31 | * var queryable = session.declareQueryable(keyExpr); 32 | * BlockingQueue> receiver = queryable.getReceiver(); 33 | * assert receiver != null; 34 | * while (true) { 35 | * Optional wrapper = receiver.take(); 36 | * if (wrapper.isEmpty()) { 37 | * break; 38 | * } 39 | * Query query = wrapper.get(); 40 | * query.reply(query.getKeyExpr(), "Example reply"); 41 | * } 42 | * } 43 | * ``` 44 | * 45 | * Example using a [io.zenoh.handlers.Callback]: 46 | * ```java 47 | * try (Session session = Zenoh.open(config)) { 48 | * var queryable = session.declareQueryable(keyExpr, query -> query.reply(query.getKeyExpr(), "Example reply"); 49 | * } 50 | * ``` 51 | * 52 | * @property keyExpr The [KeyExpr] to which the subscriber is associated. 53 | * @property jniQueryable Delegate object in charge of communicating with the underlying native code. 54 | * @see CallbackQueryable 55 | * @see HandlerQueryable 56 | */ 57 | sealed class Queryable( 58 | val keyExpr: KeyExpr, private var jniQueryable: JNIQueryable? 59 | ) : AutoCloseable, SessionDeclaration { 60 | 61 | fun isValid(): Boolean { 62 | return jniQueryable != null 63 | } 64 | 65 | /** 66 | * Undeclares the queryable. 67 | */ 68 | override fun undeclare() { 69 | jniQueryable?.close() 70 | jniQueryable = null 71 | } 72 | 73 | /** 74 | * Closes the queryable, equivalent to [undeclare]. This function is automatically called 75 | * when using try with resources. 76 | */ 77 | override fun close() { 78 | undeclare() 79 | } 80 | 81 | protected fun finalize() { 82 | jniQueryable?.close() 83 | } 84 | } 85 | 86 | /** 87 | * [Queryable] receiving replies through a callback. 88 | * 89 | * Example 90 | * ```java 91 | * try (Session session = Zenoh.open(config)) { 92 | * CallbackQueryable queryable = session.declareQueryable(keyExpr, query -> query.reply(query.getKeyExpr(), "Example reply"); 93 | * } 94 | * ``` 95 | */ 96 | class CallbackQueryable internal constructor(keyExpr: KeyExpr, jniQueryable: JNIQueryable?): Queryable(keyExpr, jniQueryable) 97 | 98 | /** 99 | * [Queryable] receiving replies through a [Handler]. 100 | * 101 | * Example using the default receiver: 102 | * ```java 103 | * try (Session session = Zenoh.open(config)) { 104 | * Queryable>> queryable = session.declareQueryable(keyExpr); 105 | * BlockingQueue> receiver = queryable.getReceiver(); 106 | * while (true) { 107 | * Optional wrapper = receiver.take(); 108 | * if (wrapper.isEmpty()) { 109 | * break; 110 | * } 111 | * Query query = wrapper.get(); 112 | * query.reply(query.getKeyExpr(), "Example reply"); 113 | * } 114 | * } 115 | * ``` 116 | * 117 | * @param R The type of the handler's receiver. 118 | * @param receiver The receiver of the queryable's handler. 119 | */ 120 | class HandlerQueryable internal constructor(keyExpr: KeyExpr, jniQueryable: JNIQueryable?, val receiver: R): Queryable(keyExpr, jniQueryable) 121 | 122 | /** 123 | * Options for configuring a [Queryable]. 124 | * 125 | * @param complete The completeness of the information the queryable provides. 126 | */ 127 | data class QueryableOptions(var complete: Boolean = false) 128 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/query/Reply.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.query 16 | 17 | import io.zenoh.ZenohType 18 | import io.zenoh.bytes.Encoding 19 | import io.zenoh.bytes.IntoZBytes 20 | import io.zenoh.bytes.ZBytes 21 | import io.zenoh.config.ZenohId 22 | import io.zenoh.sample.Sample 23 | import io.zenoh.qos.CongestionControl 24 | import io.zenoh.qos.Priority 25 | import io.zenoh.qos.QoS 26 | import org.apache.commons.net.ntp.TimeStamp 27 | 28 | /** 29 | * Class to represent a Zenoh Reply to a remote query. 30 | * 31 | * @property replierId: unique ID identifying the replier. 32 | * @see Success 33 | * @see Error 34 | */ 35 | sealed class Reply private constructor(val replierId: ZenohId?) : ZenohType { 36 | 37 | /** 38 | * A Success reply. 39 | */ 40 | class Success internal constructor(replierId: ZenohId?, val sample: Sample) : Reply(replierId) { 41 | 42 | override fun toString(): String { 43 | return "Success(sample=$sample)" 44 | } 45 | 46 | override fun equals(other: Any?): Boolean { 47 | if (this === other) return true 48 | if (other !is Success) return false 49 | return sample == other.sample 50 | } 51 | 52 | override fun hashCode(): Int { 53 | return sample.hashCode() 54 | } 55 | 56 | } 57 | 58 | /** 59 | * An Error reply. 60 | */ 61 | class Error internal constructor(replierId: ZenohId?, val error: ZBytes, val encoding: Encoding) : 62 | Reply(replierId) { 63 | 64 | override fun toString(): String { 65 | return "Error(error=$error)" 66 | } 67 | 68 | override fun equals(other: Any?): Boolean { 69 | if (this === other) return true 70 | if (other !is Error) return false 71 | 72 | return error == other.error 73 | } 74 | 75 | override fun hashCode(): Int { 76 | return error.hashCode() 77 | } 78 | } 79 | } 80 | 81 | /** 82 | * Options for performing a [Reply] to a [Query]. 83 | * 84 | * @param encoding [Encoding] of the payload of the reply. 85 | * @param timeStamp Optional timestamp. 86 | * @param attachment Optional attachment. 87 | * @property express [QoS] express value. 88 | * @property congestionControl The congestion control policy. 89 | * @property priority The priority policy. 90 | */ 91 | data class ReplyOptions( 92 | var encoding: Encoding = Encoding.defaultEncoding(), 93 | var timeStamp: TimeStamp? = null, 94 | var attachment: IntoZBytes? = null, 95 | var express: Boolean = QoS.defaultResponse.express, 96 | var congestionControl: CongestionControl = QoS.defaultResponse.congestionControl, 97 | var priority: Priority = QoS.defaultResponse.priority 98 | ) { 99 | fun setAttachment(attachment: String) = apply { this.attachment = ZBytes.from(attachment) } 100 | } 101 | 102 | /** 103 | * Options for performing a Reply Delete to a [Query]. 104 | * 105 | * @param timeStamp Optional timestamp. 106 | * @param attachment Optional attachment. 107 | * @property express [QoS] express value. 108 | * @property congestionControl The congestion control policy. 109 | * @property priority The priority policy. 110 | */ 111 | data class ReplyDelOptions( 112 | var timeStamp: TimeStamp? = null, 113 | var attachment: IntoZBytes? = null, 114 | var express: Boolean = QoS.defaultResponse.express, 115 | var congestionControl: CongestionControl = QoS.defaultResponse.congestionControl, 116 | var priority: Priority = QoS.defaultResponse.priority 117 | ) { 118 | fun setAttachment(attachment: String) = apply { this.attachment = ZBytes.from(attachment) } 119 | } 120 | 121 | 122 | /** 123 | * Options for performing a Reply Err to a [Query]. 124 | * 125 | * @param encoding The encoding of the error message. 126 | */ 127 | data class ReplyErrOptions(var encoding: Encoding = Encoding.defaultEncoding()) 128 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/query/Selector.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.query 16 | 17 | import io.zenoh.exceptions.ZError 18 | import io.zenoh.keyexpr.KeyExpr 19 | 20 | /** 21 | * A selector is the combination of a [KeyExpr], which defines the 22 | * set of keys that are relevant to an operation, and a set of parameters 23 | * with a few intended uses: 24 | * - specifying arguments to a queryable, allowing the passing of Remote Procedure Call parameters 25 | * - filtering by value, 26 | * - filtering by metadata, such as the timestamp of a value, 27 | * - specifying arguments to zenoh when using the REST API. 28 | * 29 | * When in string form, selectors look a lot like a URI, with similar semantics: 30 | * - the `key_expr` before the first `?` must be a valid key expression. 31 | * - the `parameters` after the first `?` should be encoded like the query section of a URL: 32 | * - parameters are separated by `;`, 33 | * - the parameter name and value are separated by the first `=`, 34 | * - in the absence of `=`, the parameter value is considered to be the empty string, 35 | * - both name and value should use percent-encoding to escape characters, 36 | * - defining a value for the same parameter name twice is considered undefined behavior, 37 | * with the encouraged behaviour being to reject operations when a duplicate parameter is detected. 38 | * 39 | * Zenoh intends to standardize the usage of a set of parameter names. To avoid conflicting with RPC parameters, 40 | * the Zenoh team has settled on reserving the set of parameter names that start with non-alphanumeric characters. 41 | * 42 | * The full specification for selectors is available [here](https://github.com/eclipse-zenoh/roadmap/tree/main/rfcs/ALL/Selectors), 43 | * it includes standardized parameters. 44 | * 45 | * Queryable implementers are encouraged to prefer these standardized parameter names when implementing their 46 | * associated features, and to prefix their own parameter names to avoid having conflicting parameter names with other 47 | * queryables. 48 | * 49 | * @property keyExpr The [KeyExpr] of the selector. 50 | * @property parameters The [Parameters] of the selector. 51 | */ 52 | data class Selector(val keyExpr: KeyExpr, val parameters: Parameters? = null) : AutoCloseable, IntoSelector { 53 | 54 | companion object { 55 | 56 | /** 57 | * Try from. 58 | * 59 | * The default way to construct a Selector. 60 | * 61 | * When in string form, selectors look a lot like a URI, with similar semantics: 62 | * - the `key_expr` before the first `?` must be a valid key expression. 63 | * - the `parameters` after the first `?` should be encoded like the query section of a URL: 64 | * - parameters are separated by `;`, 65 | * - the parameter name and value are separated by the first `=`, 66 | * - in the absence of `=`, the parameter value is considered to be the empty string, 67 | * - both name and value should use percent-encoding to escape characters, 68 | * - defining a value for the same parameter name twice is considered undefined behavior, 69 | * with the encouraged behaviour being to reject operations when a duplicate parameter is detected. 70 | * 71 | * @param selector The selector expression as a String. 72 | * @return An instance [Selector]. 73 | * @throws ZError in case of failure processing the selector. 74 | */ 75 | @Throws(ZError::class) 76 | @JvmStatic 77 | fun tryFrom(selector: String): Selector { 78 | if (selector.isEmpty()) { 79 | throw ZError("Attempting to create a selector from an empty string.") 80 | } 81 | val result = selector.split('?', limit = 2) 82 | val keyExpr = KeyExpr.autocanonize(result[0]) 83 | val params = if (result.size == 2) Parameters.from(result[1]) else null 84 | 85 | return Selector(keyExpr, params) 86 | } 87 | } 88 | 89 | override fun into(): Selector = this 90 | 91 | override fun toString(): String { 92 | return parameters?.let { "$keyExpr?$parameters" } ?: keyExpr.toString() 93 | } 94 | 95 | /** Closes the selector's [KeyExpr]. */ 96 | override fun close() { 97 | keyExpr.close() 98 | } 99 | } 100 | 101 | interface IntoSelector { 102 | fun into(): Selector 103 | } 104 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/sample/Sample.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.sample 16 | 17 | import io.zenoh.ZenohType 18 | import io.zenoh.qos.QoS 19 | import io.zenoh.keyexpr.KeyExpr 20 | import io.zenoh.bytes.Encoding 21 | import io.zenoh.bytes.ZBytes 22 | import org.apache.commons.net.ntp.TimeStamp 23 | 24 | /** 25 | * Class representing a Zenoh Sample. 26 | * 27 | * @property keyExpr The [KeyExpr] of the sample. 28 | * @property payload [ZBytes] with the payload of the sample. 29 | * @property encoding [Encoding] of the payload. 30 | * @property kind The [SampleKind] of the sample. 31 | * @property timestamp Optional [TimeStamp]. 32 | * @property qos The Quality of Service settings used to deliver the sample. 33 | * @property attachment Optional attachment. 34 | * @property express [QoS] express value. 35 | * @property congestionControl The congestion control policy. 36 | * @property priority The priority policy. 37 | */ 38 | data class Sample( 39 | val keyExpr: KeyExpr, 40 | val payload: ZBytes, 41 | val encoding: Encoding, 42 | val kind: SampleKind, 43 | val timestamp: TimeStamp?, 44 | val qos: QoS, 45 | val attachment: ZBytes? = null, 46 | ): ZenohType { 47 | 48 | val express = qos.express 49 | val congestionControl = qos.congestionControl 50 | val priority = qos.priority 51 | } 52 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/sample/SampleKind.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.sample 16 | 17 | /** The kind of sample. */ 18 | enum class SampleKind { 19 | PUT, 20 | DELETE; 21 | 22 | companion object { 23 | fun fromInt(value: Int) = entries.first { it.ordinal == value } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/scouting/Hello.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.scouting 16 | 17 | import io.zenoh.ZenohType 18 | import io.zenoh.config.WhatAmI 19 | import io.zenoh.config.ZenohId 20 | 21 | /** 22 | * Hello message received while scouting. 23 | * 24 | * @property whatAmI [WhatAmI] configuration: it indicates the role of the zenoh node sending the HELLO message. 25 | * @property zid [ZenohId] of the node sending the hello message. 26 | * @property locators The locators of this hello message. 27 | * @see Scout 28 | */ 29 | data class Hello(val whatAmI: WhatAmI, val zid: ZenohId, val locators: List): ZenohType 30 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/scouting/Scout.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.scouting 16 | 17 | import io.zenoh.jni.JNIScout 18 | 19 | /** 20 | * Scout for routers and/or peers. 21 | * 22 | * Scout spawns a task that periodically sends scout messages and waits for Hello replies. 23 | * Drop the returned Scout to stop the scouting task. 24 | * 25 | * To launch a scout, use [io.zenoh.Zenoh.scout]: 26 | * 27 | * Example using the default blocking queue handler: 28 | * ```java 29 | * 30 | * var scoutOptions = new ScoutOptions(); 31 | * scoutOptions.setWhatAmI(Set.of(WhatAmI.Peer, WhatAmI.Router)); 32 | * 33 | * var scout = Zenoh.scout(scoutOptions); 34 | * BlockingQueue> receiver = scout.getReceiver(); 35 | * 36 | * try { 37 | * while (true) { 38 | * Optional wrapper = receiver.take(); 39 | * if (wrapper.isEmpty()) { 40 | * break; 41 | * } 42 | * 43 | * Hello hello = wrapper.get(); 44 | * System.out.println(hello); 45 | * } 46 | * } finally { 47 | * scout.stop(); 48 | * } 49 | * ``` 50 | * 51 | * Example using a callback: 52 | * ```java 53 | * var scoutOptions = new ScoutOptions(); 54 | * scoutOptions.setWhatAmI(Set.of(WhatAmI.Peer, WhatAmI.Router)); 55 | * Zenoh.scout(hello -> { 56 | * //... 57 | * System.out.println(hello); 58 | * }, scoutOptions); 59 | * ``` 60 | * 61 | * @see CallbackScout 62 | * @see HandlerScout 63 | */ 64 | sealed class Scout ( 65 | private var jniScout: JNIScout? 66 | ) : AutoCloseable { 67 | 68 | /** 69 | * Stops the scouting. 70 | */ 71 | fun stop() { 72 | jniScout?.close() 73 | jniScout = null 74 | } 75 | 76 | /** 77 | * Equivalent to [stop]. 78 | */ 79 | override fun close() { 80 | stop() 81 | } 82 | 83 | protected fun finalize() { 84 | stop() 85 | } 86 | } 87 | 88 | /** 89 | * Scout using a callback to handle incoming [Hello] messages. 90 | * 91 | * Example: 92 | * ```java 93 | * CallbackScout scout = Zenoh.scout(hello -> {...}); 94 | * ``` 95 | */ 96 | class CallbackScout internal constructor(jniScout: JNIScout?) : Scout(jniScout) 97 | 98 | /** 99 | * Scout using a handler to handle incoming [Hello] messages. 100 | * 101 | * Example 102 | * ```java 103 | * HandlerScout>> scout = Zenoh.scout(); 104 | * ``` 105 | * 106 | * @param R The type of the receiver. 107 | * @param receiver The receiver of the scout's handler. 108 | */ 109 | class HandlerScout internal constructor(jniScout: JNIScout?, val receiver: R) : Scout(jniScout) 110 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/scouting/ScoutOptions.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.scouting 16 | 17 | import io.zenoh.Config 18 | import io.zenoh.config.WhatAmI 19 | 20 | /** 21 | * Options for scouting. 22 | * 23 | * @param config A [Config] for scouting. 24 | * @param whatAmI [WhatAmI] parameters. 25 | */ 26 | data class ScoutOptions( 27 | var config: Config? = null, 28 | var whatAmI: Set = setOf(WhatAmI.Peer, WhatAmI.Router) 29 | ) 30 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/session/SessionDeclaration.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.session 16 | 17 | /** 18 | * Session declaration. 19 | * 20 | * A session declaration is either a [io.zenoh.pubsub.Publisher], 21 | * a [io.zenoh.pubsub.Subscriber] or a [io.zenoh.query.Queryable] declared from a [io.zenoh.Session]. 22 | */ 23 | interface SessionDeclaration { 24 | 25 | /** Undeclare a declaration. No further operations should be performed after calling this function. */ 26 | fun undeclare() 27 | } 28 | -------------------------------------------------------------------------------- /zenoh-java/src/commonMain/kotlin/io/zenoh/session/SessionInfo.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh.session 16 | 17 | import io.zenoh.Session 18 | import io.zenoh.config.ZenohId 19 | import io.zenoh.exceptions.ZError 20 | 21 | /** 22 | * Class allowing to obtain the information of a [Session]. 23 | */ 24 | class SessionInfo(private val session: Session) { 25 | 26 | /** 27 | * Return the [ZenohId] of the current Zenoh [Session] 28 | */ 29 | @Throws(ZError::class) 30 | fun zid(): ZenohId { 31 | return session.zid() 32 | } 33 | 34 | /** 35 | * Return the [ZenohId] of the zenoh peers the session is currently connected to. 36 | */ 37 | @Throws(ZError::class) 38 | fun peersZid(): List { 39 | return session.getPeersId() 40 | } 41 | 42 | /** 43 | * Return the [ZenohId] of the zenoh routers the session is currently connected to. 44 | */ 45 | @Throws(ZError::class) 46 | fun routersZid(): List { 47 | return session.getRoutersId() 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /zenoh-java/src/jvmMain/kotlin/io/zenoh/Target.kt: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh 16 | 17 | internal enum class Target { 18 | WINDOWS_X86_64_MSVC, 19 | WINDOWS_AARCH64_MSVC, 20 | LINUX_X86_64, 21 | LINUX_AARCH64, 22 | APPLE_AARCH64, 23 | APPLE_X86_64; 24 | 25 | override fun toString(): String { 26 | return when (this) { 27 | WINDOWS_X86_64_MSVC -> "x86_64-pc-windows-msvc" 28 | WINDOWS_AARCH64_MSVC -> "aarch64-pc-windows-msvc" 29 | LINUX_X86_64 -> "x86_64-unknown-linux-gnu" 30 | LINUX_AARCH64 -> "aarch64-unknown-linux-gnu" 31 | APPLE_AARCH64 -> "aarch64-apple-darwin" 32 | APPLE_X86_64 -> "x86_64-apple-darwin" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /zenoh-java/src/jvmTest/java/io/zenoh/DeleteTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.exceptions.ZError; 18 | import io.zenoh.keyexpr.KeyExpr; 19 | import io.zenoh.pubsub.Subscriber; 20 | import io.zenoh.sample.SampleKind; 21 | import io.zenoh.sample.Sample; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.junit.runners.JUnit4; 25 | 26 | import static org.junit.Assert.assertEquals; 27 | import static org.junit.Assert.assertNotNull; 28 | 29 | @RunWith(JUnit4.class) 30 | public class DeleteTest { 31 | 32 | @Test 33 | public void deleteIsProperlyReceivedBySubscriberTest() throws ZError, InterruptedException { 34 | Session session = Zenoh.open(Config.loadDefault()); 35 | final Sample[] receivedSample = new Sample[1]; 36 | KeyExpr keyExpr = KeyExpr.tryFrom("example/testing/keyexpr"); 37 | Subscriber subscriber = 38 | session.declareSubscriber(keyExpr, sample -> receivedSample[0] = sample); 39 | session.delete(keyExpr); 40 | 41 | Thread.sleep(1000); 42 | subscriber.close(); 43 | session.close(); 44 | assertNotNull(receivedSample[0]); 45 | assertEquals(receivedSample[0].getKind(), SampleKind.DELETE); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /zenoh-java/src/jvmTest/java/io/zenoh/GetTest.java: -------------------------------------------------------------------------------- 1 | package io.zenoh; 2 | 3 | import io.zenoh.bytes.ZBytes; 4 | import io.zenoh.exceptions.ZError; 5 | import io.zenoh.handlers.Handler; 6 | import io.zenoh.query.*; 7 | import io.zenoh.sample.Sample; 8 | import io.zenoh.sample.SampleKind; 9 | import org.apache.commons.net.ntp.TimeStamp; 10 | import org.junit.After; 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | import org.junit.runner.RunWith; 14 | import org.junit.runners.JUnit4; 15 | 16 | import java.time.Duration; 17 | import java.util.ArrayList; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | import static org.junit.Assert.assertNotNull; 21 | 22 | @RunWith(JUnit4.class) 23 | public class GetTest { 24 | 25 | static final ZBytes payload = ZBytes.from("test"); 26 | static final TimeStamp timestamp = TimeStamp.getCurrentTime(); 27 | static final SampleKind kind = SampleKind.PUT; 28 | 29 | private Session session; 30 | private Selector selector; 31 | private Queryable queryable; 32 | 33 | @Before 34 | public void setUp() throws ZError { 35 | session = Zenoh.open(Config.loadDefault()); 36 | selector = Selector.tryFrom("example/testing/keyexpr"); 37 | queryable = session.declareQueryable(selector.getKeyExpr(), query -> 38 | { 39 | try { 40 | var options = new ReplyOptions(); 41 | options.setTimeStamp(timestamp); 42 | query.reply(query.getKeyExpr(), payload, options); 43 | } catch (ZError e) { 44 | throw new RuntimeException(e); 45 | } 46 | } 47 | ); 48 | } 49 | 50 | @After 51 | public void tearDown() throws ZError { 52 | session.close(); 53 | selector.close(); 54 | queryable.close(); 55 | } 56 | 57 | @Test 58 | public void get_runsWithCallbackTest() throws ZError, InterruptedException { 59 | Reply[] reply = new Reply[1]; 60 | 61 | var getOptions = new GetOptions(); 62 | getOptions.setTimeout(Duration.ofMillis(1000)); 63 | session.get(selector, reply1 -> reply[0] = reply1, getOptions); 64 | 65 | Thread.sleep(1000); 66 | assertNotNull(reply[0]); 67 | Sample sample = ((Reply.Success) reply[0]).getSample(); 68 | assertEquals(payload, sample.getPayload()); 69 | assertEquals(kind, sample.getKind()); 70 | assertEquals(selector.getKeyExpr(), sample.getKeyExpr()); 71 | assertEquals(timestamp, sample.getTimestamp()); 72 | } 73 | 74 | @Test 75 | public void get_runsWithHandlerTest() throws ZError { 76 | var getOptions = new GetOptions(); 77 | getOptions.setTimeout(Duration.ofMillis(1000)); 78 | ArrayList receiver = session.get(selector, new TestHandler(), getOptions); 79 | for (Reply reply : receiver) { 80 | Sample sample = ((Reply.Success) reply).getSample(); 81 | assertEquals(payload, sample.getPayload()); 82 | assertEquals(SampleKind.PUT, sample.getKind()); 83 | } 84 | } 85 | 86 | @Test 87 | public void getWithSelectorParamsTest() throws ZError { 88 | Parameters[] receivedParams = new Parameters[1]; 89 | 90 | Queryable queryable = session.declareQueryable(selector.getKeyExpr(), query -> 91 | receivedParams[0] = query.getParameters() 92 | ); 93 | 94 | Parameters params = Parameters.from("arg1=val1&arg2=val2&arg3"); 95 | Selector selectorWithParams = new Selector(selector.getKeyExpr(), params); 96 | var getOptions = new GetOptions(); 97 | getOptions.setTimeout(Duration.ofMillis(1000)); 98 | session.get(selectorWithParams, getOptions); 99 | 100 | queryable.close(); 101 | 102 | assertEquals(params, receivedParams[0]); 103 | } 104 | } 105 | 106 | /** 107 | * A dummy handler for get operations. 108 | */ 109 | class TestHandler implements Handler> { 110 | 111 | static final ArrayList performedReplies = new ArrayList<>(); 112 | 113 | @Override 114 | public void handle(Reply t) { 115 | performedReplies.add(t); 116 | } 117 | 118 | @Override 119 | public ArrayList receiver() { 120 | return performedReplies; 121 | } 122 | 123 | @Override 124 | public void onClose() { 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /zenoh-java/src/jvmTest/java/io/zenoh/LivelinessTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.exceptions.ZError; 18 | import io.zenoh.keyexpr.KeyExpr; 19 | import io.zenoh.liveliness.LivelinessToken; 20 | import io.zenoh.query.Reply; 21 | import io.zenoh.sample.Sample; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.junit.runners.JUnit4; 25 | 26 | import static org.junit.Assert.assertNotNull; 27 | 28 | @RunWith(JUnit4.class) 29 | public class LivelinessTest { 30 | 31 | @Test 32 | public void getLivelinessTest() throws ZError, InterruptedException { 33 | Session sessionA = Zenoh.open(Config.loadDefault()); 34 | Session sessionB = Zenoh.open(Config.loadDefault()); 35 | 36 | var keyExpr = KeyExpr.tryFrom("test/liveliness"); 37 | LivelinessToken token = sessionA.liveliness().declareToken(keyExpr); 38 | Thread.sleep(1000); 39 | 40 | Reply[] receivedReply = new Reply[1]; 41 | sessionB.liveliness().get(KeyExpr.tryFrom("test/**"), reply -> receivedReply[0] = reply); 42 | 43 | Thread.sleep(1000); 44 | 45 | assertNotNull(receivedReply[0]); 46 | token.close(); 47 | sessionA.close(); 48 | sessionB.close(); 49 | } 50 | 51 | @Test 52 | public void livelinessSubscriberTest() throws ZError, InterruptedException { 53 | Session sessionA = Zenoh.open(Config.loadDefault()); 54 | Session sessionB = Zenoh.open(Config.loadDefault()); 55 | 56 | Sample[] receivedSample = new Sample[1]; 57 | 58 | var subscriber = sessionA.liveliness().declareSubscriber(KeyExpr.tryFrom("test/**"), sample -> receivedSample[0] = sample); 59 | Thread.sleep(1000); 60 | var token = sessionB.liveliness().declareToken(KeyExpr.tryFrom("test/liveliness")); 61 | 62 | Thread.sleep(1000); 63 | 64 | assertNotNull(receivedSample[0]); 65 | 66 | token.close(); 67 | subscriber.close(); 68 | sessionA.close(); 69 | sessionB.close(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /zenoh-java/src/jvmTest/java/io/zenoh/ParametersTest.java: -------------------------------------------------------------------------------- 1 | package io.zenoh; 2 | 3 | import io.zenoh.query.Parameters; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.junit.runners.JUnit4; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | @RunWith(JUnit4.class) 14 | public class ParametersTest { 15 | 16 | @Test 17 | public void shouldCreateEmptyParametersFromEmptyString() { 18 | var result = Parameters.from(""); 19 | 20 | assertTrue(result.isEmpty()); 21 | } 22 | 23 | @Test 24 | public void shouldParseParametersFromFormattedString() { 25 | var parameters = Parameters.from("a=1;b=2;c=3|4|5;d=6"); 26 | 27 | assertEquals("1", parameters.get("a")); 28 | assertEquals("2", parameters.get("b")); 29 | assertEquals("3|4|5", parameters.get("c")); 30 | assertEquals("6", parameters.get("d")); 31 | } 32 | 33 | @Test 34 | public void shouldReturnListOfValuesSplitBySeparator() { 35 | var parameters = Parameters.from("a=1;b=2;c=3|4|5;d=6"); 36 | 37 | assertEquals(List.of("3", "4", "5"), parameters.values("c")); 38 | } 39 | 40 | @Test 41 | public void containsKeyTest() { 42 | var parameters = Parameters.from("a=1;b=2;c=3|4|5;d=6"); 43 | 44 | assertTrue(parameters.containsKey("a")); 45 | assertFalse(parameters.containsKey("e")); 46 | } 47 | 48 | @Test 49 | public void getTest() { 50 | var parameters = Parameters.from("a=1;b=2;c=3|4|5;d=6"); 51 | 52 | assertEquals("1", parameters.get("a")); 53 | assertEquals("2", parameters.get("b")); 54 | assertEquals("3|4|5", parameters.get("c")); 55 | assertEquals("6", parameters.get("d")); 56 | } 57 | 58 | @Test 59 | public void getOrDefaultTest() { 60 | var parameters = Parameters.from("a=1;b=2;c=3|4|5;d=6"); 61 | 62 | assertEquals("1", parameters.get("a")); 63 | assertEquals("None", parameters.getOrDefault("e", "None")); 64 | } 65 | 66 | @Test 67 | public void toMapTest() { 68 | var parameters = Parameters.from("a=1;b=2;c=3|4|5;d=6"); 69 | 70 | assertEquals(Map.of("a", "1", "b", "2", "c", "3|4|5", "d", "6"), parameters.toMap()); 71 | } 72 | 73 | @Test 74 | public void insertShouldReturnPreviouslyContainedValue() { 75 | var parameters = Parameters.from("a=1"); 76 | var oldValue = parameters.insert("a", "3"); 77 | assertEquals("1", oldValue); 78 | } 79 | 80 | @Test 81 | public void insertShouldReturnNullIfNotAlreadyPresent() { 82 | var parameters = Parameters.empty(); 83 | var oldValue = parameters.insert("a", "1"); 84 | assertNull(oldValue); 85 | } 86 | 87 | @Test 88 | public void removeShouldReturnOldValueIfPresent() { 89 | var parameters = Parameters.from("a=1"); 90 | var oldValue = parameters.remove("a"); 91 | assertEquals("1", oldValue); 92 | } 93 | 94 | @Test 95 | public void removeShouldReturnNullIfNotAlreadyPresent() { 96 | var parameters = Parameters.empty(); 97 | var oldValue = parameters.remove("a"); 98 | assertNull(oldValue); 99 | } 100 | 101 | @Test 102 | public void extendTest() { 103 | var parameters = Parameters.from("a=1;b=2"); 104 | parameters.extend(Parameters.from("c=3;d=4")); 105 | 106 | assertEquals(Parameters.from("a=1;b=2;c=3;d=4"), parameters); 107 | 108 | parameters.extend(Map.of("e", "5")); 109 | assertEquals(Parameters.from("a=1;b=2;c=3;d=4;e=5"), parameters); 110 | } 111 | 112 | @Test 113 | public void extendOverwritesConflictingKeysTest() { 114 | var parameters = Parameters.from("a=1;b=2"); 115 | parameters.extend(Parameters.from("b=3;d=4")); 116 | 117 | assertEquals(Parameters.from("a=1;b=3;d=4"), parameters); 118 | } 119 | 120 | @Test 121 | public void emptyParametersToStringTest() { 122 | var parameters = Parameters.empty(); 123 | assertEquals("", parameters.toString()); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /zenoh-java/src/jvmTest/java/io/zenoh/PublisherTest.java: -------------------------------------------------------------------------------- 1 | package io.zenoh; 2 | 3 | import io.zenoh.bytes.ZBytes; 4 | import io.zenoh.exceptions.ZError; 5 | import io.zenoh.keyexpr.KeyExpr; 6 | import io.zenoh.bytes.Encoding; 7 | import io.zenoh.pubsub.PublisherOptions; 8 | import io.zenoh.pubsub.PutOptions; 9 | import io.zenoh.qos.QoS; 10 | import io.zenoh.qos.Reliability; 11 | import io.zenoh.sample.SampleKind; 12 | import io.zenoh.pubsub.Publisher; 13 | import io.zenoh.sample.Sample; 14 | import io.zenoh.pubsub.Subscriber; 15 | import kotlin.Pair; 16 | import org.junit.After; 17 | import org.junit.Before; 18 | import org.junit.Test; 19 | import org.junit.runner.RunWith; 20 | import org.junit.runners.JUnit4; 21 | 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | import static org.junit.Assert.assertEquals; 26 | 27 | @RunWith(JUnit4.class) 28 | public class PublisherTest { 29 | 30 | private Session session; 31 | private ArrayList receivedSamples; 32 | private Publisher publisher; 33 | private Subscriber subscriber; 34 | private KeyExpr keyExpr; 35 | 36 | @Before 37 | public void setUp() throws ZError { 38 | session = Zenoh.open(Config.loadDefault()); 39 | keyExpr = KeyExpr.tryFrom("example/testing/keyexpr"); 40 | 41 | var config = new PublisherOptions(); 42 | config.setReliability(Reliability.RELIABLE); 43 | config.setEncoding(Encoding.ZENOH_STRING); 44 | publisher = session.declarePublisher(keyExpr, config); 45 | 46 | receivedSamples = new ArrayList<>(); 47 | 48 | subscriber = session.declareSubscriber(keyExpr, receivedSamples::add); 49 | } 50 | 51 | @After 52 | public void tearDown() throws ZError { 53 | publisher.close(); 54 | subscriber.close(); 55 | session.close(); 56 | keyExpr.close(); 57 | } 58 | 59 | @Test 60 | public void putTest() { 61 | 62 | List> testPayloads = List.of( 63 | new Pair<>(ZBytes.from("Test 1"), Encoding.TEXT_PLAIN), 64 | new Pair<>(ZBytes.from("Test 2"), Encoding.TEXT_JSON), 65 | new Pair<>(ZBytes.from("Test 3"), Encoding.TEXT_CSV) 66 | ); 67 | 68 | testPayloads.forEach(value -> { 69 | try { 70 | var putOptions = new PutOptions(); 71 | putOptions.setEncoding(value.getSecond()); 72 | publisher.put(value.getFirst(), putOptions); 73 | } catch (ZError e) { 74 | throw new RuntimeException(e); 75 | } 76 | }); 77 | 78 | assertEquals(testPayloads.size(), receivedSamples.size()); 79 | for (int index = 0; index < receivedSamples.size(); index++) { 80 | var sample = receivedSamples.get(index); 81 | assertEquals(testPayloads.get(index).getFirst(), sample.getPayload()); 82 | assertEquals(testPayloads.get(index).getSecond(), sample.getEncoding()); 83 | } 84 | } 85 | 86 | @Test 87 | public void deleteTest() throws ZError { 88 | publisher.delete(); 89 | assertEquals(1, receivedSamples.size()); 90 | assertEquals(SampleKind.DELETE, receivedSamples.get(0).getKind()); 91 | } 92 | 93 | @Test 94 | public void shouldFallbackToPublisherEncodingWhenEncodingNotProvided() throws ZError { 95 | publisher.put(ZBytes.from("Test")); 96 | assertEquals(1, receivedSamples.size()); 97 | assertEquals(Encoding.ZENOH_STRING, receivedSamples.get(0).getEncoding()); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /zenoh-java/src/jvmTest/java/io/zenoh/PutTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.bytes.ZBytes; 18 | import io.zenoh.bytes.Encoding; 19 | import io.zenoh.exceptions.ZError; 20 | import io.zenoh.keyexpr.KeyExpr; 21 | import io.zenoh.pubsub.PutOptions; 22 | import io.zenoh.pubsub.Subscriber; 23 | import io.zenoh.sample.Sample; 24 | import org.junit.Test; 25 | import org.junit.runner.RunWith; 26 | import org.junit.runners.JUnit4; 27 | 28 | import static org.junit.Assert.assertEquals; 29 | import static org.junit.Assert.assertNotNull; 30 | 31 | @RunWith(JUnit4.class) 32 | public class PutTest { 33 | 34 | public static final String TEST_KEY_EXP = "example/testing/keyexpr"; 35 | public static final ZBytes TEST_PAYLOAD = ZBytes.from("Hello"); 36 | 37 | @Test 38 | public void putTest() throws ZError { 39 | Session session = Zenoh.open(Config.loadDefault()); 40 | Sample[] receivedSample = new Sample[1]; 41 | var keyExpr = KeyExpr.tryFrom(TEST_KEY_EXP); 42 | 43 | Subscriber subscriber = 44 | session.declareSubscriber(keyExpr, sample -> receivedSample[0] = sample); 45 | 46 | var putOptions = new PutOptions(); 47 | putOptions.setEncoding(Encoding.TEXT_PLAIN); 48 | session.put(keyExpr, TEST_PAYLOAD, putOptions); 49 | subscriber.close(); 50 | session.close(); 51 | assertNotNull(receivedSample[0]); 52 | assertEquals(TEST_PAYLOAD, receivedSample[0].getPayload()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /zenoh-java/src/jvmTest/java/io/zenoh/QuerierTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.bytes.Encoding; 18 | import io.zenoh.bytes.ZBytes; 19 | import io.zenoh.exceptions.ZError; 20 | import io.zenoh.keyexpr.KeyExpr; 21 | import io.zenoh.qos.CongestionControl; 22 | import io.zenoh.qos.Priority; 23 | import io.zenoh.qos.QoS; 24 | import io.zenoh.query.Querier; 25 | import io.zenoh.query.Reply; 26 | import io.zenoh.query.ReplyOptions; 27 | import io.zenoh.sample.Sample; 28 | import io.zenoh.sample.SampleKind; 29 | import org.apache.commons.net.ntp.TimeStamp; 30 | import org.junit.Test; 31 | 32 | import java.time.Instant; 33 | import java.util.*; 34 | 35 | import static org.junit.Assert.*; 36 | 37 | public class QuerierTest { 38 | 39 | static final ZBytes testPayload = ZBytes.from("Hello queryable"); 40 | static final KeyExpr testKeyExpr; 41 | 42 | static { 43 | try { 44 | testKeyExpr = KeyExpr.tryFrom("example/testing/keyexpr"); 45 | } catch (ZError e) { 46 | throw new RuntimeException(e); 47 | } 48 | } 49 | 50 | /** 51 | * Test validating both Queryable and get operations. 52 | */ 53 | @Test 54 | public void querier_runsWithCallbackTest() throws ZError, InterruptedException { 55 | var sample = new Sample( 56 | testKeyExpr, 57 | testPayload, 58 | Encoding.defaultEncoding(), 59 | SampleKind.PUT, 60 | new TimeStamp(Date.from(Instant.now())), 61 | new QoS(CongestionControl.BLOCK, Priority.DATA, false), 62 | null 63 | ); 64 | var examplePayload = ZBytes.from("Example payload"); 65 | var exampleAttachment = ZBytes.from("Example attachment"); 66 | var session = Zenoh.open(Config.loadDefault()); 67 | 68 | var queryable = session.declareQueryable(testKeyExpr, query -> { 69 | assertEquals(exampleAttachment, query.getAttachment()); 70 | assertEquals(examplePayload, query.getPayload()); 71 | 72 | var replyOptions = new ReplyOptions(); 73 | replyOptions.setTimeStamp(sample.getTimestamp()); 74 | try { 75 | query.reply(testKeyExpr, sample.getPayload(), replyOptions); 76 | } catch (ZError e) { 77 | throw new RuntimeException(e); 78 | } 79 | }); 80 | 81 | var querier = session.declareQuerier(testKeyExpr); 82 | 83 | Reply[] receivedReply = new Reply[1]; 84 | var options = new Querier.GetOptions(); 85 | options.setPayload(examplePayload); 86 | options.setAttachment(exampleAttachment); 87 | querier.get( 88 | reply -> { 89 | receivedReply[0] = reply; 90 | }, 91 | options 92 | ); 93 | 94 | Thread.sleep(1000); 95 | assertNotNull(receivedReply[0]); 96 | assertEquals(sample, ((Reply.Success) receivedReply[0]).getSample()); 97 | 98 | queryable.close(); 99 | querier.close(); 100 | session.close(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /zenoh-java/src/jvmTest/java/io/zenoh/ScoutTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.config.WhatAmI; 18 | import io.zenoh.exceptions.ZError; 19 | import io.zenoh.scouting.Hello; 20 | import io.zenoh.scouting.Scout; 21 | import io.zenoh.scouting.ScoutOptions; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.junit.runners.JUnit4; 25 | 26 | import java.util.ArrayList; 27 | import java.util.Optional; 28 | import java.util.Set; 29 | import java.util.concurrent.BlockingQueue; 30 | 31 | import static org.junit.Assert.assertNotNull; 32 | import static org.junit.Assert.assertTrue; 33 | 34 | @RunWith(JUnit4.class) 35 | public class ScoutTest { 36 | 37 | @Test 38 | public void scouting_queueTest() throws ZError, InterruptedException { 39 | Session session = Zenoh.open(Config.loadDefault()); 40 | 41 | Thread.sleep(1000); 42 | 43 | var scout = Zenoh.scout(); 44 | 45 | Thread.sleep(1000); 46 | scout.close(); 47 | 48 | ArrayList> helloList = new ArrayList<>(); 49 | scout.getReceiver().drainTo(helloList); 50 | 51 | assertTrue(helloList.size() > 1); 52 | for (int i = 0; i < helloList.size() - 1; i++) { 53 | assertTrue(helloList.get(i).isPresent()); 54 | } 55 | assertTrue(helloList.get(helloList.size() - 1).isEmpty()); 56 | session.close(); 57 | } 58 | 59 | @Test 60 | public void scouting_callbackTest() throws ZError, InterruptedException { 61 | Session session = Zenoh.open(Config.loadDefault()); 62 | 63 | Hello[] hello = new Hello[1]; 64 | Zenoh.scout(hello1 -> hello[0] = hello1); 65 | 66 | Thread.sleep(1000); 67 | 68 | assertNotNull(hello[0]); 69 | session.close(); 70 | } 71 | 72 | @Test 73 | public void scouting_whatAmITest() throws ZError { 74 | var scoutOptions = new ScoutOptions(); 75 | scoutOptions.setWhatAmI(Set.of(WhatAmI.Client, WhatAmI.Peer)); 76 | var scout = Zenoh.scout(scoutOptions); 77 | scout.close(); 78 | } 79 | 80 | @Test 81 | public void scouting_onCloseTest() throws ZError { 82 | var scout = Zenoh.scout(); 83 | var receiver = scout.getReceiver(); 84 | 85 | scout.close(); 86 | var element = receiver.poll(); 87 | assertNotNull(element); 88 | assertTrue(element.isEmpty()); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /zenoh-java/src/jvmTest/java/io/zenoh/SelectorTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.exceptions.ZError; 18 | import io.zenoh.keyexpr.KeyExpr; 19 | import io.zenoh.query.Parameters; 20 | import io.zenoh.query.Selector; 21 | import org.junit.Test; 22 | import org.junit.runner.RunWith; 23 | import org.junit.runners.JUnit4; 24 | 25 | import java.util.List; 26 | 27 | import static org.junit.Assert.*; 28 | 29 | @RunWith(JUnit4.class) 30 | public class SelectorTest { 31 | 32 | @Test 33 | public void selector_fromStringTest() throws ZError { 34 | var selector = Selector.tryFrom("a/b/c?arg1=val1"); 35 | assertEquals("a/b/c", selector.getKeyExpr().toString()); 36 | assertNotNull(selector.getParameters()); 37 | assertEquals("arg1=val1", selector.getParameters().toString()); 38 | 39 | var selector2 = Selector.tryFrom("a/b/c"); 40 | assertEquals("a/b/c", selector2.getKeyExpr().toString()); 41 | assertNull(selector2.getParameters()); 42 | 43 | assertThrows(ZError.class, () -> Selector.tryFrom("")); 44 | } 45 | 46 | @Test 47 | public void parametersTest() { 48 | var parameters = Parameters.from("a=1;b=2;c=1|2|3"); 49 | assertEquals(List.of("1", "2", "3"), parameters.values("c")); 50 | } 51 | 52 | /** 53 | * Check the queryable properly receives the query's selector with and without parameters. 54 | */ 55 | @Test 56 | public void selectorQueryTest() throws ZError, InterruptedException { 57 | var session = Zenoh.open(Config.loadDefault()); 58 | var queryableKeyExpr = KeyExpr.tryFrom("a/b/**"); 59 | 60 | Selector[] receivedQuerySelector = new Selector[1]; 61 | var queryable = session.declareQueryable(queryableKeyExpr, query -> { 62 | receivedQuerySelector[0] = query.getSelector(); 63 | query.close(); 64 | } 65 | ); 66 | 67 | var querySelector = Selector.tryFrom("a/b/c"); 68 | session.get(querySelector, reply -> { 69 | }); 70 | Thread.sleep(1000); 71 | assertEquals(querySelector, receivedQuerySelector[0]); 72 | 73 | var querySelector2 = Selector.tryFrom("a/b/c?key=value"); 74 | session.get(querySelector2, reply -> { 75 | }); 76 | Thread.sleep(1000); 77 | assertEquals(querySelector2, receivedQuerySelector[0]); 78 | 79 | queryable.close(); 80 | session.close(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /zenoh-java/src/jvmTest/java/io/zenoh/SessionInfoTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.config.ZenohId; 18 | import org.junit.Test; 19 | import org.junit.runner.RunWith; 20 | import org.junit.runners.JUnit4; 21 | 22 | import static org.junit.Assert.assertEquals; 23 | import static org.junit.Assert.assertTrue; 24 | 25 | @RunWith(JUnit4.class) 26 | public class SessionInfoTest { 27 | 28 | @Test 29 | public void peersZidTest() throws Exception { 30 | String jsonConfig = "{\n" + 31 | " mode: \"peer\",\n" + 32 | " connect: {\n" + 33 | " endpoints: [\"tcp/localhost:7450\"]\n" + 34 | " }\n" + 35 | "}"; 36 | 37 | Config listenConfig = Config.fromJson("{\n" + 38 | " mode: \"peer\",\n" + 39 | " listen: {\n" + 40 | " endpoints: [\"tcp/localhost:7450\"]\n" + 41 | " }\n" + 42 | "}"); 43 | 44 | Session sessionC = Zenoh.open(listenConfig); 45 | Session sessionA = Zenoh.open(Config.fromJson(jsonConfig)); 46 | Session sessionB = Zenoh.open(Config.fromJson(jsonConfig)); 47 | 48 | ZenohId idA = sessionA.info().zid(); 49 | ZenohId idB = sessionB.info().zid(); 50 | var peers = sessionC.info().peersZid(); 51 | assertTrue(peers.contains(idA)); 52 | assertTrue(peers.contains(idB)); 53 | 54 | sessionA.close(); 55 | sessionB.close(); 56 | sessionC.close(); 57 | } 58 | 59 | @Test 60 | public void routersZidTest() throws Exception { 61 | Session session = Zenoh.open(Config.fromJson("{\n" + 62 | " mode: \"router\",\n" + 63 | " listen: {\n" + 64 | " endpoints: [\"tcp/localhost:7450\"]\n" + 65 | " }\n" + 66 | "}")); 67 | 68 | Session connectedRouterA = Zenoh.open(Config.fromJson("{\n" + 69 | " mode: \"router\",\n" + 70 | " connect: {\n" + 71 | " endpoints: [\"tcp/localhost:7450\"]\n" + 72 | " },\n" + 73 | " listen: {\n" + 74 | " endpoints: [\"tcp/localhost:7451\"]\n" + 75 | " }\n" + 76 | "}")); 77 | 78 | Session connectedRouterB = Zenoh.open(Config.fromJson("{\n" + 79 | " mode: \"router\",\n" + 80 | " connect: {\n" + 81 | " endpoints: [\"tcp/localhost:7450\"]\n" + 82 | " },\n" + 83 | " listen: {\n" + 84 | " endpoints: [\"tcp/localhost:7452\"]\n" + 85 | " }\n" + 86 | "}")); 87 | 88 | ZenohId idA = connectedRouterA.info().zid(); 89 | ZenohId idB = connectedRouterB.info().zid(); 90 | 91 | var routers = session.info().routersZid(); 92 | 93 | assertTrue(routers.contains(idA)); 94 | assertTrue(routers.contains(idB)); 95 | 96 | connectedRouterA.close(); 97 | connectedRouterB.close(); 98 | session.close(); 99 | } 100 | 101 | @Test 102 | public void zidTest() throws Exception { 103 | String jsonConfig = "{\n" + 104 | " id: \"123456\"\n" + 105 | "}"; 106 | 107 | Session session = Zenoh.open(Config.fromJson(jsonConfig)); 108 | assertEquals("123456", session.info().zid().toString()); 109 | session.close(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /zenoh-java/src/jvmTest/java/io/zenoh/SessionTest.java: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | package io.zenoh; 16 | 17 | import io.zenoh.bytes.ZBytes; 18 | import io.zenoh.exceptions.ZError; 19 | import io.zenoh.keyexpr.KeyExpr; 20 | import io.zenoh.pubsub.Publisher; 21 | import org.junit.Test; 22 | import org.junit.runner.RunWith; 23 | import org.junit.runners.JUnit4; 24 | 25 | import static org.junit.Assert.*; 26 | 27 | @RunWith(JUnit4.class) 28 | public class SessionTest { 29 | 30 | private static final KeyExpr testKeyExpr; 31 | 32 | static { 33 | try { 34 | testKeyExpr = KeyExpr.tryFrom("example/testing/keyexpr"); 35 | } catch (ZError e) { 36 | throw new RuntimeException(e); 37 | } 38 | } 39 | 40 | @Test 41 | public void sessionStartCloseTest() throws ZError { 42 | Session session = Zenoh.open(Config.loadDefault()); 43 | assertFalse(session.isClosed()); 44 | session.close(); 45 | assertTrue(session.isClosed()); 46 | } 47 | 48 | @Test 49 | public void sessionClose_declarationsAreUndeclaredAfterClosingSessionTest() throws ZError, InterruptedException { 50 | Session session = Zenoh.open(Config.loadDefault()); 51 | 52 | Publisher publisher = session.declarePublisher(testKeyExpr); 53 | var subscriber = session.declareSubscriber(testKeyExpr); 54 | session.close(); 55 | 56 | Thread.sleep(1000); 57 | 58 | assertFalse(subscriber.isValid()); 59 | assertFalse(publisher.isValid()); 60 | 61 | assertThrows(ZError.class, () -> publisher.put(ZBytes.from("Test"))); 62 | } 63 | 64 | @Test 65 | public void sessionClose_newDeclarationsReturnNullAfterClosingSession() throws ZError { 66 | Session session = Zenoh.open(Config.loadDefault()); 67 | session.close(); 68 | assertThrows(ZError.class, () -> session.declarePublisher(testKeyExpr)); 69 | assertThrows(ZError.class, () -> session.declareQueryable(testKeyExpr)); 70 | assertThrows(ZError.class, () -> session.declareSubscriber(testKeyExpr)); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /zenoh-jni/Cargo.toml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2023 ZettaScale Technology 3 | # 4 | # This program and the accompanying materials are made available under the 5 | # terms of the Eclipse Public License 2.0 which is available at 6 | # http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | # which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | # 9 | # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | # 11 | # Contributors: 12 | # ZettaScale Zenoh Team, 13 | # 14 | 15 | [package] 16 | rust-version = "1.75.0" 17 | version = "1.4.0" 18 | repository = "https://github.com/eclipse-zenoh/zenoh" 19 | homepage = "http://zenoh.io" 20 | edition = "2021" 21 | license = "EPL-2.0 OR Apache-2.0" 22 | categories = ["network-programming"] 23 | description = "Zenoh: Zero Overhead Pub/sub, Store/Query and Compute." 24 | name = "zenoh_jni" 25 | 26 | [features] 27 | default = ["zenoh/default", "zenoh-ext"] 28 | 29 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 30 | [dependencies] 31 | android-logd-logger = "0.4.0" 32 | async-std = { version = "=1.12.0", default-features = false } 33 | clap = "3.2.23" 34 | jni = "0.21.1" 35 | flume = "0.10.14" 36 | uhlc = "0.8.0" 37 | json5 = "0.4.1" 38 | serde_yaml = "0.9.19" 39 | zenoh = { version = "1.4.0", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", features = ["unstable", "internal"], default-features = false } 40 | zenoh-ext = { version = "1.4.0", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", features = ["internal"], default-features = false, optional = true } 41 | tracing = { version = "0.1" , features = ["log"] } 42 | [lib] 43 | name = "zenoh_jni" 44 | crate_type = ["staticlib", "dylib"] 45 | 46 | [build-dependencies] 47 | rustc_version = "0.4.0" 48 | 49 | [profile.release] 50 | debug = false # If you want debug symbol in release mode, set the env variable: RUSTFLAGS=-g 51 | lto = "fat" 52 | codegen-units = 1 53 | opt-level = 3 54 | panic = "abort" 55 | -------------------------------------------------------------------------------- /zenoh-jni/src/errors.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | use std::fmt; 16 | 17 | use jni::JNIEnv; 18 | 19 | #[macro_export] 20 | macro_rules! throw_exception { 21 | ($env:expr, $err:expr) => {{ 22 | let _ = $err.throw_on_jvm(&mut $env).map_err(|err| { 23 | tracing::error!("Unable to throw exception: {}", err); 24 | }); 25 | }}; 26 | } 27 | 28 | #[macro_export] 29 | macro_rules! zerror { 30 | ($arg:expr) => { 31 | $crate::errors::ZError($arg.to_string()) 32 | }; 33 | ($fmt:expr, $($arg:tt)*) => { 34 | $crate::errors::ZError(format!($fmt, $($arg)*)) 35 | }; 36 | } 37 | 38 | pub(crate) type ZResult = core::result::Result; 39 | 40 | #[derive(Debug)] 41 | pub(crate) struct ZError(pub String); 42 | 43 | impl fmt::Display for ZError { 44 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 45 | write!(f, "{}", self.0) 46 | } 47 | } 48 | 49 | impl ZError { 50 | const KOTLIN_EXCEPTION_NAME: &'static str = "io/zenoh/exceptions/ZError"; 51 | 52 | pub fn throw_on_jvm(&self, env: &mut JNIEnv) -> ZResult<()> { 53 | let exception_class = env 54 | .find_class(Self::KOTLIN_EXCEPTION_NAME) 55 | .map_err(|err| zerror!("Failed to retrieve exception class: {}", err))?; 56 | env.throw_new(exception_class, self.to_string()) 57 | .map_err(|err| zerror!("Failed to throw exception: {}", err)) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /zenoh-jni/src/lib.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | mod config; 16 | mod errors; 17 | mod key_expr; 18 | mod liveliness; 19 | mod logger; 20 | mod publisher; 21 | mod querier; 22 | mod query; 23 | mod queryable; 24 | mod scouting; 25 | mod session; 26 | mod subscriber; 27 | mod utils; 28 | #[cfg(feature = "zenoh-ext")] 29 | mod zbytes; 30 | mod zenoh_id; 31 | 32 | // Test should be runned with `cargo test --no-default-features` 33 | #[test] 34 | #[cfg(not(feature = "default"))] 35 | fn test_no_default_features() { 36 | assert_eq!(zenoh::FEATURES, concat!(" zenoh/unstable")); 37 | } 38 | -------------------------------------------------------------------------------- /zenoh-jni/src/logger.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | use jni::{ 16 | objects::{JClass, JString}, 17 | JNIEnv, 18 | }; 19 | 20 | use crate::{errors::ZResult, throw_exception, zerror}; 21 | 22 | /// Redirects the Rust logs either to logcat for Android systems or to the standard output (for non-Android systems). 23 | /// 24 | /// This function is meant to be called from Java/Kotlin code through JNI. It takes a `filter` 25 | /// indicating the desired log level. 26 | /// 27 | /// See https://docs.rs/env_logger/latest/env_logger/index.html for accepted filter format. 28 | /// 29 | /// # Parameters: 30 | /// - `env`: The JNI environment. 31 | /// - `_class`: The JNI class. 32 | /// - `filter`: The logs filter. 33 | /// 34 | /// # Errors: 35 | /// - If there is an error parsing the log level string, a `JNIException` is thrown on the JVM. 36 | /// 37 | #[no_mangle] 38 | #[allow(non_snake_case)] 39 | pub extern "C" fn Java_io_zenoh_Logger_00024Companion_startLogsViaJNI( 40 | mut env: JNIEnv, 41 | _class: JClass, 42 | filter: JString, 43 | ) { 44 | || -> ZResult<()> { 45 | let log_level = parse_filter(&mut env, filter)?; 46 | android_logd_logger::builder() 47 | .parse_filters(log_level.as_str()) 48 | .tag_target_strip() 49 | .prepend_module(true) 50 | .init(); 51 | Ok(()) 52 | }() 53 | .unwrap_or_else(|err| throw_exception!(env, err)) 54 | } 55 | 56 | fn parse_filter(env: &mut JNIEnv, log_level: JString) -> ZResult { 57 | let log_level = env.get_string(&log_level).map_err(|err| zerror!(err))?; 58 | log_level 59 | .to_str() 60 | .map(|level| Ok(level.to_string())) 61 | .map_err(|err| zerror!(err))? 62 | } 63 | -------------------------------------------------------------------------------- /zenoh-jni/src/publisher.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | use std::sync::Arc; 16 | 17 | use jni::{ 18 | objects::{JByteArray, JClass, JString}, 19 | sys::jint, 20 | JNIEnv, 21 | }; 22 | use zenoh::{pubsub::Publisher, Wait}; 23 | 24 | use crate::throw_exception; 25 | use crate::{ 26 | errors::ZResult, 27 | utils::{decode_byte_array, decode_encoding}, 28 | zerror, 29 | }; 30 | 31 | /// Performs a PUT operation on a Zenoh publisher via JNI. 32 | /// 33 | /// # Parameters 34 | /// - `env`: The JNI environment pointer. 35 | /// - `_class`: The Java class reference (unused). 36 | /// - `payload`: The byte array to be published. 37 | /// - `encoding_id`: The encoding ID of the payload. 38 | /// - `encoding_schema`: Nullable encoding schema string of the payload. 39 | /// - `attachment`: Nullble byte array for the attachment. 40 | /// - `publisher_ptr`: The raw pointer to the Zenoh publisher ([Publisher]). 41 | /// 42 | /// # Safety 43 | /// - This function is marked as unsafe due to raw pointer manipulation and JNI interaction. 44 | /// - Assumes that the provided publisher pointer is valid and has not been modified or freed. 45 | /// - The publisher pointer remains valid after this function call. 46 | /// - May throw an exception in case of failure, which must be handled by the caller. 47 | /// 48 | #[no_mangle] 49 | #[allow(non_snake_case)] 50 | pub unsafe extern "C" fn Java_io_zenoh_jni_JNIPublisher_putViaJNI( 51 | mut env: JNIEnv, 52 | _class: JClass, 53 | payload: JByteArray, 54 | encoding_id: jint, 55 | encoding_schema: /*nullable*/ JString, 56 | attachment: /*nullable*/ JByteArray, 57 | publisher_ptr: *const Publisher<'static>, 58 | ) { 59 | let publisher = Arc::from_raw(publisher_ptr); 60 | let _ = || -> ZResult<()> { 61 | let payload = decode_byte_array(&env, payload)?; 62 | let mut publication = publisher.put(payload); 63 | let encoding = decode_encoding(&mut env, encoding_id, &encoding_schema)?; 64 | publication = publication.encoding(encoding); 65 | if !attachment.is_null() { 66 | let attachment = decode_byte_array(&env, attachment)?; 67 | publication = publication.attachment::>(attachment) 68 | }; 69 | publication.wait().map_err(|err| zerror!(err)) 70 | }() 71 | .map_err(|err| throw_exception!(env, err)); 72 | std::mem::forget(publisher); 73 | } 74 | 75 | /// Performs a DELETE operation on a Zenoh publisher via JNI. 76 | /// 77 | /// # Parameters 78 | /// - `env`: The JNI environment pointer. 79 | /// - `_class`: The Java class reference (unused). 80 | /// - `attachment`: Nullble byte array for the attachment. 81 | /// - `publisher_ptr`: The raw pointer to the Zenoh publisher ([Publisher]). 82 | /// 83 | /// # Safety 84 | /// - This function is marked as unsafe due to raw pointer manipulation and JNI interaction. 85 | /// - Assumes that the provided publisher pointer is valid and has not been modified or freed. 86 | /// - The publisher pointer remains valid after this function call. 87 | /// - May throw an exception in case of failure, which must be handled by the caller. 88 | /// 89 | #[no_mangle] 90 | #[allow(non_snake_case)] 91 | pub unsafe extern "C" fn Java_io_zenoh_jni_JNIPublisher_deleteViaJNI( 92 | mut env: JNIEnv, 93 | _class: JClass, 94 | attachment: /*nullable*/ JByteArray, 95 | publisher_ptr: *const Publisher<'static>, 96 | ) { 97 | let publisher = Arc::from_raw(publisher_ptr); 98 | let _ = || -> ZResult<()> { 99 | let mut delete = publisher.delete(); 100 | if !attachment.is_null() { 101 | let attachment = decode_byte_array(&env, attachment)?; 102 | delete = delete.attachment::>(attachment) 103 | }; 104 | delete.wait().map_err(|err| zerror!(err)) 105 | }() 106 | .map_err(|err| throw_exception!(env, err)); 107 | std::mem::forget(publisher) 108 | } 109 | 110 | /// Frees the publisher. 111 | /// 112 | /// # Parameters: 113 | /// - `_env`: The JNI environment. 114 | /// - `_class`: The JNI class. 115 | /// - `publisher_ptr`: The raw pointer to the Zenoh publisher ([Publisher]). 116 | /// 117 | /// # Safety: 118 | /// - The function is marked as unsafe due to raw pointer manipulation. 119 | /// - It assumes that the provided publisher pointer is valid and has not been modified or freed. 120 | /// - After calling this function, the publisher pointer becomes invalid and should not be used anymore. 121 | /// 122 | #[no_mangle] 123 | #[allow(non_snake_case)] 124 | pub(crate) unsafe extern "C" fn Java_io_zenoh_jni_JNIPublisher_freePtrViaJNI( 125 | _env: JNIEnv, 126 | _: JClass, 127 | publisher_ptr: *const Publisher, 128 | ) { 129 | Arc::from_raw(publisher_ptr); 130 | } 131 | -------------------------------------------------------------------------------- /zenoh-jni/src/queryable.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | use std::sync::Arc; 16 | 17 | use jni::{objects::JClass, JNIEnv}; 18 | use zenoh::query::Queryable; 19 | 20 | /// Frees the [Queryable]. 21 | /// 22 | /// # Parameters: 23 | /// - `_env`: The JNI environment. 24 | /// - `_class`: The JNI class. 25 | /// - `queryable_ptr`: The raw pointer to the Zenoh queryable ([Queryable]). 26 | /// 27 | /// # Safety: 28 | /// - The function is marked as unsafe due to raw pointer manipulation. 29 | /// - It assumes that the provided queryable pointer is valid and has not been modified or freed. 30 | /// - The function takes ownership of the raw pointer and releases the associated memory. 31 | /// - After calling this function, the queryable pointer becomes invalid and should not be used anymore. 32 | /// 33 | #[no_mangle] 34 | #[allow(non_snake_case)] 35 | pub(crate) unsafe extern "C" fn Java_io_zenoh_jni_JNIQueryable_freePtrViaJNI( 36 | _env: JNIEnv, 37 | _: JClass, 38 | queryable_ptr: *const Queryable<()>, 39 | ) { 40 | Arc::from_raw(queryable_ptr); 41 | } 42 | -------------------------------------------------------------------------------- /zenoh-jni/src/scouting.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | use std::{ptr::null, sync::Arc}; 16 | 17 | use jni::{ 18 | objects::{GlobalRef, JClass, JList, JObject, JValue}, 19 | sys::jint, 20 | JNIEnv, 21 | }; 22 | use zenoh::{config::WhatAmIMatcher, Wait}; 23 | use zenoh::{scouting::Scout, Config}; 24 | 25 | use crate::utils::{get_callback_global_ref, get_java_vm, load_on_close}; 26 | use crate::{errors::ZResult, throw_exception, zerror}; 27 | 28 | /// Start a scout. 29 | /// 30 | /// # Params 31 | /// - `whatAmI`: Ordinal value of the WhatAmI enum. 32 | /// - `callback`: Callback to be executed whenever a hello message is received. 33 | /// - `config_ptr`: Optional config pointer. 34 | /// 35 | /// Returns a pointer to the scout, which must be freed afterwards. 36 | /// If starting the scout fails, an exception is thrown on the JVM, and a null pointer is returned. 37 | /// 38 | #[no_mangle] 39 | #[allow(non_snake_case)] 40 | pub unsafe extern "C" fn Java_io_zenoh_jni_JNIScout_00024Companion_scoutViaJNI( 41 | mut env: JNIEnv, 42 | _class: JClass, 43 | whatAmI: jint, 44 | callback: JObject, 45 | on_close: JObject, 46 | config_ptr: /*nullable=*/ *const Config, 47 | ) -> *const Scout<()> { 48 | || -> ZResult<*const Scout<()>> { 49 | let callback_global_ref = get_callback_global_ref(&mut env, callback)?; 50 | let java_vm = Arc::new(get_java_vm(&mut env)?); 51 | let on_close_global_ref: GlobalRef = get_callback_global_ref(&mut env, on_close)?; 52 | let on_close = load_on_close(&java_vm, on_close_global_ref); 53 | let whatAmIMatcher: WhatAmIMatcher = (whatAmI as u8).try_into().unwrap(); // The validity of the operation is guaranteed on the kotlin layer. 54 | let config = if config_ptr.is_null() { 55 | Config::default() 56 | } else { 57 | let arc_cfg = Arc::from_raw(config_ptr); 58 | let config_clone = arc_cfg.as_ref().clone(); 59 | std::mem::forget(arc_cfg); 60 | config_clone 61 | }; 62 | zenoh::scout(whatAmIMatcher, config) 63 | .callback(move |hello| { 64 | on_close.noop(); // Moves `on_close` inside the closure so it gets destroyed with the closure 65 | tracing::debug!("Received hello: {hello}"); 66 | let _ = || -> jni::errors::Result<()> { 67 | let mut env = java_vm.attach_current_thread_as_daemon()?; 68 | let whatami = hello.whatami() as jint; 69 | let zenoh_id = env 70 | .byte_array_from_slice(&hello.zid().to_le_bytes()) 71 | .map(|it| env.auto_local(it))?; 72 | let locators = env 73 | .new_object("java/util/ArrayList", "()V", &[]) 74 | .map(|it| env.auto_local(it))?; 75 | let jlist = JList::from_env(&mut env, &locators)?; 76 | for value in hello.locators() { 77 | let locator = env.new_string(value.as_str())?; 78 | jlist.add(&mut env, &locator)?; 79 | } 80 | env.call_method( 81 | &callback_global_ref, 82 | "run", 83 | "(I[BLjava/util/List;)V", 84 | &[ 85 | JValue::from(whatami), 86 | JValue::from(&zenoh_id), 87 | JValue::from(&locators), 88 | ], 89 | )?; 90 | Ok(()) 91 | }() 92 | .map_err(|err| tracing::error!("Error while scouting: ${err}")); 93 | }) 94 | .wait() 95 | .map(|scout| Arc::into_raw(Arc::new(scout))) 96 | .map_err(|err| zerror!(err)) 97 | }() 98 | .unwrap_or_else(|err| { 99 | throw_exception!(env, err); 100 | null() 101 | }) 102 | } 103 | 104 | /// Frees the scout. 105 | #[no_mangle] 106 | #[allow(non_snake_case)] 107 | pub(crate) unsafe extern "C" fn Java_io_zenoh_jni_JNIScout_00024Companion_freePtrViaJNI( 108 | _env: JNIEnv, 109 | _: JClass, 110 | scout_ptr: *const Scout<()>, 111 | ) { 112 | Arc::from_raw(scout_ptr); 113 | } 114 | -------------------------------------------------------------------------------- /zenoh-jni/src/subscriber.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | use std::sync::Arc; 16 | 17 | use jni::{objects::JClass, JNIEnv}; 18 | use zenoh::pubsub::Subscriber; 19 | 20 | /// Frees the [Subscriber]. 21 | /// 22 | /// # Parameters: 23 | /// - `_env`: The JNI environment. 24 | /// - `_class`: The JNI class. 25 | /// - `subscriber_ptr`: The raw pointer to the Zenoh subscriber ([Subscriber]). 26 | /// 27 | /// # Safety: 28 | /// - The function is marked as unsafe due to raw pointer manipulation. 29 | /// - It assumes that the provided subscriber pointer is valid and has not been modified or freed. 30 | /// - The function takes ownership of the raw pointer and releases the associated memory. 31 | /// - After calling this function, the subscriber pointer becomes invalid and should not be used anymore. 32 | /// 33 | #[no_mangle] 34 | #[allow(non_snake_case)] 35 | pub(crate) unsafe extern "C" fn Java_io_zenoh_jni_JNISubscriber_freePtrViaJNI( 36 | _env: JNIEnv, 37 | _: JClass, 38 | subscriber_ptr: *const Subscriber<()>, 39 | ) { 40 | Arc::from_raw(subscriber_ptr); 41 | } 42 | -------------------------------------------------------------------------------- /zenoh-jni/src/zenoh_id.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2023 ZettaScale Technology 3 | // 4 | // This program and the accompanying materials are made available under the 5 | // terms of the Eclipse Public License 2.0 which is available at 6 | // http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | // which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | // 9 | // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | // 11 | // Contributors: 12 | // ZettaScale Zenoh Team, 13 | // 14 | 15 | use crate::{errors::ZResult, throw_exception, utils::decode_byte_array, zerror}; 16 | use jni::{ 17 | objects::{JByteArray, JClass, JString}, 18 | sys::jstring, 19 | JNIEnv, 20 | }; 21 | use zenoh::session::ZenohId; 22 | 23 | /// Returns the string representation of a ZenohID. 24 | #[no_mangle] 25 | #[allow(non_snake_case)] 26 | pub extern "C" fn Java_io_zenoh_jni_JNIZenohId_toStringViaJNI( 27 | mut env: JNIEnv, 28 | _class: JClass, 29 | zenoh_id: JByteArray, 30 | ) -> jstring { 31 | || -> ZResult { 32 | let bytes = decode_byte_array(&env, zenoh_id)?; 33 | let zenohid = ZenohId::try_from(bytes.as_slice()).map_err(|err| zerror!(err))?; 34 | env.new_string(zenohid.to_string()) 35 | .map_err(|err| zerror!(err)) 36 | }() 37 | .unwrap_or_else(|err| { 38 | throw_exception!(env, err); 39 | JString::default() 40 | }) 41 | .as_raw() 42 | } 43 | --------------------------------------------------------------------------------